From 8dd16259287f58f9273002717ec4d27e97127719 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:43:14 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- .../tests/webgpu/common/framework/fixture.js | 15 +- .../tests/webgpu/common/framework/test_config.js | 20 +- .../tests/webgpu/common/internal/file_loader.js | 2 + .../webgpu/common/internal/logging/log_message.js | 51 +- .../tests/webgpu/common/internal/logging/logger.js | 7 +- .../tests/webgpu/common/internal/logging/result.js | 32 +- .../common/internal/logging/test_case_recorder.js | 8 +- .../tests/webgpu/common/internal/query/compare.js | 5 +- .../webgpu/common/internal/query/parseQuery.js | 43 +- .../tests/webgpu/common/internal/query/query.js | 6 +- .../tests/webgpu/common/internal/test_group.js | 10 +- .../webgpu/common/internal/test_suite_listing.js | 2 +- .../mozilla/tests/webgpu/common/internal/tree.js | 5 + .../tests/webgpu/common/internal/version.js | 2 +- .../webgpu/common/internal/websocket_logger.js | 17 +- .../tests/webgpu/common/runtime/helper/options.js | 53 +- .../common/runtime/helper/test_worker-worker.js | 51 +- .../webgpu/common/runtime/helper/test_worker.js | 192 ++- .../webgpu/common/runtime/helper/utils_worker.js | 35 + .../common/runtime/helper/wrap_for_worker.js | 54 + .../mozilla/tests/webgpu/common/runtime/wpt.js | 18 +- .../mozilla/tests/webgpu/common/util/crc32.js | 57 + .../tests/webgpu/common/util/parse_imports.js | 36 + .../mozilla/tests/webgpu/common/util/util.js | 7 +- .../mozilla/tests/webgpu/cts/idl/exposed.http.html | 13 + .../tests/webgpu/cts/idl/exposed.https.html | 13 + .../web_platform/reftests/canvas_clear.https.html | 12 + .../canvas_colorspace_bgra8unorm.https.html | 23 + .../canvas_colorspace_rgba16float.https.html | 23 + .../canvas_colorspace_rgba8unorm.https.html | 23 + .../canvas_complex_bgra8unorm_copy.https.html | 24 + .../canvas_complex_bgra8unorm_draw.https.html | 24 + .../canvas_complex_rgba16float_copy.https.html | 24 + .../canvas_complex_rgba16float_draw.https.html | 24 + .../canvas_complex_rgba16float_store.https.html | 24 + .../canvas_complex_rgba8unorm_copy.https.html | 24 + .../canvas_complex_rgba8unorm_draw.https.html | 24 + .../canvas_complex_rgba8unorm_store.https.html | 24 + ...mposite_alpha_bgra8unorm_opaque_copy.https.html | 21 + ...mposite_alpha_bgra8unorm_opaque_draw.https.html | 21 + ..._alpha_bgra8unorm_premultiplied_copy.https.html | 22 + ..._alpha_bgra8unorm_premultiplied_draw.https.html | 22 + ...posite_alpha_rgba16float_opaque_copy.https.html | 21 + ...posite_alpha_rgba16float_opaque_draw.https.html | 21 + ...alpha_rgba16float_premultiplied_copy.https.html | 22 + ...alpha_rgba16float_premultiplied_draw.https.html | 22 + ...mposite_alpha_rgba8unorm_opaque_copy.https.html | 21 + ...mposite_alpha_rgba8unorm_opaque_draw.https.html | 21 + ..._alpha_rgba8unorm_premultiplied_copy.https.html | 22 + ..._alpha_rgba8unorm_premultiplied_draw.https.html | 22 + .../reftests/canvas_image_rendering.https.html | 15 + .../reftests/delay_get_texture.https.html | 10 + .../reftests/ref/canvas_clear-ref.html | 22 + .../reftests/ref/canvas_colorspace-ref.html | 17 + .../reftests/ref/canvas_complex-ref.html | 26 + .../ref/canvas_composite_alpha_opaque-ref.html | 26 + .../canvas_composite_alpha_premultiplied-ref.html | 26 + .../reftests/ref/canvas_image_rendering-ref.html | 25 + .../reftests/ref/delay_get_texture-ref.html | 17 + .../reftests/ref/resize_observer-ref.html | 90 ++ .../reftests/resize_observer.https.html | 24 + .../operation/adapter/requestDevice/cts.https.html | 1 + .../texture/readonly_depth_stencil/cts.https.html | 36 + .../webgpu/api/operation/reflection/cts.https.html | 3 + .../rendering/3d_texture_slices/cts.https.html | 38 + .../storage_texture/read_only/cts.https.html | 36 + .../storage_texture/read_write/cts.https.html | 36 + .../features/query_types/cts.https.html | 2 +- .../maxBindGroupsPlusVertexBuffers/cts.https.html | 37 + .../api/validation/compute_pipeline/cts.https.html | 1 + .../createRenderBundleEncoder/cts.https.html | 1 - .../pipeline_bind_group_compat/cts.https.html | 2 + .../encoding/queries/general/cts.https.html | 6 +- .../validation/layout_shader_compat/cts.https.html | 36 + .../queue/destroyed/query_set/cts.https.html | 2 +- .../render_pass_descriptor/cts.https.html | 4 + .../render_pipeline/fragment_state/cts.https.html | 1 + .../validation/render_pipeline/misc/cts.https.html | 1 + .../resource_compatibility/cts.https.html | 36 + .../shader_module/entry_point/cts.https.html | 3 + .../texture/bgra8unorm_storage/cts.https.html | 2 - .../api/validation/createBindGroup/cts.https.html | 36 + .../createBindGroupLayout/cts.https.html | 36 + .../cmds/copyTextureToTexture/cts.https.html | 37 + .../depth_stencil_state/cts.https.html | 36 + .../render_pipeline/shader_module/cts.https.html | 4 + .../texture/createTexture/cts.https.html | 4 + .../cts/webgpu/idl/constructable/cts.https.html | 38 + .../cts/webgpu/print_environment/cts.https.html | 36 + .../expression/access/array/index/cts.https.html | 40 + .../expression/access/matrix/index/cts.https.html | 39 + .../access/structure/index/cts.https.html | 43 + .../access/vector/components/cts.https.html | 37 + .../expression/access/vector/index/cts.https.html | 37 + .../af_matrix_matrix_multiplication/cts.https.html | 36 + .../af_matrix_scalar_multiplication/cts.https.html | 37 + .../af_matrix_vector_multiplication/cts.https.html | 37 + .../expression/binary/ai_arithmetic/cts.https.html | 50 + .../expression/binary/ai_comparison/cts.https.html | 41 + .../expression/call/builtin/bitcast/cts.https.html | 10 + .../call/builtin/distance/cts.https.html | 3 + .../expression/call/builtin/dot/cts.https.html | 16 +- .../call/builtin/dot4I8Packed/cts.https.html | 36 + .../call/builtin/dot4U8Packed/cts.https.html | 36 + .../call/builtin/faceForward/cts.https.html | 4 +- .../expression/call/builtin/frexp/cts.https.html | 8 + .../expression/call/builtin/length/cts.https.html | 3 + .../call/builtin/normalize/cts.https.html | 4 +- .../call/builtin/pack4xI8/cts.https.html | 36 + .../call/builtin/pack4xI8Clamp/cts.https.html | 36 + .../call/builtin/pack4xU8/cts.https.html | 36 + .../call/builtin/pack4xU8Clamp/cts.https.html | 36 + .../expression/call/builtin/reflect/cts.https.html | 4 +- .../expression/call/builtin/refract/cts.https.html | 4 +- .../call/builtin/textureDimension/cts.https.html | 39 - .../call/builtin/textureDimensions/cts.https.html | 39 + .../call/builtin/textureSample/cts.https.html | 2 +- .../call/builtin/textureSampleBias/cts.https.html | 2 - .../builtin/textureSampleCompare/cts.https.html | 2 - .../call/builtin/unpack4xI8/cts.https.html | 36 + .../call/builtin/unpack4xU8/cts.https.html | 36 + .../builtin/workgroupUniformLoad/cts.https.html | 36 + .../expression/call/user/ptr_params/cts.https.html | 44 + .../expression/constructor/non_zero/cts.https.html | 51 + .../constructor/zero_value/cts.https.html | 40 + .../execution/expression/precedence/cts.https.html | 36 + .../address_of_and_indirection/cts.https.html | 38 + .../expression/unary/ai_arithmetic/cts.https.html | 36 + .../expression/unary/ai_assignment/cts.https.html | 38 + .../expression/unary/ai_complement/cts.https.html | 36 + .../expression/unary/f16_conversion/cts.https.html | 3 + .../expression/unary/i32_conversion/cts.https.html | 2 + .../expression/unary/u32_conversion/cts.https.html | 1 + .../execution/flow_control/call/cts.https.html | 4 + .../execution/flow_control/for/cts.https.html | 2 + .../execution/flow_control/loop/cts.https.html | 2 + .../execution/flow_control/switch/cts.https.html | 1 + .../execution/flow_control/while/cts.https.html | 2 + .../shader/execution/memory_layout/cts.https.html | 37 + .../cts.https.html | 36 + .../shader_io/fragment_builtins/cts.https.html | 41 + .../execution/shader_io/user_io/cts.https.html | 36 + .../shader_io/workgroup_size/cts.https.html | 36 + .../webgpu/shader/execution/stage/cts.https.html | 37 + .../execution/statement/compound/cts.https.html | 36 + .../execution/statement/discard/cts.https.html | 41 + .../decl/compound_statement/cts.https.html | 37 + .../shader/validation/decl/const/cts.https.html | 3 + .../context_dependent_resolution/cts.https.html | 44 + .../shader/validation/decl/let/cts.https.html | 38 + .../shader/validation/decl/override/cts.https.html | 4 + .../shader/validation/decl/var/cts.https.html | 46 + .../expression/binary/add_sub_mul/cts.https.html | 38 + .../expression/binary/and_or_xor/cts.https.html | 37 + .../expression/binary/bitwise_shift/cts.https.html | 4 +- .../expression/binary/comparison/cts.https.html | 37 + .../expression/binary/div_rem/cts.https.html | 38 + .../expression/call/builtin/abs/cts.https.html | 1 + .../expression/call/builtin/acos/cts.https.html | 1 + .../expression/call/builtin/acosh/cts.https.html | 1 + .../expression/call/builtin/all/cts.https.html | 38 + .../expression/call/builtin/any/cts.https.html | 38 + .../call/builtin/arrayLength/cts.https.html | 38 + .../expression/call/builtin/asin/cts.https.html | 1 + .../expression/call/builtin/asinh/cts.https.html | 1 + .../expression/call/builtin/atan/cts.https.html | 1 + .../expression/call/builtin/atan2/cts.https.html | 6 +- .../expression/call/builtin/atanh/cts.https.html | 1 + .../expression/call/builtin/atomics/cts.https.html | 3 + .../call/builtin/barriers/cts.https.html | 37 + .../expression/call/builtin/cos/cts.https.html | 2 + .../expression/call/builtin/cosh/cts.https.html | 3 +- .../call/builtin/countLeadingZeros/cts.https.html | 39 + .../call/builtin/countOneBits/cts.https.html | 39 + .../call/builtin/countTrailingZeros/cts.https.html | 39 + .../expression/call/builtin/cross/cts.https.html | 38 + .../expression/call/builtin/degrees/cts.https.html | 2 + .../call/builtin/derivatives/cts.https.html | 37 + .../call/builtin/determinant/cts.https.html | 38 + .../call/builtin/distance/cts.https.html | 38 + .../call/builtin/dot4I8Packed/cts.https.html | 39 + .../call/builtin/dot4U8Packed/cts.https.html | 39 + .../expression/call/builtin/exp/cts.https.html | 3 +- .../expression/call/builtin/exp2/cts.https.html | 3 +- .../call/builtin/extractBits/cts.https.html | 39 + .../call/builtin/faceForward/cts.https.html | 38 + .../call/builtin/firstLeadingBit/cts.https.html | 39 + .../call/builtin/firstTrailingBit/cts.https.html | 39 + .../expression/call/builtin/floor/cts.https.html | 39 + .../expression/call/builtin/fract/cts.https.html | 38 + .../expression/call/builtin/frexp/cts.https.html | 38 + .../call/builtin/insertBits/cts.https.html | 40 + .../call/builtin/inverseSqrt/cts.https.html | 3 +- .../expression/call/builtin/log/cts.https.html | 2 + .../expression/call/builtin/log2/cts.https.html | 2 + .../expression/call/builtin/max/cts.https.html | 38 + .../expression/call/builtin/min/cts.https.html | 38 + .../call/builtin/normalize/cts.https.html | 39 + .../call/builtin/pack2x16snorm/cts.https.html | 38 + .../call/builtin/pack2x16unorm/cts.https.html | 38 + .../call/builtin/pack4x8snorm/cts.https.html | 38 + .../call/builtin/pack4x8unorm/cts.https.html | 38 + .../call/builtin/pack4xI8/cts.https.html | 39 + .../call/builtin/pack4xI8Clamp/cts.https.html | 39 + .../call/builtin/pack4xU8/cts.https.html | 39 + .../call/builtin/pack4xU8Clamp/cts.https.html | 39 + .../call/builtin/quantizeToF16/cts.https.html | 38 + .../expression/call/builtin/radians/cts.https.html | 2 + .../expression/call/builtin/reflect/cts.https.html | 38 + .../call/builtin/reverseBits/cts.https.html | 39 + .../expression/call/builtin/select/cts.https.html | 39 + .../expression/call/builtin/sign/cts.https.html | 3 +- .../expression/call/builtin/sin/cts.https.html | 2 + .../expression/call/builtin/sinh/cts.https.html | 3 +- .../call/builtin/smoothstep/cts.https.html | 38 + .../expression/call/builtin/sqrt/cts.https.html | 2 + .../expression/call/builtin/step/cts.https.html | 38 + .../expression/call/builtin/tan/cts.https.html | 3 +- .../expression/call/builtin/tanh/cts.https.html | 38 + .../call/builtin/textureGather/cts.https.html | 41 + .../builtin/textureGatherCompare/cts.https.html | 40 + .../call/builtin/textureLoad/cts.https.html | 41 + .../call/builtin/textureSample/cts.https.html | 40 + .../textureSampleBaseClampToEdge/cts.https.html | 36 + .../call/builtin/textureSampleBias/cts.https.html | 41 + .../builtin/textureSampleCompare/cts.https.html | 41 + .../textureSampleCompareLevel/cts.https.html | 40 + .../call/builtin/textureSampleGrad/cts.https.html | 41 + .../call/builtin/textureSampleLevel/cts.https.html | 40 + .../call/builtin/textureStore/cts.https.html | 38 + .../expression/call/builtin/trunc/cts.https.html | 38 + .../call/builtin/unpack2x16float/cts.https.html | 38 + .../call/builtin/unpack2x16snorm/cts.https.html | 38 + .../call/builtin/unpack2x16unorm/cts.https.html | 38 + .../call/builtin/unpack4x8snorm/cts.https.html | 38 + .../call/builtin/unpack4x8unorm/cts.https.html | 38 + .../call/builtin/unpack4xI8/cts.https.html | 39 + .../call/builtin/unpack4xU8/cts.https.html | 39 + .../builtin/workgroupUniformLoad/cts.https.html | 37 + .../expression/overload_resolution/cts.https.html | 37 + .../expression/precedence/cts.https.html | 38 + .../address_of_and_indirection/cts.https.html | 38 + .../unary/arithmetic_negation/cts.https.html | 37 + .../unary/bitwise_complement/cts.https.html | 37 + .../unary/logical_negation/cts.https.html | 37 + .../pointer_composite_access/cts.https.html | 37 + .../cts.https.html | 37 + .../functions/alias_analysis/cts.https.html | 9 + .../functions/restrictions/cts.https.html | 4 +- .../validation/parse/break_if/cts.https.html | 37 + .../validation/parse/compound/cts.https.html | 36 + .../validation/parse/continuing/cts.https.html | 36 + .../validation/parse/diagnostic/cts.https.html | 2 + .../validation/parse/must_use/cts.https.html | 1 + .../validation/parse/pipeline_stage/cts.https.html | 6 +- .../validation/parse/requires/cts.https.html | 37 + .../validation/parse/semicolon/cts.https.html | 2 + .../parse/shadow_builtins/cts.https.html | 44 + .../parse/statement_behavior/cts.https.html | 39 + .../validation/shader_io/binding/cts.https.html | 1 - .../validation/shader_io/group/cts.https.html | 1 - .../shader_io/layout_constraints/cts.https.html | 36 + .../validation/shader_io/locations/cts.https.html | 1 + .../validation/shader_io/size/cts.https.html | 1 + .../shader/validation/types/alias/cts.https.html | 2 + .../shader/validation/types/array/cts.https.html | 37 + .../shader/validation/types/atomics/cts.https.html | 38 + .../shader/validation/types/matrix/cts.https.html | 37 + .../validation/types/textures/cts.https.html | 42 + .../texture/color_space_conversions/cts.https.html | 36 + .../external_texture/video/cts.https.html | 2 +- .../web_platform/worker/worker/cts.https.html | 4 +- .../api/operation/adapter/requestAdapter.worker.js | 6 + .../operation/adapter/requestAdapterInfo.worker.js | 6 + .../api/operation/adapter/requestDevice.worker.js | 6 + .../webworker/api/operation/buffers/map.worker.js | 6 + .../operation/buffers/map_ArrayBuffer.worker.js | 6 + .../api/operation/buffers/map_detach.worker.js | 6 + .../api/operation/buffers/map_oom.worker.js | 6 + .../api/operation/buffers/threading.worker.js | 6 + .../api/operation/command_buffer/basic.worker.js | 6 + .../operation/command_buffer/clearBuffer.worker.js | 6 + .../command_buffer/copyBufferToBuffer.worker.js | 6 + .../command_buffer/copyTextureToTexture.worker.js | 6 + .../operation/command_buffer/image_copy.worker.js | 6 + .../programmable/state_tracking.worker.js | 6 + .../queries/occlusionQuery.worker.js | 6 + .../command_buffer/render/dynamic_state.worker.js | 6 + .../command_buffer/render/state_tracking.worker.js | 6 + .../api/operation/compute/basic.worker.js | 6 + .../compute_pipeline/entry_point_name.worker.js | 6 + .../operation/compute_pipeline/overrides.worker.js | 6 + .../webworker/api/operation/device/lost.worker.js | 6 + .../cts/webworker/api/operation/labels.worker.js | 6 + .../memory_sync/buffer/multiple_buffers.worker.js | 6 + .../memory_sync/buffer/single_buffer.worker.js | 6 + .../texture/readonly_depth_stencil.worker.js | 6 + .../memory_sync/texture/same_subresource.worker.js | 6 + .../api/operation/onSubmittedWorkDone.worker.js | 6 + .../operation/pipeline/default_layout.worker.js | 6 + .../api/operation/queue/writeBuffer.worker.js | 6 + .../webworker/api/operation/reflection.worker.js | 6 + .../operation/render_pass/clear_value.worker.js | 6 + .../api/operation/render_pass/resolve.worker.js | 6 + .../api/operation/render_pass/storeOp.worker.js | 6 + .../api/operation/render_pass/storeop2.worker.js | 6 + .../render_pipeline/culling_tests.worker.js | 6 + .../operation/render_pipeline/overrides.worker.js | 6 + .../pipeline_output_targets.worker.js | 6 + .../render_pipeline/primitive_topology.worker.js | 6 + .../render_pipeline/sample_mask.worker.js | 6 + .../vertex_only_render_pipeline.worker.js | 6 + .../rendering/3d_texture_slices.worker.js | 6 + .../api/operation/rendering/basic.worker.js | 6 + .../rendering/color_target_state.worker.js | 6 + .../api/operation/rendering/depth.worker.js | 6 + .../api/operation/rendering/depth_bias.worker.js | 6 + .../operation/rendering/depth_clip_clamp.worker.js | 6 + .../api/operation/rendering/draw.worker.js | 6 + .../operation/rendering/indirect_draw.worker.js | 6 + .../rendering/robust_access_index.worker.js | 6 + .../api/operation/rendering/stencil.worker.js | 6 + .../api/operation/resource_init/buffer.worker.js | 6 + .../operation/resource_init/texture_zero.worker.js | 6 + .../api/operation/sampling/anisotropy.worker.js | 6 + .../api/operation/sampling/filter_mode.worker.js | 6 + .../api/operation/sampling/lod_clamp.worker.js | 6 + .../shader_module/compilation_info.worker.js | 6 + .../operation/storage_texture/read_only.worker.js | 6 + .../operation/storage_texture/read_write.worker.js | 6 + .../texture_view/format_reinterpretation.worker.js | 6 + .../api/operation/texture_view/read.worker.js | 6 + .../api/operation/texture_view/write.worker.js | 6 + .../api/operation/uncapturederror.worker.js | 6 + .../operation/vertex_state/correctness.worker.js | 6 + .../operation/vertex_state/index_format.worker.js | 6 + .../api/validation/buffer/create.worker.js | 6 + .../api/validation/buffer/destroy.worker.js | 6 + .../api/validation/buffer/mapping.worker.js | 6 + .../api/validation/buffer/threading.worker.js | 6 + .../features/query_types.worker.js | 6 + .../features/texture_formats.worker.js | 6 + .../limits/maxBindGroups.worker.js | 6 + .../maxBindGroupsPlusVertexBuffers.worker.js | 6 + .../limits/maxBindingsPerBindGroup.worker.js | 6 + .../limits/maxBufferSize.worker.js | 6 + .../maxColorAttachmentBytesPerSample.worker.js | 6 + .../limits/maxColorAttachments.worker.js | 6 + .../maxComputeInvocationsPerWorkgroup.worker.js | 6 + .../limits/maxComputeWorkgroupSizeX.worker.js | 6 + .../limits/maxComputeWorkgroupSizeY.worker.js | 6 + .../limits/maxComputeWorkgroupSizeZ.worker.js | 6 + .../maxComputeWorkgroupStorageSize.worker.js | 6 + .../maxComputeWorkgroupsPerDimension.worker.js | 6 + ...ynamicStorageBuffersPerPipelineLayout.worker.js | 6 + ...ynamicUniformBuffersPerPipelineLayout.worker.js | 6 + .../limits/maxInterStageShaderComponents.worker.js | 6 + .../limits/maxInterStageShaderVariables.worker.js | 6 + .../maxSampledTexturesPerShaderStage.worker.js | 6 + .../limits/maxSamplersPerShaderStage.worker.js | 6 + .../limits/maxStorageBufferBindingSize.worker.js | 6 + .../maxStorageBuffersPerShaderStage.worker.js | 6 + .../maxStorageTexturesPerShaderStage.worker.js | 6 + .../limits/maxTextureArrayLayers.worker.js | 6 + .../limits/maxTextureDimension1D.worker.js | 6 + .../limits/maxTextureDimension2D.worker.js | 6 + .../limits/maxTextureDimension3D.worker.js | 6 + .../limits/maxUniformBufferBindingSize.worker.js | 6 + .../maxUniformBuffersPerShaderStage.worker.js | 6 + .../limits/maxVertexAttributes.worker.js | 6 + .../limits/maxVertexBufferArrayStride.worker.js | 6 + .../limits/maxVertexBuffers.worker.js | 6 + .../minStorageBufferOffsetAlignment.worker.js | 6 + .../minUniformBufferOffsetAlignment.worker.js | 6 + .../api/validation/compute_pipeline.worker.js | 6 + .../api/validation/createBindGroup.worker.js | 6 + .../api/validation/createBindGroupLayout.worker.js | 6 + .../api/validation/createPipelineLayout.worker.js | 6 + .../api/validation/createSampler.worker.js | 6 + .../api/validation/createTexture.worker.js | 6 + .../webworker/api/validation/createView.worker.js | 6 + .../webworker/api/validation/debugMarker.worker.js | 6 + .../validation/encoding/beginComputePass.worker.js | 6 + .../validation/encoding/beginRenderPass.worker.js | 6 + .../validation/encoding/cmds/clearBuffer.worker.js | 6 + .../encoding/cmds/compute_pass.worker.js | 6 + .../encoding/cmds/copyBufferToBuffer.worker.js | 6 + .../encoding/cmds/copyTextureToTexture.worker.js | 6 + .../api/validation/encoding/cmds/debug.worker.js | 6 + .../encoding/cmds/index_access.worker.js | 6 + .../validation/encoding/cmds/render/draw.worker.js | 6 + .../encoding/cmds/render/dynamic_state.worker.js | 6 + .../encoding/cmds/render/indirect_draw.worker.js | 6 + .../encoding/cmds/render/setIndexBuffer.worker.js | 6 + .../encoding/cmds/render/setPipeline.worker.js | 6 + .../encoding/cmds/render/setVertexBuffer.worker.js | 6 + .../encoding/cmds/render/state_tracking.worker.js | 6 + .../validation/encoding/cmds/render_pass.worker.js | 6 + .../encoding/cmds/setBindGroup.worker.js | 6 + .../encoding/createRenderBundleEncoder.worker.js | 6 + .../encoding/encoder_open_state.worker.js | 6 + .../validation/encoding/encoder_state.worker.js | 6 + .../pipeline_bind_group_compat.worker.js | 6 + .../encoding/queries/begin_end.worker.js | 6 + .../validation/encoding/queries/general.worker.js | 6 + .../encoding/queries/resolveQuerySet.worker.js | 6 + .../validation/encoding/render_bundle.worker.js | 6 + .../webworker/api/validation/error_scope.worker.js | 6 + .../api/validation/getBindGroupLayout.worker.js | 6 + .../gpu_external_texture_expiration.worker.js | 6 + .../validation/image_copy/buffer_related.worker.js | 6 + .../image_copy/buffer_texture_copies.worker.js | 6 + .../validation/image_copy/layout_related.worker.js | 6 + .../image_copy/texture_related.worker.js | 6 + .../api/validation/layout_shader_compat.worker.js | 6 + .../api/validation/query_set/create.worker.js | 6 + .../api/validation/query_set/destroy.worker.js | 6 + .../api/validation/queue/buffer_mapped.worker.js | 6 + .../CopyExternalImageToTexture.worker.js | 6 + .../validation/queue/destroyed/buffer.worker.js | 6 + .../validation/queue/destroyed/query_set.worker.js | 6 + .../validation/queue/destroyed/texture.worker.js | 6 + .../api/validation/queue/submit.worker.js | 6 + .../api/validation/queue/writeBuffer.worker.js | 6 + .../api/validation/queue/writeTexture.worker.js | 6 + .../render_pass/attachment_compatibility.worker.js | 6 + .../render_pass/render_pass_descriptor.worker.js | 6 + .../api/validation/render_pass/resolve.worker.js | 6 + .../render_pipeline/depth_stencil_state.worker.js | 6 + .../render_pipeline/fragment_state.worker.js | 6 + .../render_pipeline/inter_stage.worker.js | 6 + .../api/validation/render_pipeline/misc.worker.js | 6 + .../render_pipeline/multisample_state.worker.js | 6 + .../validation/render_pipeline/overrides.worker.js | 6 + .../render_pipeline/primitive_state.worker.js | 6 + .../resource_compatibility.worker.js | 6 + .../render_pipeline/shader_module.worker.js | 6 + .../render_pipeline/vertex_state.worker.js | 6 + .../buffer/in_pass_encoder.worker.js | 6 + .../resource_usages/buffer/in_pass_misc.worker.js | 6 + .../texture/in_pass_encoder.worker.js | 6 + .../texture/in_render_common.worker.js | 6 + .../texture/in_render_misc.worker.js | 6 + .../validation/shader_module/entry_point.worker.js | 6 + .../validation/shader_module/overrides.worker.js | 6 + .../validation/state/device_lost/destroy.worker.js | 6 + .../texture/bgra8unorm_storage.worker.js | 6 + .../api/validation/texture/destroy.worker.js | 6 + .../texture/float32_filterable.worker.js | 6 + .../texture/rg11b10ufloat_renderable.worker.js | 6 + .../api/validation/createBindGroup.worker.js | 6 + .../api/validation/createBindGroupLayout.worker.js | 6 + .../encoding/cmds/copyTextureToBuffer.worker.js | 6 + .../encoding/cmds/copyTextureToTexture.worker.js | 6 + .../pipeline_bind_group_compat.worker.js | 6 + .../render_pipeline/depth_stencil_state.worker.js | 6 + .../render_pipeline/fragment_state.worker.js | 6 + .../render_pipeline/shader_module.worker.js | 6 + .../render_pipeline/vertex_state.worker.js | 6 + .../api/validation/texture/createTexture.worker.js | 6 + .../api/validation/texture/cubeArray.worker.js | 6 + .../tests/webgpu/cts/webworker/examples.worker.js | 6 + .../cts/webworker/idl/constants/flags.worker.js | 6 + .../cts/webworker/idl/constructable.worker.js | 6 + .../cts/webworker/print_environment.worker.js | 6 + .../expression/access/array/index.worker.js | 6 + .../expression/access/matrix/index.worker.js | 6 + .../expression/access/structure/index.worker.js | 6 + .../expression/access/vector/components.worker.js | 6 + .../expression/access/vector/index.worker.js | 6 + .../expression/binary/af_addition.worker.js | 6 + .../expression/binary/af_comparison.worker.js | 6 + .../expression/binary/af_division.worker.js | 6 + .../expression/binary/af_matrix_addition.worker.js | 6 + .../af_matrix_matrix_multiplication.worker.js | 6 + .../af_matrix_scalar_multiplication.worker.js | 6 + .../binary/af_matrix_subtraction.worker.js | 6 + .../af_matrix_vector_multiplication.worker.js | 6 + .../expression/binary/af_multiplication.worker.js | 6 + .../expression/binary/af_remainder.worker.js | 6 + .../expression/binary/af_subtraction.worker.js | 6 + .../expression/binary/ai_arithmetic.worker.js | 6 + .../expression/binary/ai_comparison.worker.js | 6 + .../execution/expression/binary/bitwise.worker.js | 6 + .../expression/binary/bitwise_shift.worker.js | 6 + .../expression/binary/bool_logical.worker.js | 6 + .../expression/binary/f16_addition.worker.js | 6 + .../expression/binary/f16_comparison.worker.js | 6 + .../expression/binary/f16_division.worker.js | 6 + .../binary/f16_matrix_addition.worker.js | 6 + .../f16_matrix_matrix_multiplication.worker.js | 6 + .../f16_matrix_scalar_multiplication.worker.js | 6 + .../binary/f16_matrix_subtraction.worker.js | 6 + .../f16_matrix_vector_multiplication.worker.js | 6 + .../expression/binary/f16_multiplication.worker.js | 6 + .../expression/binary/f16_remainder.worker.js | 6 + .../expression/binary/f16_subtraction.worker.js | 6 + .../expression/binary/f32_addition.worker.js | 6 + .../expression/binary/f32_comparison.worker.js | 6 + .../expression/binary/f32_division.worker.js | 6 + .../binary/f32_matrix_addition.worker.js | 6 + .../f32_matrix_matrix_multiplication.worker.js | 6 + .../f32_matrix_scalar_multiplication.worker.js | 6 + .../binary/f32_matrix_subtraction.worker.js | 6 + .../f32_matrix_vector_multiplication.worker.js | 6 + .../expression/binary/f32_multiplication.worker.js | 6 + .../expression/binary/f32_remainder.worker.js | 6 + .../expression/binary/f32_subtraction.worker.js | 6 + .../expression/binary/i32_arithmetic.worker.js | 6 + .../expression/binary/i32_comparison.worker.js | 6 + .../expression/binary/u32_arithmetic.worker.js | 6 + .../expression/binary/u32_comparison.worker.js | 6 + .../expression/call/builtin/abs.worker.js | 6 + .../expression/call/builtin/acos.worker.js | 6 + .../expression/call/builtin/acosh.worker.js | 6 + .../expression/call/builtin/all.worker.js | 6 + .../expression/call/builtin/any.worker.js | 6 + .../expression/call/builtin/arrayLength.worker.js | 6 + .../expression/call/builtin/asin.worker.js | 6 + .../expression/call/builtin/asinh.worker.js | 6 + .../expression/call/builtin/atan.worker.js | 6 + .../expression/call/builtin/atan2.worker.js | 6 + .../expression/call/builtin/atanh.worker.js | 6 + .../call/builtin/atomics/atomicAdd.worker.js | 6 + .../call/builtin/atomics/atomicAnd.worker.js | 6 + .../atomics/atomicCompareExchangeWeak.worker.js | 6 + .../call/builtin/atomics/atomicExchange.worker.js | 6 + .../call/builtin/atomics/atomicLoad.worker.js | 6 + .../call/builtin/atomics/atomicMax.worker.js | 6 + .../call/builtin/atomics/atomicMin.worker.js | 6 + .../call/builtin/atomics/atomicOr.worker.js | 6 + .../call/builtin/atomics/atomicStore.worker.js | 6 + .../call/builtin/atomics/atomicSub.worker.js | 6 + .../call/builtin/atomics/atomicXor.worker.js | 6 + .../expression/call/builtin/bitcast.worker.js | 6 + .../expression/call/builtin/ceil.worker.js | 6 + .../expression/call/builtin/clamp.worker.js | 6 + .../expression/call/builtin/cos.worker.js | 6 + .../expression/call/builtin/cosh.worker.js | 6 + .../call/builtin/countLeadingZeros.worker.js | 6 + .../expression/call/builtin/countOneBits.worker.js | 6 + .../call/builtin/countTrailingZeros.worker.js | 6 + .../expression/call/builtin/cross.worker.js | 6 + .../expression/call/builtin/degrees.worker.js | 6 + .../expression/call/builtin/determinant.worker.js | 6 + .../expression/call/builtin/distance.worker.js | 6 + .../expression/call/builtin/dot.worker.js | 6 + .../expression/call/builtin/dot4I8Packed.worker.js | 6 + .../expression/call/builtin/dot4U8Packed.worker.js | 6 + .../expression/call/builtin/dpdx.worker.js | 6 + .../expression/call/builtin/dpdxCoarse.worker.js | 6 + .../expression/call/builtin/dpdxFine.worker.js | 6 + .../expression/call/builtin/dpdy.worker.js | 6 + .../expression/call/builtin/dpdyCoarse.worker.js | 6 + .../expression/call/builtin/dpdyFine.worker.js | 6 + .../expression/call/builtin/exp.worker.js | 6 + .../expression/call/builtin/exp2.worker.js | 6 + .../expression/call/builtin/extractBits.worker.js | 6 + .../expression/call/builtin/faceForward.worker.js | 6 + .../call/builtin/firstLeadingBit.worker.js | 6 + .../call/builtin/firstTrailingBit.worker.js | 6 + .../expression/call/builtin/floor.worker.js | 6 + .../expression/call/builtin/fma.worker.js | 6 + .../expression/call/builtin/fract.worker.js | 6 + .../expression/call/builtin/frexp.worker.js | 6 + .../expression/call/builtin/fwidth.worker.js | 6 + .../expression/call/builtin/fwidthCoarse.worker.js | 6 + .../expression/call/builtin/fwidthFine.worker.js | 6 + .../expression/call/builtin/insertBits.worker.js | 6 + .../expression/call/builtin/inversesqrt.worker.js | 6 + .../expression/call/builtin/ldexp.worker.js | 6 + .../expression/call/builtin/length.worker.js | 6 + .../expression/call/builtin/log.worker.js | 6 + .../expression/call/builtin/log2.worker.js | 6 + .../expression/call/builtin/max.worker.js | 6 + .../expression/call/builtin/min.worker.js | 6 + .../expression/call/builtin/mix.worker.js | 6 + .../expression/call/builtin/modf.worker.js | 6 + .../expression/call/builtin/normalize.worker.js | 6 + .../call/builtin/pack2x16float.worker.js | 6 + .../call/builtin/pack2x16snorm.worker.js | 6 + .../call/builtin/pack2x16unorm.worker.js | 6 + .../expression/call/builtin/pack4x8snorm.worker.js | 6 + .../expression/call/builtin/pack4x8unorm.worker.js | 6 + .../expression/call/builtin/pack4xI8.worker.js | 6 + .../call/builtin/pack4xI8Clamp.worker.js | 6 + .../expression/call/builtin/pack4xU8.worker.js | 6 + .../call/builtin/pack4xU8Clamp.worker.js | 6 + .../expression/call/builtin/pow.worker.js | 6 + .../call/builtin/quantizeToF16.worker.js | 6 + .../expression/call/builtin/radians.worker.js | 6 + .../expression/call/builtin/reflect.worker.js | 6 + .../expression/call/builtin/refract.worker.js | 6 + .../expression/call/builtin/reverseBits.worker.js | 6 + .../expression/call/builtin/round.worker.js | 6 + .../expression/call/builtin/saturate.worker.js | 6 + .../expression/call/builtin/select.worker.js | 6 + .../expression/call/builtin/sign.worker.js | 6 + .../expression/call/builtin/sin.worker.js | 6 + .../expression/call/builtin/sinh.worker.js | 6 + .../expression/call/builtin/smoothstep.worker.js | 6 + .../expression/call/builtin/sqrt.worker.js | 6 + .../expression/call/builtin/step.worker.js | 6 + .../call/builtin/storageBarrier.worker.js | 6 + .../expression/call/builtin/tan.worker.js | 6 + .../expression/call/builtin/tanh.worker.js | 6 + .../call/builtin/textureDimensions.worker.js | 6 + .../call/builtin/textureGather.worker.js | 6 + .../call/builtin/textureGatherCompare.worker.js | 6 + .../expression/call/builtin/textureLoad.worker.js | 6 + .../call/builtin/textureNumLayers.worker.js | 6 + .../call/builtin/textureNumLevels.worker.js | 6 + .../call/builtin/textureNumSamples.worker.js | 6 + .../call/builtin/textureSample.worker.js | 6 + .../call/builtin/textureSampleBias.worker.js | 6 + .../call/builtin/textureSampleCompare.worker.js | 6 + .../builtin/textureSampleCompareLevel.worker.js | 6 + .../call/builtin/textureSampleGrad.worker.js | 6 + .../call/builtin/textureSampleLevel.worker.js | 6 + .../expression/call/builtin/textureStore.worker.js | 6 + .../expression/call/builtin/transpose.worker.js | 6 + .../expression/call/builtin/trunc.worker.js | 6 + .../call/builtin/unpack2x16float.worker.js | 6 + .../call/builtin/unpack2x16snorm.worker.js | 6 + .../call/builtin/unpack2x16unorm.worker.js | 6 + .../call/builtin/unpack4x8snorm.worker.js | 6 + .../call/builtin/unpack4x8unorm.worker.js | 6 + .../expression/call/builtin/unpack4xI8.worker.js | 6 + .../expression/call/builtin/unpack4xU8.worker.js | 6 + .../call/builtin/workgroupBarrier.worker.js | 6 + .../call/builtin/workgroupUniformLoad.worker.js | 6 + .../expression/call/user/ptr_params.worker.js | 6 + .../expression/constructor/non_zero.worker.js | 6 + .../expression/constructor/zero_value.worker.js | 6 + .../execution/expression/precedence.worker.js | 6 + .../unary/address_of_and_indirection.worker.js | 6 + .../expression/unary/af_arithmetic.worker.js | 6 + .../expression/unary/af_assignment.worker.js | 6 + .../expression/unary/ai_arithmetic.worker.js | 6 + .../expression/unary/ai_assignment.worker.js | 6 + .../expression/unary/ai_complement.worker.js | 6 + .../expression/unary/bool_conversion.worker.js | 6 + .../expression/unary/bool_logical.worker.js | 6 + .../expression/unary/f16_arithmetic.worker.js | 6 + .../expression/unary/f16_conversion.worker.js | 6 + .../expression/unary/f32_arithmetic.worker.js | 6 + .../expression/unary/f32_conversion.worker.js | 6 + .../expression/unary/i32_arithmetic.worker.js | 6 + .../expression/unary/i32_complement.worker.js | 6 + .../expression/unary/i32_conversion.worker.js | 6 + .../expression/unary/u32_complement.worker.js | 6 + .../expression/unary/u32_conversion.worker.js | 6 + .../shader/execution/float_parse.worker.js | 6 + .../shader/execution/flow_control/call.worker.js | 6 + .../execution/flow_control/complex.worker.js | 6 + .../execution/flow_control/eval_order.worker.js | 6 + .../shader/execution/flow_control/for.worker.js | 6 + .../shader/execution/flow_control/if.worker.js | 6 + .../shader/execution/flow_control/loop.worker.js | 6 + .../shader/execution/flow_control/phony.worker.js | 6 + .../shader/execution/flow_control/return.worker.js | 6 + .../shader/execution/flow_control/switch.worker.js | 6 + .../shader/execution/flow_control/while.worker.js | 6 + .../shader/execution/memory_layout.worker.js | 6 + .../execution/memory_model/adjacent.worker.js | 6 + .../execution/memory_model/atomicity.worker.js | 6 + .../execution/memory_model/barrier.worker.js | 6 + .../execution/memory_model/coherence.worker.js | 6 + .../texture_intra_invocation_coherence.worker.js | 6 + .../shader/execution/memory_model/weak.worker.js | 6 + .../webworker/shader/execution/padding.worker.js | 6 + .../shader/execution/robust_access.worker.js | 6 + .../execution/robust_access_vertex.worker.js | 6 + .../execution/shader_io/compute_builtins.worker.js | 6 + .../shader_io/fragment_builtins.worker.js | 6 + .../execution/shader_io/shared_structs.worker.js | 6 + .../shader/execution/shader_io/user_io.worker.js | 6 + .../execution/shader_io/workgroup_size.worker.js | 6 + .../webworker/shader/execution/shadow.worker.js | 6 + .../cts/webworker/shader/execution/stage.worker.js | 6 + .../shader/execution/statement/compound.worker.js | 6 + .../shader/execution/statement/discard.worker.js | 6 + .../statement/increment_decrement.worker.js | 6 + .../webworker/shader/execution/zero_init.worker.js | 6 + .../validation/const_assert/const_assert.worker.js | 6 + .../validation/decl/compound_statement.worker.js | 6 + .../shader/validation/decl/const.worker.js | 6 + .../decl/context_dependent_resolution.worker.js | 6 + .../webworker/shader/validation/decl/let.worker.js | 6 + .../shader/validation/decl/override.worker.js | 6 + .../shader/validation/decl/ptr_spelling.worker.js | 6 + .../webworker/shader/validation/decl/var.worker.js | 6 + .../validation/decl/var_access_mode.worker.js | 6 + .../validation/expression/access/vector.worker.js | 6 + .../expression/binary/add_sub_mul.worker.js | 6 + .../expression/binary/and_or_xor.worker.js | 6 + .../expression/binary/bitwise_shift.worker.js | 6 + .../expression/binary/comparison.worker.js | 6 + .../validation/expression/binary/div_rem.worker.js | 6 + .../expression/call/builtin/abs.worker.js | 6 + .../expression/call/builtin/acos.worker.js | 6 + .../expression/call/builtin/acosh.worker.js | 6 + .../expression/call/builtin/all.worker.js | 6 + .../expression/call/builtin/any.worker.js | 6 + .../expression/call/builtin/arrayLength.worker.js | 6 + .../expression/call/builtin/asin.worker.js | 6 + .../expression/call/builtin/asinh.worker.js | 6 + .../expression/call/builtin/atan.worker.js | 6 + .../expression/call/builtin/atan2.worker.js | 6 + .../expression/call/builtin/atanh.worker.js | 6 + .../expression/call/builtin/atomics.worker.js | 6 + .../expression/call/builtin/barriers.worker.js | 6 + .../expression/call/builtin/bitcast.worker.js | 6 + .../expression/call/builtin/ceil.worker.js | 6 + .../expression/call/builtin/clamp.worker.js | 6 + .../expression/call/builtin/cos.worker.js | 6 + .../expression/call/builtin/cosh.worker.js | 6 + .../call/builtin/countLeadingZeros.worker.js | 6 + .../expression/call/builtin/countOneBits.worker.js | 6 + .../call/builtin/countTrailingZeros.worker.js | 6 + .../expression/call/builtin/cross.worker.js | 6 + .../expression/call/builtin/degrees.worker.js | 6 + .../expression/call/builtin/derivatives.worker.js | 6 + .../expression/call/builtin/determinant.worker.js | 6 + .../expression/call/builtin/distance.worker.js | 6 + .../expression/call/builtin/dot4I8Packed.worker.js | 6 + .../expression/call/builtin/dot4U8Packed.worker.js | 6 + .../expression/call/builtin/exp.worker.js | 6 + .../expression/call/builtin/exp2.worker.js | 6 + .../expression/call/builtin/extractBits.worker.js | 6 + .../expression/call/builtin/faceForward.worker.js | 6 + .../call/builtin/firstLeadingBit.worker.js | 6 + .../call/builtin/firstTrailingBit.worker.js | 6 + .../expression/call/builtin/floor.worker.js | 6 + .../expression/call/builtin/fract.worker.js | 6 + .../expression/call/builtin/frexp.worker.js | 6 + .../expression/call/builtin/insertBits.worker.js | 6 + .../expression/call/builtin/inverseSqrt.worker.js | 6 + .../expression/call/builtin/length.worker.js | 6 + .../expression/call/builtin/log.worker.js | 6 + .../expression/call/builtin/log2.worker.js | 6 + .../expression/call/builtin/max.worker.js | 6 + .../expression/call/builtin/min.worker.js | 6 + .../expression/call/builtin/modf.worker.js | 6 + .../expression/call/builtin/normalize.worker.js | 6 + .../call/builtin/pack2x16snorm.worker.js | 6 + .../call/builtin/pack2x16unorm.worker.js | 6 + .../expression/call/builtin/pack4x8snorm.worker.js | 6 + .../expression/call/builtin/pack4x8unorm.worker.js | 6 + .../expression/call/builtin/pack4xI8.worker.js | 6 + .../call/builtin/pack4xI8Clamp.worker.js | 6 + .../expression/call/builtin/pack4xU8.worker.js | 6 + .../call/builtin/pack4xU8Clamp.worker.js | 6 + .../call/builtin/quantizeToF16.worker.js | 6 + .../expression/call/builtin/radians.worker.js | 6 + .../expression/call/builtin/reflect.worker.js | 6 + .../expression/call/builtin/reverseBits.worker.js | 6 + .../expression/call/builtin/round.worker.js | 6 + .../expression/call/builtin/saturate.worker.js | 6 + .../expression/call/builtin/select.worker.js | 6 + .../expression/call/builtin/sign.worker.js | 6 + .../expression/call/builtin/sin.worker.js | 6 + .../expression/call/builtin/sinh.worker.js | 6 + .../expression/call/builtin/smoothstep.worker.js | 6 + .../expression/call/builtin/sqrt.worker.js | 6 + .../expression/call/builtin/step.worker.js | 6 + .../expression/call/builtin/tan.worker.js | 6 + .../expression/call/builtin/tanh.worker.js | 6 + .../call/builtin/textureGather.worker.js | 6 + .../call/builtin/textureGatherCompare.worker.js | 6 + .../expression/call/builtin/textureLoad.worker.js | 6 + .../call/builtin/textureSample.worker.js | 6 + .../builtin/textureSampleBaseClampToEdge.worker.js | 6 + .../call/builtin/textureSampleBias.worker.js | 6 + .../call/builtin/textureSampleCompare.worker.js | 6 + .../builtin/textureSampleCompareLevel.worker.js | 6 + .../call/builtin/textureSampleGrad.worker.js | 6 + .../call/builtin/textureSampleLevel.worker.js | 6 + .../expression/call/builtin/textureStore.worker.js | 6 + .../expression/call/builtin/trunc.worker.js | 6 + .../call/builtin/unpack2x16float.worker.js | 6 + .../call/builtin/unpack2x16snorm.worker.js | 6 + .../call/builtin/unpack2x16unorm.worker.js | 6 + .../call/builtin/unpack4x8snorm.worker.js | 6 + .../call/builtin/unpack4x8unorm.worker.js | 6 + .../expression/call/builtin/unpack4xI8.worker.js | 6 + .../expression/call/builtin/unpack4xU8.worker.js | 6 + .../call/builtin/workgroupUniformLoad.worker.js | 6 + .../expression/overload_resolution.worker.js | 6 + .../validation/expression/precedence.worker.js | 6 + .../unary/address_of_and_indirection.worker.js | 6 + .../expression/unary/arithmetic_negation.worker.js | 6 + .../expression/unary/bitwise_complement.worker.js | 6 + .../expression/unary/logical_negation.worker.js | 6 + .../extension/pointer_composite_access.worker.js | 6 + ...adonly_and_readwrite_storage_textures.worker.js | 6 + .../validation/functions/alias_analysis.worker.js | 6 + .../validation/functions/restrictions.worker.js | 6 + .../shader/validation/parse/align.worker.js | 6 + .../shader/validation/parse/attribute.worker.js | 6 + .../shader/validation/parse/binary_ops.worker.js | 6 + .../shader/validation/parse/blankspace.worker.js | 6 + .../shader/validation/parse/break.worker.js | 6 + .../shader/validation/parse/break_if.worker.js | 6 + .../shader/validation/parse/builtin.worker.js | 6 + .../shader/validation/parse/comments.worker.js | 6 + .../shader/validation/parse/compound.worker.js | 6 + .../shader/validation/parse/const.worker.js | 6 + .../shader/validation/parse/const_assert.worker.js | 6 + .../shader/validation/parse/continuing.worker.js | 6 + .../shader/validation/parse/diagnostic.worker.js | 6 + .../shader/validation/parse/discard.worker.js | 6 + .../shader/validation/parse/enable.worker.js | 6 + .../shader/validation/parse/identifiers.worker.js | 6 + .../shader/validation/parse/literal.worker.js | 6 + .../shader/validation/parse/must_use.worker.js | 6 + .../validation/parse/pipeline_stage.worker.js | 6 + .../shader/validation/parse/requires.worker.js | 6 + .../shader/validation/parse/semicolon.worker.js | 6 + .../validation/parse/shadow_builtins.worker.js | 6 + .../shader/validation/parse/source.worker.js | 6 + .../validation/parse/statement_behavior.worker.js | 6 + .../shader/validation/parse/unary_ops.worker.js | 6 + .../shader/validation/parse/var_and_let.worker.js | 6 + .../shader/validation/shader_io/binding.worker.js | 6 + .../shader/validation/shader_io/builtins.worker.js | 6 + .../validation/shader_io/entry_point.worker.js | 6 + .../shader/validation/shader_io/group.worker.js | 6 + .../shader_io/group_and_binding.worker.js | 6 + .../shader/validation/shader_io/id.worker.js | 6 + .../validation/shader_io/interpolate.worker.js | 6 + .../validation/shader_io/invariant.worker.js | 6 + .../shader_io/layout_constraints.worker.js | 6 + .../validation/shader_io/locations.worker.js | 6 + .../shader/validation/shader_io/size.worker.js | 6 + .../validation/shader_io/workgroup_size.worker.js | 6 + .../shader/validation/types/alias.worker.js | 6 + .../shader/validation/types/array.worker.js | 6 + .../shader/validation/types/atomics.worker.js | 6 + .../shader/validation/types/matrix.worker.js | 6 + .../shader/validation/types/struct.worker.js | 6 + .../shader/validation/types/textures.worker.js | 6 + .../shader/validation/types/vector.worker.js | 6 + .../validation/uniformity/uniformity.worker.js | 6 + .../util/texture/color_space_conversions.worker.js | 6 + .../webworker/util/texture/texel_data.worker.js | 6 + .../webworker/util/texture/texture_ok.worker.js | 6 + .../web_platform/canvas/configure.worker.js | 6 + .../web_platform/canvas/context_creation.worker.js | 6 + .../canvas/getCurrentTexture.worker.js | 6 + .../canvas/getPreferredCanvasFormat.worker.js | 6 + .../canvas/readbackFromWebGPUCanvas.worker.js | 6 + .../copyToTexture/ImageBitmap.worker.js | 6 + .../web_platform/copyToTexture/ImageData.worker.js | 6 + .../web_platform/copyToTexture/canvas.worker.js | 6 + .../web_platform/copyToTexture/image.worker.js | 6 + .../web_platform/copyToTexture/video.worker.js | 6 + .../web_platform/external_texture/video.worker.js | 6 + .../webworker/web_platform/worker/worker.worker.js | 6 + .../external/petamoriken/float16/float16.d.js | 27 + .../webgpu/external/petamoriken/float16/float16.js | 179 ++- .../mozilla/tests/webgpu/resources/README.md | 99 +- .../tests/webgpu/resources/cache/hashes.json | 111 ++ .../cache/webgpu/shader/execution/abs.bin | Bin 0 -> 17976 bytes .../cache/webgpu/shader/execution/acos.bin | Bin 0 -> 26440 bytes .../cache/webgpu/shader/execution/acosh.bin | Bin 0 -> 30248 bytes .../cache/webgpu/shader/execution/asin.bin | Bin 0 -> 26440 bytes .../cache/webgpu/shader/execution/asinh.bin | Bin 0 -> 11664 bytes .../cache/webgpu/shader/execution/atan.bin | Bin 0 -> 20128 bytes .../cache/webgpu/shader/execution/atan2.bin | Bin 0 -> 51608 bytes .../cache/webgpu/shader/execution/atanh.bin | Bin 0 -> 21104 bytes .../webgpu/shader/execution/binary/af_addition.bin | Bin 0 -> 237960 bytes .../webgpu/shader/execution/binary/af_division.bin | Bin 0 -> 77496 bytes .../webgpu/shader/execution/binary/af_logical.bin | Bin 0 -> 12456 bytes .../shader/execution/binary/af_matrix_addition.bin | Bin 0 -> 175672 bytes .../binary/af_matrix_matrix_multiplication.bin | Bin 0 -> 82608 bytes .../binary/af_matrix_scalar_multiplication.bin | Bin 0 -> 291528 bytes .../execution/binary/af_matrix_subtraction.bin | Bin 0 -> 181112 bytes .../binary/af_matrix_vector_multiplication.bin | Bin 0 -> 152528 bytes .../shader/execution/binary/af_multiplication.bin | Bin 0 -> 207864 bytes .../shader/execution/binary/af_remainder.bin | Bin 0 -> 77496 bytes .../shader/execution/binary/af_subtraction.bin | Bin 0 -> 237960 bytes .../shader/execution/binary/ai_arithmetic.bin | Bin 0 -> 831992 bytes .../shader/execution/binary/f16_addition.bin | Bin 0 -> 169680 bytes .../shader/execution/binary/f16_division.bin | Bin 0 -> 120856 bytes .../webgpu/shader/execution/binary/f16_logical.bin | Bin 0 -> 15912 bytes .../execution/binary/f16_matrix_addition.bin | Bin 0 -> 557464 bytes .../binary/f16_matrix_matrix_multiplication.bin | Bin 0 -> 1481368 bytes .../binary/f16_matrix_scalar_multiplication.bin | Bin 0 -> 906440 bytes .../execution/binary/f16_matrix_subtraction.bin | Bin 0 -> 534232 bytes .../binary/f16_matrix_vector_multiplication.bin | Bin 0 -> 601680 bytes .../shader/execution/binary/f16_multiplication.bin | Bin 0 -> 171072 bytes .../shader/execution/binary/f16_remainder.bin | Bin 0 -> 118944 bytes .../shader/execution/binary/f16_subtraction.bin | Bin 0 -> 169680 bytes .../shader/execution/binary/f32_addition.bin | Bin 0 -> 279984 bytes .../shader/execution/binary/f32_division.bin | Bin 0 -> 174960 bytes .../webgpu/shader/execution/binary/f32_logical.bin | Bin 0 -> 18984 bytes .../execution/binary/f32_matrix_addition.bin | Bin 0 -> 991896 bytes .../binary/f32_matrix_matrix_multiplication.bin | Bin 0 -> 2510560 bytes .../binary/f32_matrix_scalar_multiplication.bin | Bin 0 -> 1534768 bytes .../execution/binary/f32_matrix_subtraction.bin | Bin 0 -> 995984 bytes .../binary/f32_matrix_vector_multiplication.bin | Bin 0 -> 950336 bytes .../shader/execution/binary/f32_multiplication.bin | Bin 0 -> 257976 bytes .../shader/execution/binary/f32_remainder.bin | Bin 0 -> 171384 bytes .../shader/execution/binary/f32_subtraction.bin | Bin 0 -> 279968 bytes .../shader/execution/binary/i32_arithmetic.bin | Bin 0 -> 727864 bytes .../shader/execution/binary/i32_comparison.bin | Bin 0 -> 3872 bytes .../shader/execution/binary/u32_arithmetic.bin | Bin 0 -> 225816 bytes .../shader/execution/binary/u32_comparison.bin | Bin 0 -> 2192 bytes .../cache/webgpu/shader/execution/bitcast.bin | Bin 0 -> 2240896 bytes .../cache/webgpu/shader/execution/ceil.bin | Bin 0 -> 16016 bytes .../cache/webgpu/shader/execution/clamp.bin | Bin 0 -> 1048136 bytes .../cache/webgpu/shader/execution/cos.bin | Bin 0 -> 20176 bytes .../cache/webgpu/shader/execution/cosh.bin | Bin 0 -> 14904 bytes .../cache/webgpu/shader/execution/cross.bin | Bin 0 -> 829096 bytes .../cache/webgpu/shader/execution/degrees.bin | Bin 0 -> 18048 bytes .../cache/webgpu/shader/execution/derivatives.bin | Bin 0 -> 11264 bytes .../cache/webgpu/shader/execution/determinant.bin | Bin 0 -> 9944 bytes .../cache/webgpu/shader/execution/distance.bin | Bin 0 -> 1731496 bytes .../cache/webgpu/shader/execution/dot.bin | Bin 0 -> 469272 bytes .../cache/webgpu/shader/execution/exp.bin | Bin 0 -> 34592 bytes .../cache/webgpu/shader/execution/exp2.bin | Bin 0 -> 34592 bytes .../cache/webgpu/shader/execution/faceForward.bin | Bin 0 -> 4214688 bytes .../cache/webgpu/shader/execution/floor.bin | Bin 0 -> 16016 bytes .../cache/webgpu/shader/execution/fma.bin | Bin 0 -> 886720 bytes .../cache/webgpu/shader/execution/fract.bin | Bin 0 -> 16408 bytes .../cache/webgpu/shader/execution/frexp.bin | Bin 0 -> 47072 bytes .../cache/webgpu/shader/execution/inverseSqrt.bin | Bin 0 -> 78424 bytes .../cache/webgpu/shader/execution/ldexp.bin | Bin 0 -> 33096 bytes .../cache/webgpu/shader/execution/length.bin | Bin 0 -> 35696 bytes .../cache/webgpu/shader/execution/log.bin | Bin 0 -> 148848 bytes .../cache/webgpu/shader/execution/log2.bin | Bin 0 -> 148848 bytes .../cache/webgpu/shader/execution/max.bin | Bin 0 -> 37944 bytes .../cache/webgpu/shader/execution/min.bin | Bin 0 -> 37944 bytes .../cache/webgpu/shader/execution/mix.bin | Bin 0 -> 5817432 bytes .../cache/webgpu/shader/execution/modf.bin | Bin 0 -> 82448 bytes .../cache/webgpu/shader/execution/normalize.bin | Bin 0 -> 47608 bytes .../webgpu/shader/execution/pack2x16float.bin | Bin 0 -> 1791400 bytes .../cache/webgpu/shader/execution/pow.bin | Bin 0 -> 1308224 bytes .../webgpu/shader/execution/quantizeToF16.bin | Bin 0 -> 8904 bytes .../cache/webgpu/shader/execution/radians.bin | Bin 0 -> 10992 bytes .../cache/webgpu/shader/execution/reflect.bin | Bin 0 -> 277720 bytes .../cache/webgpu/shader/execution/refract.bin | Bin 0 -> 2828888 bytes .../cache/webgpu/shader/execution/round.bin | Bin 0 -> 14816 bytes .../cache/webgpu/shader/execution/saturate.bin | Bin 0 -> 17096 bytes .../cache/webgpu/shader/execution/sign.bin | Bin 0 -> 21224 bytes .../cache/webgpu/shader/execution/sin.bin | Bin 0 -> 20176 bytes .../cache/webgpu/shader/execution/sinh.bin | Bin 0 -> 14904 bytes .../cache/webgpu/shader/execution/smoothstep.bin | Bin 0 -> 629408 bytes .../cache/webgpu/shader/execution/sqrt.bin | Bin 0 -> 10024 bytes .../cache/webgpu/shader/execution/step.bin | Bin 0 -> 33160 bytes .../cache/webgpu/shader/execution/tan.bin | Bin 0 -> 21776 bytes .../cache/webgpu/shader/execution/tanh.bin | Bin 0 -> 11448 bytes .../cache/webgpu/shader/execution/transpose.bin | Bin 0 -> 129192 bytes .../cache/webgpu/shader/execution/trunc.bin | Bin 0 -> 14696 bytes .../shader/execution/unary/af_arithmetic.bin | Bin 0 -> 30376 bytes .../shader/execution/unary/af_assignment.bin | Bin 0 -> 10296 bytes .../shader/execution/unary/ai_arithmetic.bin | Bin 0 -> 3256 bytes .../shader/execution/unary/ai_assignment.bin | Bin 0 -> 6936 bytes .../shader/execution/unary/bool_conversion.bin | Bin 0 -> 6480 bytes .../shader/execution/unary/f16_arithmetic.bin | Bin 0 -> 15208 bytes .../shader/execution/unary/f16_conversion.bin | Bin 0 -> 97912 bytes .../shader/execution/unary/f32_arithmetic.bin | Bin 0 -> 19544 bytes .../shader/execution/unary/f32_conversion.bin | Bin 0 -> 105744 bytes .../shader/execution/unary/i32_arithmetic.bin | Bin 0 -> 1648 bytes .../shader/execution/unary/i32_conversion.bin | Bin 0 -> 11856 bytes .../shader/execution/unary/u32_conversion.bin | Bin 0 -> 10680 bytes .../webgpu/shader/execution/unpack2x16float.bin | Bin 0 -> 4832 bytes .../webgpu/shader/execution/unpack2x16snorm.bin | Bin 0 -> 4968 bytes .../webgpu/shader/execution/unpack2x16unorm.bin | Bin 0 -> 4968 bytes .../webgpu/shader/execution/unpack4x8snorm.bin | Bin 0 -> 7416 bytes .../webgpu/shader/execution/unpack4x8unorm.bin | Bin 0 -> 7416 bytes .../resources/four-colors-h264-bt601-hflip.mp4 | Bin 0 -> 3174 bytes .../four-colors-h264-bt601-rotate-180.mp4 | Bin 16261 -> 3113 bytes .../four-colors-h264-bt601-rotate-270.mp4 | Bin 16261 -> 3211 bytes .../resources/four-colors-h264-bt601-rotate-90.mp4 | Bin 16261 -> 3204 bytes .../resources/four-colors-h264-bt601-vflip.mp4 | Bin 0 -> 3174 bytes .../webgpu/resources/four-colors-h264-bt601.mp4 | Bin 16261 -> 3174 bytes .../webgpu/resources/four-colors-vp8-bt601.webm | Bin 17910 -> 2421 bytes .../resources/four-colors-vp9-bt601-hflip.mp4 | Bin 0 -> 2077 bytes .../resources/four-colors-vp9-bt601-rotate-180.mp4 | Bin 0 -> 2079 bytes .../resources/four-colors-vp9-bt601-rotate-270.mp4 | Bin 0 -> 2016 bytes .../resources/four-colors-vp9-bt601-rotate-90.mp4 | Bin 0 -> 2079 bytes .../resources/four-colors-vp9-bt601-vflip.mp4 | Bin 0 -> 2077 bytes .../webgpu/resources/four-colors-vp9-bt601.mp4 | Bin 0 -> 2077 bytes .../webgpu/resources/four-colors-vp9-bt601.webm | Bin 13116 -> 1847 bytes .../webgpu/resources/four-colors-vp9-bt709.webm | Bin 12584 -> 1789 bytes .../api/operation/adapter/requestDevice.spec.js | 59 + .../command_buffer/copyTextureToTexture.spec.js | 115 +- .../operation/command_buffer/image_copy.spec.js | 100 +- .../command_buffer/queries/occlusionQuery.spec.js | 8 +- .../texture/readonly_depth_stencil.spec.js | 329 ++++ .../webgpu/webgpu/api/operation/reflection.spec.js | 197 ++- .../operation/render_pipeline/sample_mask.spec.js | 24 +- .../operation/rendering/3d_texture_slices.spec.js | 363 +++++ .../operation/rendering/color_target_state.spec.js | 8 +- .../webgpu/api/operation/rendering/depth.spec.js | 9 +- .../api/operation/rendering/depth_bias.spec.js | 12 + .../operation/rendering/depth_clip_clamp.spec.js | 20 +- .../resource_init/check_texture/by_copy.js | 1 + .../resource_init/check_texture/by_ds_test.js | 1 + .../resource_init/check_texture/by_sampling.js | 36 +- .../check_texture/texture_zero_init_test.js | 538 +++++++ .../operation/resource_init/texture_zero.spec.js | 556 +------ .../shader_module/compilation_info.spec.js | 39 +- .../operation/storage_texture/read_only.spec.js | 626 ++++++++ .../operation/storage_texture/read_write.spec.js | 385 +++++ .../texture_view/format_reinterpretation.spec.js | 10 +- .../api/operation/texture_view/write.spec.js | 347 +++- .../webgpu/api/validation/buffer/mapping.spec.js | 39 +- .../capability_checks/features/query_types.spec.js | 56 +- .../capability_checks/limits/limit_utils.js | 115 +- .../capability_checks/limits/maxBindGroups.spec.js | 156 +- .../limits/maxBindGroupsPlusVertexBuffers.spec.js | 301 ++++ .../limits/maxComputeWorkgroupStorageSize.spec.js | 9 +- .../limits/maxInterStageShaderComponents.spec.js | 8 +- .../maxSampledTexturesPerShaderStage.spec.js | 52 +- .../limits/maxSamplersPerShaderStage.spec.js | 56 +- .../limits/maxStorageBuffersPerShaderStage.spec.js | 91 +- .../maxStorageTexturesPerShaderStage.spec.js | 48 +- .../limits/maxUniformBuffersPerShaderStage.spec.js | 48 +- .../limits/maxVertexBuffers.spec.js | 68 +- .../webgpu/api/validation/compute_pipeline.spec.js | 50 + .../webgpu/api/validation/createBindGroup.spec.js | 49 +- .../api/validation/createBindGroupLayout.spec.js | 47 +- .../webgpu/api/validation/createTexture.spec.js | 45 +- .../webgpu/api/validation/createView.spec.js | 11 +- .../encoding/cmds/copyTextureToTexture.spec.js | 15 +- .../encoding/createRenderBundleEncoder.spec.js | 44 +- .../validation/encoding/encoder_open_state.spec.js | 10 +- .../pipeline_bind_group_compat.spec.js | 343 +++- .../validation/encoding/queries/general.spec.js | 42 +- .../api/validation/encoding/render_bundle.spec.js | 16 +- .../webgpu/api/validation/error_scope.spec.js | 18 +- .../gpu_external_texture_expiration.spec.js | 35 +- .../webgpu/api/validation/image_copy/image_copy.js | 4 +- .../validation/image_copy/texture_related.spec.js | 2 +- .../api/validation/layout_shader_compat.spec.js | 287 +++- .../CopyExternalImageToTexture.spec.js | 4 +- .../validation/queue/destroyed/query_set.spec.js | 53 +- .../api/validation/queue/destroyed/texture.spec.js | 11 +- .../render_pass/attachment_compatibility.spec.js | 7 - .../render_pass/render_pass_descriptor.spec.js | 190 ++- .../api/validation/render_pipeline/common.js | 7 +- .../render_pipeline/depth_stencil_state.spec.js | 12 +- .../render_pipeline/fragment_state.spec.js | 79 +- .../validation/render_pipeline/inter_stage.spec.js | 72 +- .../api/validation/render_pipeline/misc.spec.js | 34 + .../render_pipeline/resource_compatibility.spec.js | 95 ++ .../texture/in_pass_encoder.spec.js | 277 +++- .../texture/in_render_common.spec.js | 97 +- .../resource_usages/texture/in_render_misc.spec.js | 311 +++- .../validation/shader_module/entry_point.spec.js | 228 ++- .../validation/state/device_lost/destroy.spec.js | 12 +- .../validation/texture/bgra8unorm_storage.spec.js | 31 - .../tests/webgpu/webgpu/api/validation/utils.js | 275 ++++ .../webgpu/api/validation/validation_test.js | 25 +- .../mozilla/tests/webgpu/webgpu/capability_info.js | 90 +- .../compat/api/validation/createBindGroup.spec.js | 178 +++ .../api/validation/createBindGroupLayout.spec.js | 34 + .../encoding/cmds/copyTextureToBuffer.spec.js | 9 +- .../encoding/cmds/copyTextureToTexture.spec.js | 94 ++ .../render_pipeline/depth_stencil_state.spec.js | 53 + .../render_pipeline/shader_module.spec.js | 207 +++ .../api/validation/texture/createTexture.spec.js | 133 +- .../mozilla/tests/webgpu/webgpu/constants.js | 5 +- .../mozilla/tests/webgpu/webgpu/format_info.js | 1159 ++++++++++---- .../mozilla/tests/webgpu/webgpu/gpu_test.js | 234 ++- .../tests/webgpu/webgpu/idl/constructable.spec.js | 54 + .../tests/webgpu/webgpu/idl/exposed.http.html | 13 - .../tests/webgpu/webgpu/idl/exposed.https.html | 13 - .../mozilla/tests/webgpu/webgpu/listing.js | 1436 +++++++++++++++-- .../tests/webgpu/webgpu/multisample_info.js | 75 + .../tests/webgpu/webgpu/print_environment.spec.js | 70 + .../expression/access/array/index.spec.js | 354 +++++ .../expression/access/matrix/index.spec.js | 200 +++ .../expression/access/structure/index.spec.js | 508 ++++++ .../expression/access/vector/components.spec.js | 118 ++ .../expression/access/vector/index.spec.js | 87 + .../expression/binary/af_addition.cache.js | 54 + .../expression/binary/af_addition.spec.js | 85 +- .../expression/binary/af_comparison.cache.js | 90 ++ .../expression/binary/af_comparison.spec.js | 139 +- .../expression/binary/af_division.cache.js | 57 + .../expression/binary/af_division.spec.js | 85 +- .../expression/binary/af_matrix_addition.cache.js | 26 + .../expression/binary/af_matrix_addition.spec.js | 34 +- .../af_matrix_matrix_multiplication.cache.js | 29 + .../binary/af_matrix_matrix_multiplication.spec.js | 45 + .../af_matrix_scalar_multiplication.cache.js | 49 + .../binary/af_matrix_scalar_multiplication.spec.js | 69 + .../binary/af_matrix_subtraction.cache.js | 26 + .../binary/af_matrix_subtraction.spec.js | 34 +- .../af_matrix_vector_multiplication.cache.js | 51 + .../binary/af_matrix_vector_multiplication.spec.js | 69 + .../expression/binary/af_multiplication.cache.js | 54 + .../expression/binary/af_multiplication.spec.js | 85 +- .../expression/binary/af_remainder.cache.js | 57 + .../expression/binary/af_remainder.spec.js | 83 +- .../expression/binary/af_subtraction.cache.js | 54 + .../expression/binary/af_subtraction.spec.js | 85 +- .../expression/binary/ai_arithmetic.cache.js | 145 ++ .../expression/binary/ai_arithmetic.spec.js | 303 ++++ .../expression/binary/ai_comparison.spec.js | 124 ++ .../shader/execution/expression/binary/binary.js | 10 +- .../execution/expression/binary/bitwise.spec.js | 505 ++++-- .../expression/binary/bitwise_shift.spec.js | 11 +- .../expression/binary/bool_logical.spec.js | 18 +- .../expression/binary/f16_addition.cache.js | 60 + .../expression/binary/f16_addition.spec.js | 81 +- .../expression/binary/f16_comparison.cache.js | 144 ++ .../expression/binary/f16_comparison.spec.js | 157 +- .../expression/binary/f16_division.cache.js | 60 + .../expression/binary/f16_division.spec.js | 81 +- .../expression/binary/f16_matrix_addition.cache.js | 23 + .../expression/binary/f16_matrix_addition.spec.js | 34 +- .../f16_matrix_matrix_multiplication.cache.js | 25 + .../f16_matrix_matrix_multiplication.spec.js | 36 +- .../f16_matrix_scalar_multiplication.cache.js | 44 + .../f16_matrix_scalar_multiplication.spec.js | 59 +- .../binary/f16_matrix_subtraction.cache.js | 23 + .../binary/f16_matrix_subtraction.spec.js | 34 +- .../f16_matrix_vector_multiplication.cache.js | 44 + .../f16_matrix_vector_multiplication.spec.js | 59 +- .../expression/binary/f16_multiplication.cache.js | 60 + .../expression/binary/f16_multiplication.spec.js | 81 +- .../expression/binary/f16_remainder.cache.js | 60 + .../expression/binary/f16_remainder.spec.js | 81 +- .../expression/binary/f16_subtraction.cache.js | 60 + .../expression/binary/f16_subtraction.spec.js | 81 +- .../expression/binary/f32_addition.cache.js | 60 + .../expression/binary/f32_addition.spec.js | 81 +- .../expression/binary/f32_comparison.cache.js | 144 ++ .../expression/binary/f32_comparison.spec.js | 157 +- .../expression/binary/f32_division.cache.js | 60 + .../expression/binary/f32_division.spec.js | 81 +- .../expression/binary/f32_matrix_addition.cache.js | 23 + .../expression/binary/f32_matrix_addition.spec.js | 34 +- .../f32_matrix_matrix_multiplication.cache.js | 25 + .../f32_matrix_matrix_multiplication.spec.js | 36 +- .../f32_matrix_scalar_multiplication.cache.js | 44 + .../f32_matrix_scalar_multiplication.spec.js | 59 +- .../binary/f32_matrix_subtraction.cache.js | 23 + .../binary/f32_matrix_subtraction.spec.js | 34 +- .../f32_matrix_vector_multiplication.cache.js | 44 + .../f32_matrix_vector_multiplication.spec.js | 59 +- .../expression/binary/f32_multiplication.cache.js | 60 + .../expression/binary/f32_multiplication.spec.js | 81 +- .../expression/binary/f32_remainder.cache.js | 64 + .../expression/binary/f32_remainder.spec.js | 81 +- .../expression/binary/f32_subtraction.cache.js | 60 + .../expression/binary/f32_subtraction.spec.js | 81 +- .../expression/binary/i32_arithmetic.cache.js | 306 ++++ .../expression/binary/i32_arithmetic.spec.js | 392 +---- .../expression/binary/i32_comparison.cache.js | 21 + .../expression/binary/i32_comparison.spec.js | 34 +- .../expression/binary/u32_arithmetic.cache.js | 293 ++++ .../expression/binary/u32_arithmetic.spec.js | 379 +---- .../expression/binary/u32_comparison.cache.js | 21 + .../expression/binary/u32_comparison.spec.js | 34 +- .../execution/expression/call/builtin/abs.cache.js | 26 + .../execution/expression/call/builtin/abs.spec.js | 64 +- .../expression/call/builtin/acos.cache.js | 24 + .../execution/expression/call/builtin/acos.spec.js | 57 +- .../expression/call/builtin/acosh.cache.js | 24 + .../expression/call/builtin/acosh.spec.js | 56 +- .../execution/expression/call/builtin/all.spec.js | 20 +- .../execution/expression/call/builtin/any.spec.js | 20 +- .../expression/call/builtin/asin.cache.js | 24 + .../execution/expression/call/builtin/asin.spec.js | 57 +- .../expression/call/builtin/asinh.cache.js | 18 + .../expression/call/builtin/asinh.spec.js | 41 +- .../expression/call/builtin/atan.cache.js | 25 + .../execution/expression/call/builtin/atan.spec.js | 52 +- .../expression/call/builtin/atan2.cache.js | 35 + .../expression/call/builtin/atan2.spec.js | 56 +- .../expression/call/builtin/atanh.cache.js | 32 + .../expression/call/builtin/atanh.spec.js | 63 +- .../atomics/atomicCompareExchangeWeak.spec.js | 10 + .../expression/call/builtin/atomics/harness.js | 7 +- .../expression/call/builtin/bitcast.cache.js | 837 ++++++++++ .../expression/call/builtin/bitcast.spec.js | 1142 +++----------- .../execution/expression/call/builtin/builtin.js | 10 +- .../expression/call/builtin/ceil.cache.js | 26 + .../execution/expression/call/builtin/ceil.spec.js | 79 +- .../expression/call/builtin/clamp.cache.js | 131 ++ .../expression/call/builtin/clamp.spec.js | 138 +- .../execution/expression/call/builtin/cos.cache.js | 23 + .../execution/expression/call/builtin/cos.spec.js | 57 +- .../expression/call/builtin/cosh.cache.js | 23 + .../execution/expression/call/builtin/cosh.spec.js | 47 +- .../call/builtin/countLeadingZeros.spec.js | 6 +- .../expression/call/builtin/countOneBits.spec.js | 6 +- .../call/builtin/countTrailingZeros.spec.js | 6 +- .../expression/call/builtin/cross.cache.js | 25 + .../expression/call/builtin/cross.spec.js | 79 +- .../expression/call/builtin/degrees.cache.js | 24 + .../expression/call/builtin/degrees.spec.js | 52 +- .../expression/call/builtin/derivatives.cache.js | 14 + .../expression/call/builtin/derivatives.js | 215 +++ .../expression/call/builtin/determinant.cache.js | 99 ++ .../expression/call/builtin/determinant.spec.js | 112 +- .../expression/call/builtin/distance.cache.js | 49 + .../expression/call/builtin/distance.spec.js | 210 +-- .../execution/expression/call/builtin/dot.cache.js | 118 ++ .../execution/expression/call/builtin/dot.spec.js | 238 +-- .../expression/call/builtin/dot4I8Packed.spec.js | 74 + .../expression/call/builtin/dot4U8Packed.spec.js | 59 + .../execution/expression/call/builtin/dpdx.spec.js | 16 +- .../expression/call/builtin/dpdxCoarse.spec.js | 16 +- .../expression/call/builtin/dpdxFine.spec.js | 16 +- .../execution/expression/call/builtin/dpdy.spec.js | 16 +- .../expression/call/builtin/dpdyCoarse.spec.js | 16 +- .../expression/call/builtin/dpdyFine.spec.js | 16 +- .../execution/expression/call/builtin/exp.cache.js | 44 + .../execution/expression/call/builtin/exp.spec.js | 69 +- .../expression/call/builtin/exp2.cache.js | 44 + .../execution/expression/call/builtin/exp2.spec.js | 69 +- .../expression/call/builtin/extractBits.spec.js | 20 +- .../expression/call/builtin/faceForward.cache.js | 125 ++ .../expression/call/builtin/faceForward.spec.js | 196 +-- .../call/builtin/firstLeadingBit.spec.js | 6 +- .../call/builtin/firstTrailingBit.spec.js | 6 +- .../expression/call/builtin/floor.cache.js | 26 + .../expression/call/builtin/floor.spec.js | 61 +- .../execution/expression/call/builtin/fma.cache.js | 26 + .../execution/expression/call/builtin/fma.spec.js | 70 +- .../expression/call/builtin/fract.cache.js | 50 + .../expression/call/builtin/fract.spec.js | 81 +- .../expression/call/builtin/frexp.cache.js | 103 ++ .../expression/call/builtin/frexp.spec.js | 310 ++-- .../expression/call/builtin/insertBits.spec.js | 18 +- .../expression/call/builtin/inversesqrt.cache.js | 44 + .../expression/call/builtin/inversesqrt.spec.js | 60 +- .../expression/call/builtin/ldexp.cache.js | 61 + .../expression/call/builtin/ldexp.spec.js | 94 +- .../expression/call/builtin/length.cache.js | 42 + .../expression/call/builtin/length.spec.js | 142 +- .../execution/expression/call/builtin/log.cache.js | 30 + .../execution/expression/call/builtin/log.spec.js | 62 +- .../expression/call/builtin/log2.cache.js | 30 + .../execution/expression/call/builtin/log2.spec.js | 62 +- .../execution/expression/call/builtin/max.cache.js | 18 + .../execution/expression/call/builtin/max.spec.js | 98 +- .../execution/expression/call/builtin/min.cache.js | 18 + .../execution/expression/call/builtin/min.spec.js | 98 +- .../execution/expression/call/builtin/mix.cache.js | 56 + .../execution/expression/call/builtin/mix.spec.js | 210 +-- .../expression/call/builtin/modf.cache.js | 75 + .../execution/expression/call/builtin/modf.spec.js | 192 +-- .../expression/call/builtin/normalize.cache.js | 25 + .../expression/call/builtin/normalize.spec.js | 86 +- .../expression/call/builtin/pack2x16float.cache.js | 55 + .../expression/call/builtin/pack2x16float.spec.js | 66 +- .../expression/call/builtin/pack2x16snorm.spec.js | 13 +- .../expression/call/builtin/pack2x16unorm.spec.js | 13 +- .../expression/call/builtin/pack4x8snorm.spec.js | 19 +- .../expression/call/builtin/pack4x8unorm.spec.js | 19 +- .../expression/call/builtin/pack4xI8.spec.js | 69 + .../expression/call/builtin/pack4xI8Clamp.spec.js | 73 + .../expression/call/builtin/pack4xU8.spec.js | 54 + .../expression/call/builtin/pack4xU8Clamp.spec.js | 57 + .../execution/expression/call/builtin/pow.cache.js | 24 + .../execution/expression/call/builtin/pow.spec.js | 67 +- .../expression/call/builtin/quantizeToF16.cache.js | 41 + .../expression/call/builtin/quantizeToF16.spec.js | 46 +- .../expression/call/builtin/radians.cache.js | 18 + .../expression/call/builtin/radians.spec.js | 44 +- .../expression/call/builtin/reflect.cache.js | 26 + .../expression/call/builtin/reflect.spec.js | 149 +- .../expression/call/builtin/refract.cache.js | 116 ++ .../expression/call/builtin/refract.spec.js | 189 +-- .../expression/call/builtin/reverseBits.spec.js | 6 +- .../expression/call/builtin/round.cache.js | 24 + .../expression/call/builtin/round.spec.js | 55 +- .../expression/call/builtin/saturate.cache.js | 18 + .../expression/call/builtin/saturate.spec.js | 56 +- .../expression/call/builtin/select.spec.js | 119 +- .../expression/call/builtin/sign.cache.js | 31 + .../execution/expression/call/builtin/sign.spec.js | 66 +- .../execution/expression/call/builtin/sin.cache.js | 23 + .../execution/expression/call/builtin/sin.spec.js | 57 +- .../expression/call/builtin/sinh.cache.js | 23 + .../execution/expression/call/builtin/sinh.spec.js | 47 +- .../expression/call/builtin/smoothstep.cache.js | 25 + .../expression/call/builtin/smoothstep.spec.js | 71 +- .../expression/call/builtin/sqrt.cache.js | 23 + .../execution/expression/call/builtin/sqrt.spec.js | 47 +- .../expression/call/builtin/step.cache.js | 41 + .../execution/expression/call/builtin/step.spec.js | 66 +- .../execution/expression/call/builtin/tan.cache.js | 23 + .../execution/expression/call/builtin/tan.spec.js | 57 +- .../expression/call/builtin/tanh.cache.js | 18 + .../execution/expression/call/builtin/tanh.spec.js | 41 +- .../call/builtin/textureDimension.spec.js | 160 -- .../call/builtin/textureDimensions.spec.js | 518 ++++++ .../expression/call/builtin/textureSample.spec.js | 99 +- .../call/builtin/textureSampleBias.spec.js | 22 - .../call/builtin/textureSampleCompare.spec.js | 23 - .../expression/call/builtin/texture_utils.js | 809 ++++++++++ .../expression/call/builtin/transpose.cache.js | 27 + .../expression/call/builtin/transpose.spec.js | 85 +- .../expression/call/builtin/trunc.cache.js | 17 + .../expression/call/builtin/trunc.spec.js | 39 +- .../call/builtin/unpack2x16float.cache.js | 20 + .../call/builtin/unpack2x16float.spec.js | 25 +- .../call/builtin/unpack2x16snorm.cache.js | 20 + .../call/builtin/unpack2x16snorm.spec.js | 25 +- .../call/builtin/unpack2x16unorm.cache.js | 20 + .../call/builtin/unpack2x16unorm.spec.js | 25 +- .../call/builtin/unpack4x8snorm.cache.js | 20 + .../expression/call/builtin/unpack4x8snorm.spec.js | 25 +- .../call/builtin/unpack4x8unorm.cache.js | 20 + .../expression/call/builtin/unpack4x8unorm.spec.js | 25 +- .../expression/call/builtin/unpack4xI8.spec.js | 56 + .../expression/call/builtin/unpack4xU8.spec.js | 48 + .../call/builtin/workgroupUniformLoad.spec.js | 182 +++ .../expression/call/user/ptr_params.spec.js | 849 ++++++++++ .../webgpu/shader/execution/expression/case.js | 440 ++++++ .../shader/execution/expression/case_cache.js | 23 +- .../expression/constructor/non_zero.spec.js | 797 ++++++++++ .../expression/constructor/zero_value.spec.js | 162 ++ .../shader/execution/expression/expectation.js | 38 + .../shader/execution/expression/expression.js | 756 ++++----- .../shader/execution/expression/interval_filter.js | 9 + .../shader/execution/expression/precedence.spec.js | 113 ++ .../unary/address_of_and_indirection.spec.js | 171 ++ .../expression/unary/af_arithmetic.cache.js | 13 + .../expression/unary/af_arithmetic.spec.js | 30 +- .../expression/unary/af_assignment.cache.js | 51 + .../expression/unary/af_assignment.spec.js | 66 +- .../expression/unary/ai_arithmetic.cache.js | 11 + .../expression/unary/ai_arithmetic.spec.js | 30 + .../expression/unary/ai_assignment.cache.js | 21 + .../expression/unary/ai_assignment.spec.js | 65 + .../expression/unary/ai_complement.spec.js | 32 + .../expression/unary/bool_conversion.cache.js | 54 + .../expression/unary/bool_conversion.spec.js | 85 +- .../expression/unary/bool_logical.spec.js | 4 +- .../expression/unary/f16_arithmetic.cache.js | 13 + .../expression/unary/f16_arithmetic.spec.js | 18 +- .../expression/unary/f16_conversion.cache.js | 135 ++ .../expression/unary/f16_conversion.spec.js | 226 ++- .../expression/unary/f32_arithmetic.cache.js | 13 + .../expression/unary/f32_arithmetic.spec.js | 18 +- .../expression/unary/f32_conversion.cache.js | 79 + .../expression/unary/f32_conversion.spec.js | 111 +- .../expression/unary/i32_arithmetic.cache.js | 11 + .../expression/unary/i32_arithmetic.spec.js | 15 +- .../expression/unary/i32_complement.spec.js | 17 +- .../expression/unary/i32_conversion.cache.js | 116 ++ .../expression/unary/i32_conversion.spec.js | 158 +- .../expression/unary/u32_complement.spec.js | 17 +- .../expression/unary/u32_conversion.cache.js | 107 ++ .../expression/unary/u32_conversion.spec.js | 144 +- .../shader/execution/expression/unary/unary.js | 10 +- .../shader/execution/flow_control/call.spec.js | 113 ++ .../shader/execution/flow_control/for.spec.js | 50 + .../shader/execution/flow_control/loop.spec.js | 60 + .../shader/execution/flow_control/switch.spec.js | 33 + .../shader/execution/flow_control/while.spec.js | 54 + .../webgpu/shader/execution/memory_layout.spec.js | 1059 +++++++++++++ .../shader/execution/memory_model/barrier.spec.js | 185 ++- .../execution/memory_model/memory_model_setup.js | 335 +++- .../texture_intra_invocation_coherence.spec.js | 333 ++++ .../webgpu/shader/execution/robust_access.spec.js | 28 +- .../shader/execution/robust_access_vertex.spec.js | 1 + .../execution/shader_io/compute_builtins.spec.js | 177 +-- .../execution/shader_io/fragment_builtins.spec.js | 1410 +++++++++++++++++ .../shader/execution/shader_io/user_io.spec.js | 213 +++ .../execution/shader_io/workgroup_size.spec.js | 150 ++ .../webgpu/webgpu/shader/execution/stage.spec.js | 133 ++ .../shader/execution/statement/compound.spec.js | 137 ++ .../shader/execution/statement/discard.spec.js | 645 ++++++++ .../webgpu/shader/execution/zero_init.spec.js | 4 + .../mozilla/tests/webgpu/webgpu/shader/types.js | 200 ++- .../validation/const_assert/const_assert.spec.js | 32 +- .../validation/decl/compound_statement.spec.js | 98 ++ .../webgpu/shader/validation/decl/const.spec.js | 158 ++ .../decl/context_dependent_resolution.spec.js | 338 ++++ .../webgpu/shader/validation/decl/let.spec.js | 180 +++ .../webgpu/shader/validation/decl/override.spec.js | 178 +++ .../webgpu/shader/validation/decl/var.spec.js | 529 +++++++ .../validation/expression/access/vector.spec.js | 7 +- .../expression/binary/add_sub_mul.spec.js | 320 ++++ .../expression/binary/and_or_xor.spec.js | 182 +++ .../expression/binary/bitwise_shift.spec.js | 182 ++- .../expression/binary/comparison.spec.js | 186 +++ .../validation/expression/binary/div_rem.spec.js | 279 ++++ .../validation/expression/call/builtin/abs.spec.js | 114 +- .../expression/call/builtin/acos.spec.js | 162 +- .../expression/call/builtin/acosh.spec.js | 158 +- .../validation/expression/call/builtin/all.spec.js | 191 +++ .../validation/expression/call/builtin/any.spec.js | 191 +++ .../expression/call/builtin/arrayLength.spec.js | 109 ++ .../expression/call/builtin/asin.spec.js | 161 +- .../expression/call/builtin/asinh.spec.js | 153 +- .../expression/call/builtin/atan.spec.js | 146 +- .../expression/call/builtin/atan2.spec.js | 293 +++- .../expression/call/builtin/atanh.spec.js | 169 +- .../expression/call/builtin/atomics.spec.js | 233 ++- .../expression/call/builtin/barriers.spec.js | 109 ++ .../expression/call/builtin/ceil.spec.js | 18 +- .../expression/call/builtin/clamp.spec.js | 14 +- .../call/builtin/const_override_validation.js | 262 +++- .../validation/expression/call/builtin/cos.spec.js | 59 +- .../expression/call/builtin/cosh.spec.js | 66 +- .../call/builtin/countLeadingZeros.spec.js | 198 +++ .../expression/call/builtin/countOneBits.spec.js | 198 +++ .../call/builtin/countTrailingZeros.spec.js | 198 +++ .../expression/call/builtin/cross.spec.js | 122 ++ .../expression/call/builtin/degrees.spec.js | 56 +- .../expression/call/builtin/derivatives.spec.js | 129 ++ .../expression/call/builtin/determinant.spec.js | 95 ++ .../expression/call/builtin/distance.spec.js | 149 ++ .../expression/call/builtin/dot4I8Packed.spec.js | 66 + .../expression/call/builtin/dot4U8Packed.spec.js | 66 + .../validation/expression/call/builtin/exp.spec.js | 122 +- .../expression/call/builtin/exp2.spec.js | 122 +- .../expression/call/builtin/extractBits.spec.js | 218 +++ .../expression/call/builtin/faceForward.spec.js | 152 ++ .../call/builtin/firstLeadingBit.spec.js | 198 +++ .../call/builtin/firstTrailingBit.spec.js | 198 +++ .../expression/call/builtin/floor.spec.js | 108 ++ .../expression/call/builtin/fract.spec.js | 94 ++ .../expression/call/builtin/frexp.spec.js | 94 ++ .../expression/call/builtin/insertBits.spec.js | 241 +++ .../expression/call/builtin/inverseSqrt.spec.js | 76 +- .../expression/call/builtin/length.spec.js | 56 +- .../validation/expression/call/builtin/log.spec.js | 50 +- .../expression/call/builtin/log2.spec.js | 50 +- .../validation/expression/call/builtin/max.spec.js | 91 ++ .../validation/expression/call/builtin/min.spec.js | 91 ++ .../expression/call/builtin/modf.spec.js | 17 +- .../expression/call/builtin/normalize.spec.js | 146 ++ .../expression/call/builtin/pack2x16snorm.spec.js | 58 + .../expression/call/builtin/pack2x16unorm.spec.js | 58 + .../expression/call/builtin/pack4x8snorm.spec.js | 58 + .../expression/call/builtin/pack4x8unorm.spec.js | 58 + .../expression/call/builtin/pack4xI8.spec.js | 62 + .../expression/call/builtin/pack4xI8Clamp.spec.js | 62 + .../expression/call/builtin/pack4xU8.spec.js | 62 + .../expression/call/builtin/pack4xU8Clamp.spec.js | 62 + .../expression/call/builtin/quantizeToF16.spec.js | 113 ++ .../expression/call/builtin/radians.spec.js | 50 +- .../expression/call/builtin/reflect.spec.js | 131 ++ .../expression/call/builtin/reverseBits.spec.js | 198 +++ .../expression/call/builtin/round.spec.js | 31 +- .../expression/call/builtin/saturate.spec.js | 17 +- .../expression/call/builtin/select.spec.js | 250 +++ .../expression/call/builtin/shader_stage_utils.js | 64 + .../expression/call/builtin/sign.spec.js | 63 +- .../validation/expression/call/builtin/sin.spec.js | 60 +- .../expression/call/builtin/sinh.spec.js | 66 +- .../expression/call/builtin/smoothstep.spec.js | 241 +++ .../expression/call/builtin/sqrt.spec.js | 66 +- .../expression/call/builtin/step.spec.js | 108 ++ .../validation/expression/call/builtin/tan.spec.js | 76 +- .../expression/call/builtin/tanh.spec.js | 98 ++ .../expression/call/builtin/textureGather.spec.js | 335 ++++ .../call/builtin/textureGatherCompare.spec.js | 264 ++++ .../expression/call/builtin/textureLoad.spec.js | 370 +++++ .../expression/call/builtin/textureSample.spec.js | 267 ++++ .../builtin/textureSampleBaseClampToEdge.spec.js | 54 + .../call/builtin/textureSampleBias.spec.js | 309 ++++ .../call/builtin/textureSampleCompare.spec.js | 308 ++++ .../call/builtin/textureSampleCompareLevel.spec.js | 268 ++++ .../call/builtin/textureSampleGrad.spec.js | 317 ++++ .../call/builtin/textureSampleLevel.spec.js | 282 ++++ .../expression/call/builtin/textureStore.spec.js | 168 ++ .../expression/call/builtin/trunc.spec.js | 94 ++ .../call/builtin/unpack2x16float.spec.js | 62 + .../call/builtin/unpack2x16snorm.spec.js | 62 + .../call/builtin/unpack2x16unorm.spec.js | 62 + .../expression/call/builtin/unpack4x8snorm.spec.js | 62 + .../expression/call/builtin/unpack4x8unorm.spec.js | 62 + .../expression/call/builtin/unpack4xI8.spec.js | 61 + .../expression/call/builtin/unpack4xU8.spec.js | 61 + .../call/builtin/workgroupUniformLoad.spec.js | 122 ++ .../expression/overload_resolution.spec.js | 268 ++++ .../validation/expression/precedence.spec.js | 188 +++ .../unary/address_of_and_indirection.spec.js | 243 +++ .../expression/unary/arithmetic_negation.spec.js | 114 ++ .../expression/unary/bitwise_complement.spec.js | 114 ++ .../expression/unary/logical_negation.spec.js | 114 ++ .../extension/pointer_composite_access.spec.js | 130 ++ ...readonly_and_readwrite_storage_textures.spec.js | 48 + .../validation/functions/alias_analysis.spec.js | 555 ++++++- .../validation/functions/restrictions.spec.js | 313 ++-- .../webgpu/shader/validation/parse/break.spec.js | 4 - .../shader/validation/parse/break_if.spec.js | 141 ++ .../shader/validation/parse/compound.spec.js | 52 + .../shader/validation/parse/continuing.spec.js | 185 +++ .../shader/validation/parse/diagnostic.spec.js | 260 +++ .../webgpu/shader/validation/parse/enable.spec.js | 18 +- .../shader/validation/parse/must_use.spec.js | 63 +- .../shader/validation/parse/pipeline_stage.spec.js | 42 +- .../shader/validation/parse/requires.spec.js | 103 ++ .../shader/validation/parse/semicolon.spec.js | 15 + .../validation/parse/shadow_builtins.spec.js | 995 ++++++++++++ .../validation/parse/statement_behavior.spec.js | 143 ++ .../shader/validation/shader_io/binding.spec.js | 14 - .../shader/validation/shader_io/builtins.spec.js | 4 +- .../shader/validation/shader_io/group.spec.js | 14 - .../validation/shader_io/group_and_binding.spec.js | 6 +- .../shader_io/layout_constraints.spec.js | 543 +++++++ .../shader/validation/shader_io/locations.spec.js | 149 ++ .../shader/validation/shader_io/size.spec.js | 20 +- .../webgpu/shader/validation/types/alias.spec.js | 122 ++ .../webgpu/shader/validation/types/array.spec.js | 122 ++ .../webgpu/shader/validation/types/atomics.spec.js | 145 ++ .../webgpu/shader/validation/types/matrix.spec.js | 152 ++ .../shader/validation/types/textures.spec.js | 170 ++ .../validation/uniformity/uniformity.spec.js | 211 ++- .../tests/webgpu/webgpu/util/binary_stream.js | 10 + .../tests/webgpu/webgpu/util/check_contents.js | 30 +- .../webgpu/webgpu/util/color_space_conversion.js | 32 +- .../mozilla/tests/webgpu/webgpu/util/compare.js | 26 +- .../mozilla/tests/webgpu/webgpu/util/constants.js | 15 + .../mozilla/tests/webgpu/webgpu/util/conversion.js | 1659 +++++++++++++++----- .../tests/webgpu/webgpu/util/device_pool.js | 12 +- .../tests/webgpu/webgpu/util/floating_point.js | 557 ++++--- .../mozilla/tests/webgpu/webgpu/util/math.js | 461 ++++-- .../tests/webgpu/webgpu/util/pretty_diff_tables.js | 35 +- .../mozilla/tests/webgpu/webgpu/util/shader.js | 23 + .../tests/webgpu/webgpu/util/texture/base.js | 44 +- .../util/texture/color_space_conversions.spec.js | 108 ++ .../tests/webgpu/webgpu/util/texture/texel_data.js | 50 +- .../webgpu/webgpu/util/texture/texel_data.spec.js | 16 +- .../tests/webgpu/webgpu/util/texture/texel_view.js | 17 +- .../tests/webgpu/webgpu/util/texture/texture_ok.js | 20 +- .../webgpu/web_platform/canvas/configure.spec.js | 5 +- .../web_platform/canvas/getCurrentTexture.spec.js | 75 +- .../canvas/readbackFromWebGPUCanvas.spec.js | 155 +- .../web_platform/copyToTexture/canvas.spec.js | 4 +- .../web_platform/copyToTexture/video.spec.js | 88 +- .../web_platform/external_texture/video.spec.js | 347 ++-- .../web_platform/reftests/canvas_clear.https.html | 12 - .../canvas_colorspace_bgra8unorm.https.html | 22 - .../canvas_colorspace_rgba16float.https.html | 23 - .../canvas_colorspace_rgba8unorm.https.html | 22 - .../canvas_complex_bgra8unorm_copy.https.html | 24 - .../canvas_complex_bgra8unorm_draw.https.html | 24 - .../canvas_complex_rgba16float_copy.https.html | 24 - .../canvas_complex_rgba16float_draw.https.html | 24 - .../canvas_complex_rgba16float_store.https.html | 24 - .../canvas_complex_rgba8unorm_copy.https.html | 24 - .../canvas_complex_rgba8unorm_draw.https.html | 24 - .../canvas_complex_rgba8unorm_store.https.html | 24 - ...mposite_alpha_bgra8unorm_opaque_copy.https.html | 21 - ...mposite_alpha_bgra8unorm_opaque_draw.https.html | 21 - ..._alpha_bgra8unorm_premultiplied_copy.https.html | 22 - ..._alpha_bgra8unorm_premultiplied_draw.https.html | 22 - ...posite_alpha_rgba16float_opaque_copy.https.html | 21 - ...posite_alpha_rgba16float_opaque_draw.https.html | 21 - ...alpha_rgba16float_premultiplied_copy.https.html | 22 - ...alpha_rgba16float_premultiplied_draw.https.html | 22 - ...mposite_alpha_rgba8unorm_opaque_copy.https.html | 21 - ...mposite_alpha_rgba8unorm_opaque_draw.https.html | 21 - ..._alpha_rgba8unorm_premultiplied_copy.https.html | 22 - ..._alpha_rgba8unorm_premultiplied_draw.https.html | 22 - .../reftests/canvas_image_rendering.https.html | 15 - .../reftests/delay_get_texture.html.js | 46 + .../reftests/ref/canvas_clear-ref.html | 22 - .../reftests/ref/canvas_colorspace-ref.html | 17 - .../reftests/ref/canvas_complex-ref.html | 26 - .../ref/canvas_composite_alpha_opaque-ref.html | 26 - .../canvas_composite_alpha_premultiplied-ref.html | 26 - .../reftests/ref/canvas_image_rendering-ref.html | 25 - .../reftests/ref/resize_observer-ref.html | 90 -- .../reftests/resize_observer.https.html | 24 - .../tests/webgpu/webgpu/web_platform/util.js | 416 ++++- .../webgpu/webgpu/web_platform/worker/worker.js | 20 +- .../webgpu/web_platform/worker/worker.spec.js | 72 +- .../webgpu/web_platform/worker/worker_launcher.js | 61 +- 1575 files changed, 64775 insertions(+), 13376 deletions(-) create mode 100644 testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/utils_worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/wrap_for_worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/common/util/crc32.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/common/util/parse_imports.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/idl/exposed.http.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/idl/exposed.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_clear.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_rgba16float.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_copy.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_draw.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_store.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_image_rendering.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/delay_get_texture.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_clear-ref.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_colorspace-ref.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_complex-ref.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_image_rendering-ref.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/delay_get_texture-ref.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/resize_observer-ref.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/resize_observer.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/memory_sync/texture/readonly_depth_stencil/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/rendering/3d_texture_slices/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/storage_texture/read_only/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/storage_texture/read_write/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/layout_shader_compat/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/resource_compatibility/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/createBindGroup/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/createBindGroupLayout/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/encoding/cmds/copyTextureToTexture/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/render_pipeline/depth_stencil_state/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/idl/constructable/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/print_environment/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/array/index/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/matrix/index/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/structure/index/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/vector/components/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/vector/index/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/ai_arithmetic/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/ai_comparison/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot4I8Packed/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot4U8Packed/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xI8/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xI8Clamp/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xU8/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xU8Clamp/cts.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureDimension/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureDimensions/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/unpack4xI8/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/unpack4xU8/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/workgroupUniformLoad/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/user/ptr_params/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/constructor/non_zero/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/constructor/zero_value/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/precedence/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/address_of_and_indirection/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_arithmetic/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_assignment/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_complement/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/memory_layout/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/memory_model/texture_intra_invocation_coherence/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/fragment_builtins/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/user_io/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/workgroup_size/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/stage/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/statement/compound/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/statement/discard/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/compound_statement/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/context_dependent_resolution/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/let/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/var/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/add_sub_mul/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/and_or_xor/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/comparison/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/div_rem/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/all/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/any/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/arrayLength/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/barriers/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countLeadingZeros/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countOneBits/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countTrailingZeros/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cross/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/derivatives/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/determinant/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/distance/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/dot4I8Packed/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/dot4U8Packed/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/extractBits/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/faceForward/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/firstLeadingBit/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/firstTrailingBit/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/floor/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/fract/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/frexp/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/insertBits/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/max/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/min/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/normalize/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack2x16snorm/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack2x16unorm/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4x8snorm/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4x8unorm/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xI8/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xI8Clamp/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xU8/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xU8Clamp/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/quantizeToF16/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/reflect/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/reverseBits/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/select/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/smoothstep/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/step/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/tanh/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureGather/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureGatherCompare/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureLoad/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSample/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleBias/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleCompare/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleCompareLevel/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleGrad/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleLevel/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureStore/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/trunc/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16float/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16snorm/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16unorm/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4x8snorm/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4x8unorm/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4xI8/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4xU8/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/workgroupUniformLoad/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/overload_resolution/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/precedence/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/address_of_and_indirection/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/arithmetic_negation/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/bitwise_complement/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/logical_negation/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/extension/pointer_composite_access/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/extension/readonly_and_readwrite_storage_textures/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/break_if/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/compound/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/continuing/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/requires/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/shadow_builtins/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/statement_behavior/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/layout_constraints/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/array/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/atomics/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/matrix/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/textures/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webgpu/util/texture/color_space_conversions/cts.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestAdapter.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestAdapterInfo.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestDevice.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_ArrayBuffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_detach.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_oom.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/threading.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/basic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/clearBuffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/copyBufferToBuffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/copyTextureToTexture.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/image_copy.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/programmable/state_tracking.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/queries/occlusionQuery.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/render/dynamic_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/render/state_tracking.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute/basic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute_pipeline/entry_point_name.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute_pipeline/overrides.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/device/lost.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/labels.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/buffer/multiple_buffers.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/buffer/single_buffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/texture/readonly_depth_stencil.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/texture/same_subresource.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/onSubmittedWorkDone.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/pipeline/default_layout.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/queue/writeBuffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/reflection.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/clear_value.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/resolve.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/storeOp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/storeop2.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/culling_tests.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/overrides.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/pipeline_output_targets.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/primitive_topology.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/sample_mask.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/vertex_only_render_pipeline.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/3d_texture_slices.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/basic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/color_target_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth_bias.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth_clip_clamp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/draw.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/indirect_draw.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/robust_access_index.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/stencil.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/resource_init/buffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/resource_init/texture_zero.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/anisotropy.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/filter_mode.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/lod_clamp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/shader_module/compilation_info.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/storage_texture/read_only.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/storage_texture/read_write.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/format_reinterpretation.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/read.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/write.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/uncapturederror.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/vertex_state/correctness.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/vertex_state/index_format.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/create.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/destroy.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/mapping.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/threading.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/features/query_types.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/features/texture_formats.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindGroups.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindingsPerBindGroup.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBufferSize.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxColorAttachmentBytesPerSample.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxColorAttachments.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeInvocationsPerWorkgroup.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeX.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeY.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeZ.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupsPerDimension.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxDynamicStorageBuffersPerPipelineLayout.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxDynamicUniformBuffersPerPipelineLayout.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxInterStageShaderComponents.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxInterStageShaderVariables.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxSampledTexturesPerShaderStage.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxSamplersPerShaderStage.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageBufferBindingSize.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageBuffersPerShaderStage.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageTexturesPerShaderStage.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureArrayLayers.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension1D.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension2D.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension3D.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxUniformBufferBindingSize.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxUniformBuffersPerShaderStage.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexAttributes.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexBufferArrayStride.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexBuffers.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/minStorageBufferOffsetAlignment.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/minUniformBufferOffsetAlignment.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/compute_pipeline.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createBindGroup.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createBindGroupLayout.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createPipelineLayout.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createSampler.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createTexture.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createView.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/debugMarker.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/beginComputePass.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/beginRenderPass.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/clearBuffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/compute_pass.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/copyBufferToBuffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/copyTextureToTexture.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/debug.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/index_access.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/draw.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/dynamic_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/indirect_draw.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setIndexBuffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setPipeline.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setVertexBuffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/state_tracking.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render_pass.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/setBindGroup.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/createRenderBundleEncoder.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/encoder_open_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/encoder_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/programmable/pipeline_bind_group_compat.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/begin_end.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/general.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/resolveQuerySet.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/render_bundle.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/error_scope.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/getBindGroupLayout.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/gpu_external_texture_expiration.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/buffer_related.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/buffer_texture_copies.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/layout_related.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/texture_related.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/layout_shader_compat.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/query_set/create.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/query_set/destroy.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/buffer_mapped.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/copyToTexture/CopyExternalImageToTexture.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/buffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/query_set.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/texture.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/submit.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/writeBuffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/writeTexture.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/attachment_compatibility.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/render_pass_descriptor.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/resolve.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/depth_stencil_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/fragment_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/inter_stage.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/misc.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/multisample_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/overrides.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/primitive_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/resource_compatibility.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/shader_module.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/vertex_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/buffer/in_pass_encoder.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/buffer/in_pass_misc.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_pass_encoder.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_render_common.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_render_misc.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/shader_module/entry_point.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/shader_module/overrides.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/state/device_lost/destroy.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/bgra8unorm_storage.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/destroy.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/float32_filterable.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/rg11b10ufloat_renderable.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/createBindGroup.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/createBindGroupLayout.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/cmds/copyTextureToBuffer.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/cmds/copyTextureToTexture.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/programmable/pipeline_bind_group_compat.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/depth_stencil_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/fragment_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/shader_module.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/vertex_state.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/texture/createTexture.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/texture/cubeArray.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/examples.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/idl/constants/flags.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/idl/constructable.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/print_environment.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/array/index.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/matrix/index.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/structure/index.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/vector/components.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/vector/index.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_addition.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_comparison.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_division.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_addition.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_matrix_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_scalar_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_subtraction.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_vector_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_remainder.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_subtraction.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/ai_arithmetic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/ai_comparison.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bitwise.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bitwise_shift.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bool_logical.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_addition.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_comparison.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_division.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_addition.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_matrix_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_scalar_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_subtraction.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_vector_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_remainder.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_subtraction.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_addition.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_comparison.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_division.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_addition.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_matrix_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_scalar_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_subtraction.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_vector_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_multiplication.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_remainder.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_subtraction.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/i32_arithmetic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/i32_comparison.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/u32_arithmetic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/u32_comparison.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/abs.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/acos.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/acosh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/all.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/any.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/arrayLength.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/asin.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/asinh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atan.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atan2.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atanh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicAdd.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicAnd.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicCompareExchangeWeak.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicExchange.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicLoad.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicMax.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicMin.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicOr.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicStore.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicSub.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicXor.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/bitcast.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/ceil.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/clamp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cos.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cosh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countLeadingZeros.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countOneBits.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countTrailingZeros.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cross.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/degrees.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/determinant.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/distance.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot4I8Packed.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot4U8Packed.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdx.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdxCoarse.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdxFine.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdy.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdyCoarse.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdyFine.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/exp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/exp2.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/extractBits.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/faceForward.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/firstLeadingBit.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/firstTrailingBit.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/floor.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fma.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fract.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/frexp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidth.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidthCoarse.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidthFine.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/insertBits.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/inversesqrt.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/ldexp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/length.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/log.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/log2.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/max.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/min.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/mix.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/modf.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/normalize.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16float.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16snorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16unorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4x8snorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4x8unorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xI8.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xI8Clamp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xU8.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xU8Clamp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pow.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/quantizeToF16.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/radians.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/reflect.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/refract.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/reverseBits.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/round.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/saturate.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/select.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sign.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sin.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sinh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/smoothstep.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sqrt.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/step.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/storageBarrier.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/tan.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/tanh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureDimensions.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureGather.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureGatherCompare.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureLoad.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumLayers.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumLevels.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumSamples.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSample.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleBias.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleCompare.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleCompareLevel.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleGrad.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleLevel.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureStore.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/transpose.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/trunc.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16float.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16snorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16unorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4x8snorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4x8unorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4xI8.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4xU8.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/workgroupBarrier.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/workgroupUniformLoad.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/user/ptr_params.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/constructor/non_zero.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/constructor/zero_value.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/precedence.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/address_of_and_indirection.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/af_arithmetic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/af_assignment.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_arithmetic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_assignment.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_complement.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/bool_conversion.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/bool_logical.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f16_arithmetic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f16_conversion.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f32_arithmetic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f32_conversion.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_arithmetic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_complement.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_conversion.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/u32_complement.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/u32_conversion.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/float_parse.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/call.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/complex.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/eval_order.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/for.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/if.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/loop.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/phony.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/return.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/switch.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/while.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_layout.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/adjacent.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/atomicity.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/barrier.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/coherence.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/texture_intra_invocation_coherence.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/weak.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/padding.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/robust_access.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/robust_access_vertex.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/compute_builtins.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/fragment_builtins.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/shared_structs.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/user_io.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/workgroup_size.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shadow.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/stage.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/compound.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/discard.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/increment_decrement.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/zero_init.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/const_assert/const_assert.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/compound_statement.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/const.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/context_dependent_resolution.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/let.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/override.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/ptr_spelling.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/var.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/var_access_mode.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/access/vector.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/add_sub_mul.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/and_or_xor.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/bitwise_shift.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/comparison.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/div_rem.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/abs.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/acos.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/acosh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/all.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/any.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/arrayLength.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/asin.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/asinh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atan.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atan2.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atanh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atomics.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/barriers.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/bitcast.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/ceil.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/clamp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cos.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cosh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countLeadingZeros.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countOneBits.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countTrailingZeros.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cross.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/degrees.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/derivatives.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/determinant.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/distance.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/dot4I8Packed.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/dot4U8Packed.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/exp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/exp2.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/extractBits.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/faceForward.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/firstLeadingBit.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/firstTrailingBit.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/floor.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/fract.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/frexp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/insertBits.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/inverseSqrt.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/length.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/log.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/log2.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/max.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/min.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/modf.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/normalize.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack2x16snorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack2x16unorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4x8snorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4x8unorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xI8.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xI8Clamp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xU8.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xU8Clamp.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/quantizeToF16.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/radians.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/reflect.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/reverseBits.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/round.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/saturate.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/select.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sign.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sin.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sinh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/smoothstep.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sqrt.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/step.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/tan.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/tanh.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureGather.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureGatherCompare.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureLoad.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSample.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleBias.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleCompare.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleCompareLevel.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleGrad.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleLevel.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureStore.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/trunc.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16float.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16snorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16unorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4x8snorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4x8unorm.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4xI8.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4xU8.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/workgroupUniformLoad.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/overload_resolution.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/precedence.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/address_of_and_indirection.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/arithmetic_negation.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/bitwise_complement.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/logical_negation.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/extension/pointer_composite_access.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/extension/readonly_and_readwrite_storage_textures.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/functions/alias_analysis.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/functions/restrictions.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/align.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/attribute.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/binary_ops.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/blankspace.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/break.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/break_if.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/builtin.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/comments.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/compound.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/const.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/const_assert.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/continuing.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/diagnostic.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/discard.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/enable.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/identifiers.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/literal.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/must_use.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/pipeline_stage.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/requires.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/semicolon.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/shadow_builtins.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/source.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/statement_behavior.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/unary_ops.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/var_and_let.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/binding.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/builtins.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/entry_point.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/group.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/group_and_binding.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/id.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/interpolate.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/invariant.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/layout_constraints.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/locations.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/size.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/workgroup_size.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/alias.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/array.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/atomics.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/matrix.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/struct.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/textures.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/vector.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/uniformity/uniformity.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/color_space_conversions.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/texel_data.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/texture_ok.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/configure.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/context_creation.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/getCurrentTexture.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/getPreferredCanvasFormat.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/readbackFromWebGPUCanvas.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/ImageBitmap.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/ImageData.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/canvas.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/image.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/video.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/external_texture/video.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/worker/worker.worker.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/hashes.json create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/abs.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/acos.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/acosh.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/asin.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/asinh.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atan.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atan2.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atanh.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_addition.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_division.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_logical.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_addition.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_matrix_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_scalar_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_subtraction.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_vector_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_remainder.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_subtraction.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/ai_arithmetic.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_addition.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_division.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_logical.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_addition.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_subtraction.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_remainder.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_subtraction.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_addition.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_division.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_logical.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_addition.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_subtraction.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_multiplication.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_remainder.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_subtraction.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/i32_arithmetic.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/i32_comparison.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/u32_arithmetic.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/u32_comparison.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/bitcast.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/ceil.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/clamp.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cos.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cosh.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cross.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/degrees.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/derivatives.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/determinant.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/distance.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/dot.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/exp.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/exp2.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/faceForward.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/floor.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/fma.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/fract.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/frexp.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/inverseSqrt.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/ldexp.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/length.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/log.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/log2.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/max.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/min.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/mix.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/modf.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/normalize.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/pack2x16float.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/pow.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/quantizeToF16.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/radians.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/reflect.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/refract.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/round.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/saturate.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sign.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sin.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sinh.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/smoothstep.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sqrt.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/step.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/tan.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/tanh.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/transpose.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/trunc.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/af_arithmetic.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/af_assignment.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/ai_arithmetic.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/ai_assignment.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/bool_conversion.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f16_arithmetic.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f16_conversion.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f32_arithmetic.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f32_conversion.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/i32_arithmetic.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/i32_conversion.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/u32_conversion.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16float.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16snorm.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16unorm.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack4x8snorm.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack4x8unorm.bin create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-hflip.mp4 create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-vflip.mp4 create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-hflip.mp4 create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-180.mp4 create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-270.mp4 create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-90.mp4 create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-vflip.mp4 create mode 100644 testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601.mp4 create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/readonly_depth_stencil.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/3d_texture_slices.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/texture_zero_init_test.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/storage_texture/read_only.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/storage_texture/read_write.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/resource_compatibility.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/utils.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/createBindGroup.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/createBindGroupLayout.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/encoding/cmds/copyTextureToTexture.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/render_pipeline/depth_stencil_state.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/idl/constructable.spec.js delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.http.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/multisample_info.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/print_environment.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/array/index.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/matrix/index.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/structure/index.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/vector/components.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/vector/index.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_addition.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_comparison.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_division.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_addition.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_subtraction.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_remainder.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_subtraction.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_arithmetic.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_arithmetic.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_comparison.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_addition.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_comparison.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_division.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_addition.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_matrix_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_scalar_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_subtraction.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_vector_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_remainder.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_subtraction.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_addition.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_comparison.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_division.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_addition.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_matrix_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_scalar_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_subtraction.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_vector_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_multiplication.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_remainder.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_subtraction.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_comparison.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_comparison.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/bitcast.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/derivatives.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/derivatives.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot4I8Packed.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot4U8Packed.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xI8.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xI8Clamp.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xU8.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xU8Clamp.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.cache.js delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimension.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimensions.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/texture_utils.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4xI8.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4xU8.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/workgroupUniformLoad.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/user/ptr_params.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/constructor/non_zero.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/constructor/zero_value.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expectation.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/interval_filter.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/precedence.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/address_of_and_indirection.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_arithmetic.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_assignment.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_arithmetic.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_arithmetic.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_assignment.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_assignment.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_complement.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_conversion.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_arithmetic.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_conversion.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_conversion.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_conversion.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_conversion.cache.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_layout.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/texture_intra_invocation_coherence.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/fragment_builtins.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/user_io.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/workgroup_size.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/stage.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/statement/compound.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/statement/discard.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/compound_statement.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/context_dependent_resolution.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/let.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/var.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/add_sub_mul.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/and_or_xor.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/comparison.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/div_rem.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/all.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/any.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/arrayLength.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/barriers.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countLeadingZeros.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countOneBits.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countTrailingZeros.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cross.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/derivatives.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/determinant.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/distance.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/dot4I8Packed.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/dot4U8Packed.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/extractBits.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/faceForward.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/firstLeadingBit.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/firstTrailingBit.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/floor.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/fract.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/frexp.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/insertBits.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/max.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/min.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/normalize.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack2x16snorm.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack2x16unorm.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4x8snorm.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4x8unorm.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xI8.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xI8Clamp.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xU8.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xU8Clamp.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/quantizeToF16.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/reflect.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/reverseBits.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/select.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/shader_stage_utils.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/smoothstep.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/step.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/tanh.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureGather.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureGatherCompare.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureLoad.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSample.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleBias.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleCompare.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleCompareLevel.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleGrad.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleLevel.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureStore.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/trunc.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16float.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16snorm.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16unorm.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4x8snorm.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4x8unorm.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4xI8.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4xU8.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/workgroupUniformLoad.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/overload_resolution.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/precedence.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/address_of_and_indirection.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/arithmetic_negation.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/bitwise_complement.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/logical_negation.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/extension/pointer_composite_access.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/extension/readonly_and_readwrite_storage_textures.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/break_if.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/compound.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/continuing.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/requires.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/shadow_builtins.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/statement_behavior.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/layout_constraints.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/array.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/atomics.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/matrix.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/textures.spec.js create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/color_space_conversions.spec.js delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html create mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/delay_get_texture.html.js delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_clear-ref.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_complex-ref.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_image_rendering-ref.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/resize_observer-ref.html delete mode 100644 testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.https.html (limited to 'testing/web-platform/mozilla/tests') diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js index d64245f5f8..149226a6e2 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js @@ -17,6 +17,7 @@ export { TestCaseRecorder } from '../internal/logging/test_case_recorder.js'; + export class SubcaseBatchState { constructor( recorder, @@ -124,8 +125,12 @@ export class Fixture { if (WEBGL_lose_context) WEBGL_lose_context.loseContext(); } else if ('destroy' in o) { o.destroy(); - } else { + } else if ('close' in o) { o.close(); + } else { + // HTMLVideoElement + o.src = ''; + o.srcObject = null; } } } @@ -161,6 +166,14 @@ export class Fixture { this.rec.debug(new Error(msg)); } + /** + * Log an info message. + * **Use sparingly. Use `debug()` instead if logs are only needed with debug logging enabled.** + */ + info(msg) { + this.rec.info(new Error(msg)); + } + /** Throws an exception marking the subcase as skipped. */ skip(msg) { throw new SkipTestCase(msg); diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js index 81984dbec5..5d8a59217f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js @@ -17,6 +17,21 @@ + + + + + + + + + + + + + + + @@ -24,9 +39,12 @@ export const globalTestConfig = { + enableDebugLogs: false, maxSubcasesInFlight: 500, testHeartbeatCallback: () => {}, noRaceWithRejectOnTimeout: false, unrollConstEvalLoops: false, - compatibility: false + compatibility: false, + forceFallbackAdapter: false, + logToWebSocket: false }; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js index f9f4f17fb4..3956108027 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js @@ -73,6 +73,7 @@ export class TestFileLoader extends EventTarget { query, { subqueriesToExpand = [], + fullyExpandSubtrees = [], maxChunkTime = Infinity } = {}) { @@ -82,6 +83,7 @@ export class TestFileLoader extends EventTarget { assert(q.level >= 2, () => `subqueriesToExpand entries should not be multi-file:\n ${q}`); return q; }), + fullyExpandSubtrees: fullyExpandSubtrees.map((s) => parseQuery(s)), maxChunkTime }); this.dispatchEvent(new MessageEvent('finish')); diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js index 234b7c2cc9..53d2cd4b9c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js @@ -1,19 +1,36 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { extractImportantStackTrace } from '../stack.js'; + + export class LogMessageWithStack extends Error { stackHiddenMessage = undefined; - constructor(name, ex) { - super(ex.message); + /** + * Wrap an Error (which was created to capture the stack at that point) into a + * LogMessageWithStack (which has extra stuff for good log messages). + * + * The original `ex.name` is ignored. Inclued it in the `name` parameter if it + * needs to be preserved. + */ + static wrapError(name, ex) { + return new LogMessageWithStack({ + name, + message: ex.message, + stackHiddenMessage: undefined, + stack: ex.stack, + extra: 'extra' in ex ? ex.extra : undefined + }); + } - this.name = name; - this.stack = ex.stack; - if ('extra' in ex) { - this.extra = ex.extra; - } + constructor(o) { + super(o.message); + this.name = o.name; + this.stackHiddenMessage = o.stackHiddenMessage; + this.stack = o.stack; + this.extra = o.extra; } /** Set a flag so the stack is not printed in toJSON(). */ @@ -21,6 +38,11 @@ export class LogMessageWithStack extends Error { this.stackHiddenMessage ??= stackHiddenMessage; } + /** + * Print the message for display. + * + * Note: This is toJSON instead of toString to make it easy to save logs using JSON.stringify. + */ toJSON() { let m = this.name; if (this.message) m += ': ' + this.message; @@ -33,6 +55,21 @@ export class LogMessageWithStack extends Error { } return m; } + + /** + * Flatten the message for sending over a message channel. + * + * Note `extra` may get mangled by postMessage. + */ + toRawData() { + return { + name: this.name, + message: this.message, + stackHiddenMessage: this.stackHiddenMessage, + stack: this.stack, + extra: this.extra + }; + } } /** diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js index 224af20ddc..4ec505cb69 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js @@ -1,13 +1,12 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { version } from '../version.js'; +**/import { globalTestConfig } from '../../framework/test_config.js';import { version } from '../version.js'; + import { TestCaseRecorder } from './test_case_recorder.js'; export class Logger { - static globalDebugMode = false; - results = new Map(); @@ -19,7 +18,7 @@ export class Logger { const result = { status: 'running', timems: -1 }; this.results.set(name, result); return [ - new TestCaseRecorder(result, this.overriddenDebugMode ?? Logger.globalDebugMode), + new TestCaseRecorder(result, this.overriddenDebugMode ?? globalTestConfig.enableDebugLogs), result]; } diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js index a7eb281daf..cd4d0e86f1 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js @@ -1,4 +1,34 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ // MAINTENANCE_TODO: Add warn expectations -export {}; \ No newline at end of file + + + + + + + + + + + + + +/** + * Raw data for a test log message. + * + * This form is sendable over a message channel, except `extra` may get mangled. + */ + + + + + + + + +/** + * Test case results in a form sendable over a message channel. + * + * Note `extra` may get mangled by postMessage. + */export {}; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js index 7b9a5302ce..5b2a4e8b8e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js @@ -45,8 +45,6 @@ export class TestCaseRecorder { logs = []; logLinesAtCurrentSeverity = 0; debugging = false; - /** Used to dedup log messages which have identical stacks. */ - messagesForPreviouslySeenStacks = new Map(); constructor(result, debugging) { this.result = result; @@ -143,13 +141,15 @@ export class TestCaseRecorder { this.skipped(ex); return; } - this.logImpl(LogSeverity.ThrewException, 'EXCEPTION', ex); + // logImpl will discard the original error's ex.name. Preserve it here. + const name = ex instanceof Error ? `EXCEPTION: ${ex.name}` : 'EXCEPTION'; + this.logImpl(LogSeverity.ThrewException, name, ex); } logImpl(level, name, baseException) { assert(baseException instanceof Error, 'test threw a non-Error object'); globalTestConfig.testHeartbeatCallback(); - const logMessage = new LogMessageWithStack(name, baseException); + const logMessage = LogMessageWithStack.wrapError(name, baseException); // Final case status should be the "worst" of all log entries. if (this.inSubCase) { diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js index 8af64919a2..f2bb1b62f3 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js @@ -58,7 +58,10 @@ function compareOneLevel(ordering, aIsBig, bIsBig) { return Ordering.Unordered; } -function comparePaths(a, b) { +/** + * Compare two file paths, or file-local test paths, returning an Ordering between the two. + */ +export function comparePaths(a, b) { const shorter = Math.min(a.length, b.length); for (let i = 0; i < shorter; ++i) { diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js index b66b16ce91..4c8bf32341 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js @@ -17,12 +17,49 @@ import { import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './separators.js'; import { validQueryPart } from './validQueryPart.js'; -export function parseQuery(s) { +/** + * converts foo/bar/src/webgpu/this/that/file.spec.ts to webgpu:this,that,file,* + */ +function convertPathToQuery(path) { + // removes .spec.ts and splits by directory separators. + const parts = path.substring(0, path.length - 8).split(/\/|\\/g); + // Gets parts only after the last `src`. Example: returns ['webgpu', 'foo', 'bar', 'test'] + // for ['Users', 'me', 'src', 'cts', 'src', 'webgpu', 'foo', 'bar', 'test'] + const partsAfterSrc = parts.slice(parts.lastIndexOf('src') + 1); + const suite = partsAfterSrc.shift(); + return `${suite}:${partsAfterSrc.join(',')},*`; +} + +/** + * If a query looks like a path (ends in .spec.ts and has directory separators) + * then convert try to convert it to a query. + */ +function convertPathLikeToQuery(queryOrPath) { + return queryOrPath.endsWith('.spec.ts') && ( + queryOrPath.includes('/') || queryOrPath.includes('\\')) ? + convertPathToQuery(queryOrPath) : + queryOrPath; +} + +/** + * Convert long suite names (the part before the first colon) to the + * shortest last word + * foo.bar.moo:test,subtest,foo -> moo:test,subtest,foo + */ +function shortenSuiteName(query) { + const parts = query.split(':'); + // converts foo.bar.moo to moo + const suite = parts.shift()?.replace(/.*\.(\w+)$/, '$1'); + return [suite, ...parts].join(':'); +} + +export function parseQuery(queryLike) { try { - return parseQueryImpl(s); + const query = shortenSuiteName(convertPathLikeToQuery(queryLike)); + return parseQueryImpl(query); } catch (ex) { if (ex instanceof Error) { - ex.message += '\n on: ' + s; + ex.message += `\n on: ${queryLike}`; } throw ex; } diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js index e1db875061..8fd443652a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js @@ -1,6 +1,6 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { optionEnabled } from '../../runtime/helper/options.js';import { assert, unreachable } from '../../util/util.js'; +**/import { optionWorkerMode } from '../../runtime/helper/options.js';import { assert, unreachable } from '../../util/util.js'; import { compareQueries, Ordering } from './compare.js'; @@ -188,12 +188,12 @@ wptURL) assert( expectationURL.pathname === wptURL.pathname, `Invalid expectation path ${expectationURL.pathname} -Expectation should be of the form path/to/cts.https.html?worker=0&q=suite:test_path:test_name:foo=1;bar=2;... +Expectation should be of the form path/to/cts.https.html?debug=0&q=suite:test_path:test_name:foo=1;bar=2;... ` ); const params = expectationURL.searchParams; - if (optionEnabled('worker', params) !== optionEnabled('worker', wptURL.searchParams)) { + if (optionWorkerMode('worker', params) !== optionWorkerMode('worker', wptURL.searchParams)) { continue; } diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js index 3db409ffe7..2772194667 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js @@ -34,7 +34,7 @@ import { validQueryPart } from '../internal/query/validQueryPart.js'; import { assert, unreachable } from '../util/util.js'; -import { logToWebsocket } from './websocket_logger.js'; +import { logToWebSocket } from './websocket_logger.js'; @@ -294,9 +294,11 @@ class TestBuilder { (this.description ? this.description + '\n\n' : '') + 'TODO: .unimplemented()'; this.isUnimplemented = true; - this.testFn = () => { + // Use the beforeFn to skip the test, so we don't have to iterate the subcases. + this.beforeFn = () => { throw new SkipTestCase('test unimplemented'); }; + this.testFn = () => {}; } /** Perform various validation/"lint" chenks. */ @@ -350,7 +352,7 @@ class TestBuilder { const testcaseStringUnique = stringifyPublicParamsUniquely(params); assert( !seen.has(testcaseStringUnique), - `Duplicate public test case+subcase params for test ${testPathString}: ${testcaseString}` + `Duplicate public test case+subcase params for test ${testPathString}: ${testcaseString} (${caseQuery})` ); seen.add(testcaseStringUnique); } @@ -737,7 +739,7 @@ class RunCaseSpecific { timems: rec.result.timems, nonskippedSubcaseCount: rec.nonskippedSubcaseCount }; - logToWebsocket(JSON.stringify(msg)); + logToWebSocket(JSON.stringify(msg)); } } } \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js index 81a15cf712..7ea1c066f5 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js @@ -2,5 +2,5 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ // A listing of all specs within a single suite. This is the (awaited) type of // `groups` in '{cts,unittests}/listing.ts' and `listing` in the auto-generated -// 'out/{cts,unittests}/listing.js' files (see tools/gen_listings). +// 'out/{cts,unittests}/listing.js' files (see tools/gen_listings_and_webworkers). export {}; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js index 8f1e6bad66..3b33542752 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js @@ -286,6 +286,7 @@ loader, queryToLoad, { subqueriesToExpand, + fullyExpandSubtrees = [], maxChunkTime = Infinity }) { @@ -303,6 +304,10 @@ queryToLoad, // If toExpand == subquery, no expansion is needed (but it's still "seen"). if (ordering === Ordering.Equal) seenSubqueriesToExpand[i] = true; return ordering !== Ordering.StrictSubset; + }) && + fullyExpandSubtrees.every((toExpand) => { + const ordering = compareQueries(toExpand, subquery); + return ordering === Ordering.Unordered; }); // L0 = suite-level, e.g. suite:* diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js index 7a632d5635..d300878e0e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js @@ -1,3 +1,3 @@ // AUTO-GENERATED - DO NOT EDIT. See tools/gen_version. -export const version = '41f89e77b67e6b66cb017be4e00235a0a9429ca7'; +export const version = '5c8510ec0d47180d1cd4dd92790b5a69335e162c'; diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/websocket_logger.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/websocket_logger.js index 7a8f92b1a8..1790e5632d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/internal/websocket_logger.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/websocket_logger.js @@ -1,19 +1,24 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/ /** +**/import { globalTestConfig } from '../framework/test_config.js'; /** * - 'uninitialized' means we haven't tried to connect yet * - Promise means it's pending * - 'failed' means it failed (this is the most common case, where the logger isn't running) * - WebSocket means it succeeded - */let connection = 'uninitialized'; + */ +let connection = +'uninitialized'; /** - * Log a string to a websocket at `localhost:59497`. See `tools/websocket-logger`. + * If the logToWebSocket option is enabled (?log_to_web_socket=1 in browser, + * --log-to-web-socket on command line, or enable it by default in options.ts), + * log a string to a websocket at `localhost:59497`. See `tools/websocket-logger`. * - * This does nothing if a connection couldn't be established on the first call. + * This does nothing if a logToWebSocket is not enabled, or if a connection + * couldn't be established on the first call. */ -export function logToWebsocket(msg) { - if (connection === 'failed') { +export function logToWebSocket(msg) { + if (!globalTestConfig.logToWebSocket || connection === 'failed') { return; } diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js index 139c3bc29f..01b7d95889 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js @@ -1,11 +1,14 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/let windowURL = undefined;function getWindowURL() {if (windowURL === undefined) { +**/import { unreachable } from '../../util/util.js';let windowURL = undefined; +function getWindowURL() { + if (windowURL === undefined) { windowURL = new URL(window.location.toString()); } return windowURL; } +/** Parse a runner option that is always boolean-typed. False if missing or '0'. */ export function optionEnabled( opt, searchParams = getWindowURL().searchParams) @@ -14,11 +17,32 @@ searchParams = getWindowURL().searchParams) return val !== null && val !== '0'; } +/** Parse a runner option that is string-typed. If the option is missing, returns `null`. */ export function optionString( opt, searchParams = getWindowURL().searchParams) { - return searchParams.get(opt) || ''; + return searchParams.get(opt); +} + +/** Runtime modes for running tests in different types of workers. */ + +/** Parse a runner option for different worker modes (as in `?worker=shared`). Null if no worker. */ +export function optionWorkerMode( +opt, +searchParams = getWindowURL().searchParams) +{ + const value = searchParams.get(opt); + if (value === null || value === '0') { + return null; + } else if (value === 'service') { + return 'service'; + } else if (value === 'shared') { + return 'shared'; + } else if (value === '' || value === '1' || value === 'dedicated') { + return 'dedicated'; + } + unreachable('invalid worker= option value'); } /** @@ -32,12 +56,16 @@ searchParams = getWindowURL().searchParams) + + export const kDefaultCTSOptions = { - worker: false, + worker: null, debug: true, compatibility: false, + forceFallbackAdapter: false, unrollConstEvalLoops: false, - powerPreference: '' + powerPreference: null, + logToWebSocket: false }; /** @@ -59,19 +87,30 @@ export const kDefaultCTSOptions = { * Options to the CTS. */ export const kCTSOptionsInfo = { - worker: { description: 'run in a worker' }, + worker: { + description: 'run in a worker', + parser: optionWorkerMode, + selectValueDescriptions: [ + { value: null, description: 'no worker' }, + { value: 'dedicated', description: 'dedicated worker' }, + { value: 'shared', description: 'shared worker' }, + { value: 'service', description: 'service worker' }] + + }, debug: { description: 'show more info' }, compatibility: { description: 'run in compatibility mode' }, + forceFallbackAdapter: { description: 'pass forceFallbackAdapter: true to requestAdapter' }, unrollConstEvalLoops: { description: 'unroll const eval loops in WGSL' }, powerPreference: { description: 'set default powerPreference for some tests', parser: optionString, selectValueDescriptions: [ - { value: '', description: 'default' }, + { value: null, description: 'default' }, { value: 'low-power', description: 'low-power' }, { value: 'high-performance', description: 'high-performance' }] - } + }, + logToWebSocket: { description: 'send some logs to ws://localhost:59497/' } }; /** diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js index a0f13c54af..c5df860d0b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js @@ -1,15 +1,11 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { setBaseResourcePath } from '../../framework/resources.js';import { globalTestConfig } from '../../framework/test_config.js';import { DefaultTestFileLoader } from '../../internal/file_loader.js'; -import { Logger } from '../../internal/logging/logger.js'; -import { parseQuery } from '../../internal/query/parseQuery.js'; - -import { setDefaultRequestAdapterOptions } from '../../util/navigator_gpu.js'; +**/import { setBaseResourcePath } from '../../framework/resources.js';import { DefaultTestFileLoader } from '../../internal/file_loader.js';import { parseQuery } from '../../internal/query/parseQuery.js'; import { assert } from '../../util/util.js'; +import { setupWorkerEnvironment } from './utils_worker.js'; - -// Should be DedicatedWorkerGlobalScope, but importing lib "webworker" conflicts with lib "dom". +// Should be WorkerGlobalScope, but importing lib "webworker" conflicts with lib "dom". @@ -17,25 +13,10 @@ const loader = new DefaultTestFileLoader(); setBaseResourcePath('../../../resources'); -self.onmessage = async (ev) => { - const query = ev.data.query; - const expectations = ev.data.expectations; - const ctsOptions = ev.data.ctsOptions; - - const { debug, unrollConstEvalLoops, powerPreference, compatibility } = ctsOptions; - globalTestConfig.unrollConstEvalLoops = unrollConstEvalLoops; - globalTestConfig.compatibility = compatibility; - - Logger.globalDebugMode = debug; - const log = new Logger(); +async function reportTestResults(ev) { + const { query, expectations, ctsOptions } = ev.data; - if (powerPreference || compatibility) { - setDefaultRequestAdapterOptions({ - ...(powerPreference && { powerPreference }), - // MAINTENANCE_TODO: Change this to whatever the option ends up being - ...(compatibility && { compatibilityMode: true }) - }); - } + const log = setupWorkerEnvironment(ctsOptions); const testcases = Array.from(await loader.loadCases(parseQuery(query))); assert(testcases.length === 1, 'worker query resulted in != 1 cases'); @@ -44,5 +25,23 @@ self.onmessage = async (ev) => { const [rec, result] = log.record(testcase.query.toString()); await testcase.run(rec, expectations); - self.postMessage({ query, result }); + this.postMessage({ + query, + result: { + ...result, + logs: result.logs?.map((l) => l.toRawData()) + } + }); +} + +self.onmessage = (ev) => { + void reportTestResults.call(ev.source || self, ev); +}; + +self.onconnect = (event) => { + const port = event.ports[0]; + + port.onmessage = (ev) => { + void reportTestResults.call(port, ev); + }; }; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js index 1d65394180..4039aa1332 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js @@ -2,48 +2,190 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { LogMessageWithStack } from '../../internal/logging/log_message.js'; +import { timeout } from '../../util/timeout.js'; +import { assert } from '../../util/util.js'; import { kDefaultCTSOptions } from './options.js'; -export class TestWorker { +/** Query all currently-registered service workers, and unregister them. */ +function unregisterAllServiceWorkers() { + void navigator.serviceWorker.getRegistrations().then((registrations) => { + for (const registration of registrations) { + void registration.unregister(); + } + }); +} + +// NOTE: This code runs on startup for any runtime with worker support. Here, we use that chance to +// delete any leaked service workers, and register to clean up after ourselves at shutdown. +unregisterAllServiceWorkers(); +window.addEventListener('beforeunload', () => { + unregisterAllServiceWorkers(); +}); + +class TestBaseWorker { resolvers = new Map(); - constructor(ctsOptions) { - this.ctsOptions = { ...(ctsOptions || kDefaultCTSOptions), ...{ worker: true } }; - const selfPath = import.meta.url; - const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/')); - const workerPath = selfPathDir + '/test_worker-worker.js'; - this.worker = new Worker(workerPath, { type: 'module' }); - this.worker.onmessage = (ev) => { - const query = ev.data.query; - const result = ev.data.result; - if (result.logs) { - for (const l of result.logs) { - Object.setPrototypeOf(l, LogMessageWithStack.prototype); - } - } - this.resolvers.get(query)(result); + constructor(worker, ctsOptions) { + this.ctsOptions = { ...(ctsOptions || kDefaultCTSOptions), ...{ worker } }; + } + + onmessage(ev) { + const query = ev.data.query; + const transferredResult = ev.data.result; - // MAINTENANCE_TODO(kainino0x): update the Logger with this result (or don't have a logger and - // update the entire results JSON somehow at some point). + const result = { + status: transferredResult.status, + timems: transferredResult.timems, + logs: transferredResult.logs?.map((l) => new LogMessageWithStack(l)) }; + + this.resolvers.get(query)(result); + this.resolvers.delete(query); + + // MAINTENANCE_TODO(kainino0x): update the Logger with this result (or don't have a logger and + // update the entire results JSON somehow at some point). } - async run( - rec, + makeRequestAndRecordResult( + target, query, - expectations = []) + expectations) { - this.worker.postMessage({ + const request = { query, expectations, ctsOptions: this.ctsOptions - }); - const workerResult = await new Promise((resolve) => { + }; + target.postMessage(request); + + return new Promise((resolve) => { + assert(!this.resolvers.has(query), "can't request same query twice simultaneously"); this.resolvers.set(query, resolve); }); - rec.injectResult(workerResult); + } + + async run( + rec, + query, + expectations = []) + { + try { + rec.injectResult(await this.runImpl(query, expectations)); + } catch (ex) { + rec.start(); + rec.threw(ex); + rec.finish(); + } + } + + + + + +} + +export class TestDedicatedWorker extends TestBaseWorker { + + + constructor(ctsOptions) { + super('dedicated', ctsOptions); + try { + if (typeof Worker === 'undefined') { + throw new Error('Dedicated Workers not available'); + } + + const selfPath = import.meta.url; + const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/')); + const workerPath = selfPathDir + '/test_worker-worker.js'; + this.worker = new Worker(workerPath, { type: 'module' }); + this.worker.onmessage = (ev) => this.onmessage(ev); + } catch (ex) { + assert(ex instanceof Error); + // Save the exception to re-throw in runImpl(). + this.worker = ex; + } + } + + runImpl(query, expectations = []) { + if (this.worker instanceof Worker) { + return this.makeRequestAndRecordResult(this.worker, query, expectations); + } else { + throw this.worker; + } + } +} + +/** @deprecated Use TestDedicatedWorker instead. */ +export class TestWorker extends TestDedicatedWorker {} + +export class TestSharedWorker extends TestBaseWorker { + /** MessagePort to the SharedWorker, or an Error if it couldn't be initialized. */ + + + constructor(ctsOptions) { + super('shared', ctsOptions); + try { + if (typeof SharedWorker === 'undefined') { + throw new Error('Shared Workers not available'); + } + + const selfPath = import.meta.url; + const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/')); + const workerPath = selfPathDir + '/test_worker-worker.js'; + const worker = new SharedWorker(workerPath, { type: 'module' }); + this.port = worker.port; + this.port.start(); + this.port.onmessage = (ev) => this.onmessage(ev); + } catch (ex) { + assert(ex instanceof Error); + // Save the exception to re-throw in runImpl(). + this.port = ex; + } + } + + runImpl(query, expectations = []) { + if (this.port instanceof MessagePort) { + return this.makeRequestAndRecordResult(this.port, query, expectations); + } else { + throw this.port; + } + } +} + +export class TestServiceWorker extends TestBaseWorker { + constructor(ctsOptions) { + super('service', ctsOptions); + } + + async runImpl(query, expectations = []) { + if (!('serviceWorker' in navigator)) { + throw new Error('Service Workers not available'); + } + const [suite, name] = query.split(':', 2); + const fileName = name.split(',').join('/'); + + const selfPath = import.meta.url; + const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/')); + // Construct the path to the worker file, then use URL to resolve the `../` components. + const serviceWorkerURL = new URL( + `${selfPathDir}/../../../${suite}/webworker/${fileName}.worker.js` + ).toString(); + + // If a registration already exists for this path, it will be ignored. + const registration = await navigator.serviceWorker.register(serviceWorkerURL, { + type: 'module' + }); + // Make sure the registration we just requested is active. (We don't worry about it being + // outdated from a previous page load, because we wipe all service workers on shutdown/startup.) + while (!registration.active || registration.active.scriptURL !== serviceWorkerURL) { + await new Promise((resolve) => timeout(resolve, 0)); + } + const serviceWorker = registration.active; + + navigator.serviceWorker.onmessage = (ev) => this.onmessage(ev); + return this.makeRequestAndRecordResult(serviceWorker, query, expectations); } } \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/utils_worker.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/utils_worker.js new file mode 100644 index 0000000000..5a34070e14 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/utils_worker.js @@ -0,0 +1,35 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { globalTestConfig } from '../../framework/test_config.js';import { Logger } from '../../internal/logging/logger.js'; +import { setDefaultRequestAdapterOptions } from '../../util/navigator_gpu.js'; + + + + + + + + + +/** + * Set config environment for workers with ctsOptions and return a Logger. + */ +export function setupWorkerEnvironment(ctsOptions) { + const { powerPreference, compatibility } = ctsOptions; + globalTestConfig.enableDebugLogs = ctsOptions.debug; + globalTestConfig.unrollConstEvalLoops = ctsOptions.unrollConstEvalLoops; + globalTestConfig.compatibility = compatibility; + globalTestConfig.logToWebSocket = ctsOptions.logToWebSocket; + + const log = new Logger(); + + if (powerPreference || compatibility) { + setDefaultRequestAdapterOptions({ + ...(powerPreference && { powerPreference }), + // MAINTENANCE_TODO: Change this to whatever the option ends up being + ...(compatibility && { compatibilityMode: true }) + }); + } + + return log; +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/wrap_for_worker.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/wrap_for_worker.js new file mode 100644 index 0000000000..69b5f375f1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/wrap_for_worker.js @@ -0,0 +1,54 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { LogMessageWithStack } from '../../internal/logging/log_message.js';import { comparePaths, comparePublicParamsPaths, Ordering } from '../../internal/query/compare.js'; +import { parseQuery } from '../../internal/query/parseQuery.js'; +import { TestQuerySingleCase } from '../../internal/query/query.js'; + +import { assert } from '../../util/util.js'; + +import { setupWorkerEnvironment } from './utils_worker.js'; + +/** + * Sets up the currently running Web Worker to wrap the TestGroup object `g`. + * `g` is the `g` exported from a `.spec.ts` file: a TestGroupBuilder interface, + * which underneath is actually a TestGroup object. + * + * This is used in the generated `.worker.js` files that are generated to use as service workers. + */ +export function wrapTestGroupForWorker(g) { + self.onmessage = async (ev) => { + const { query, expectations, ctsOptions } = ev.data; + try { + const log = setupWorkerEnvironment(ctsOptions); + + const testQuery = parseQuery(query); + assert(testQuery instanceof TestQuerySingleCase); + let testcase = null; + for (const t of g.iterate()) { + if (comparePaths(t.testPath, testQuery.testPathParts) !== Ordering.Equal) { + continue; + } + for (const c of t.iterate(testQuery.params)) { + if (comparePublicParamsPaths(c.id.params, testQuery.params) === Ordering.Equal) { + testcase = c; + } + } + } + assert(!!testcase, 'testcase not found'); + const [rec, result] = log.record(query); + await testcase.run(rec, testQuery, expectations); + + ev.source?.postMessage({ query, result }); + } catch (thrown) { + const ex = thrown instanceof Error ? thrown : new Error(`${thrown}`); + ev.source?.postMessage({ + query, + result: { + status: 'fail', + timems: 0, + logs: [LogMessageWithStack.wrapError('INTERNAL', ex)] + } + }); + } + }; +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js index 97c6a3886e..d1a025d1f8 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js @@ -8,8 +8,8 @@ import { parseQuery } from '../internal/query/parseQuery.js'; import { parseExpectationsForTestQuery, relativeQueryString } from '../internal/query/query.js'; import { assert } from '../util/util.js'; -import { optionEnabled } from './helper/options.js'; -import { TestWorker } from './helper/test_worker.js'; +import { optionEnabled, optionWorkerMode } from './helper/options.js'; +import { TestDedicatedWorker, TestServiceWorker, TestSharedWorker } from './helper/test_worker.js'; // testharness.js API (https://web-platform-tests.org/writing-tests/testharness-api.html) @@ -31,8 +31,10 @@ setup({ }); void (async () => { - const workerEnabled = optionEnabled('worker'); - const worker = workerEnabled ? new TestWorker() : undefined; + const workerString = optionWorkerMode('worker'); + const dedicatedWorker = workerString === 'dedicated' ? new TestDedicatedWorker() : undefined; + const sharedWorker = workerString === 'shared' ? new TestSharedWorker() : undefined; + const serviceWorker = workerString === 'service' ? new TestServiceWorker() : undefined; globalTestConfig.unrollConstEvalLoops = optionEnabled('unroll_const_eval_loops'); @@ -63,8 +65,12 @@ void (async () => { const wpt_fn = async () => { const [rec, res] = log.record(name); - if (worker) { - await worker.run(rec, name, expectations); + if (dedicatedWorker) { + await dedicatedWorker.run(rec, name, expectations); + } else if (sharedWorker) { + await sharedWorker.run(rec, name, expectations); + } else if (serviceWorker) { + await serviceWorker.run(rec, name, expectations); } else { await testcase.run(rec, expectations); } diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/crc32.js b/testing/web-platform/mozilla/tests/webgpu/common/util/crc32.js new file mode 100644 index 0000000000..392d3b947c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/crc32.js @@ -0,0 +1,57 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ /// CRC32 immutable lookup table data. +const kCRC32LUT = [0, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, +0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, +0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, +0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, +0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, +0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, +0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, +0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, +0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, +0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, +0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, +0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, +0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, +0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, +0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, +0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, +0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, +0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, +0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, +0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, +0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, +0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, +0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, +0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, +0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, +0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, +0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, +0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, +0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, +0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, +0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d]; + + +/** + * @param str the input string + * @returns the CRC32 of the input string + * @see https://en.wikipedia.org/wiki/Cyclic_redundancy_check#CRC-32_algorithm + */ +export function crc32(str) { + const utf8 = new TextEncoder().encode(str); + const u32 = new Uint32Array(1); + + u32[0] = 0xffffffff; + for (const c of utf8) { + u32[0] = u32[0] >>> 8 ^ kCRC32LUT[u32[0] & 0xff ^ c]; + } + u32[0] = u32[0] ^ 0xffffffff; + return u32[0]; +} + +/** @returns the input number has a 8-character hex string */ +export function toHexString(number) { + return ('00000000' + number.toString(16)).slice(-8); +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/parse_imports.js b/testing/web-platform/mozilla/tests/webgpu/common/util/parse_imports.js new file mode 100644 index 0000000000..bc970572b1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/parse_imports.js @@ -0,0 +1,36 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ /** + * Parses all the paths of the typescript `import` statements from content + * @param path the current path of the file + * @param content the file content + * @returns the list of import paths + */export function parseImports(path, content) {const out = []; + const importRE = /^import\s[^'"]*(['"])([./\w]*)(\1);/gm; + let importMatch; + while (importMatch = importRE.exec(content)) { + const importPath = importMatch[2].replace(`'`, '').replace(`"`, ''); + out.push(joinPath(path, importPath)); + } + return out; +} + +function joinPath(a, b) { + const aParts = a.split('/'); + const bParts = b.split('/'); + aParts.pop(); // remove file + let bStart = 0; + while (aParts.length > 0) { + switch (bParts[bStart]) { + case '.': + bStart++; + continue; + case '..': + aParts.pop(); + bStart++; + continue; + } + break; + } + return [...aParts, ...bParts.slice(bStart)].join('/'); +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/util.js b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js index 34934af6c0..d0a3c0a8f7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/common/util/util.js +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js @@ -1,7 +1,6 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { Float16Array } from '../../external/petamoriken/float16/float16.js';import { SkipTestCase } from '../framework/fixture.js';import { globalTestConfig } from '../framework/test_config.js'; -import { Logger } from '../internal/logging/logger.js'; import { keysOf } from './data_tables.js'; import { timeout } from './timeout.js'; @@ -24,7 +23,7 @@ export class ErrorWithExtra extends Error { super(message); const oldExtras = baseOrMessage instanceof ErrorWithExtra ? baseOrMessage.extra : {}; - this.extra = Logger.globalDebugMode ? + this.extra = globalTestConfig.enableDebugLogs ? { ...oldExtras, ...newExtra() } : { omitted: 'pass ?debug=1' }; } @@ -303,7 +302,9 @@ new Int16Array(), new Int32Array(), new Float16Array(), new Float32Array(), -new Float64Array()]; +new Float64Array(), +new BigInt64Array(), +new BigUint64Array()]; diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/idl/exposed.http.html b/testing/web-platform/mozilla/tests/webgpu/cts/idl/exposed.http.html new file mode 100644 index 0000000000..94a814d005 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/idl/exposed.http.html @@ -0,0 +1,13 @@ + + + + + WebGPU exposed items (non-HTTPS) + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/idl/exposed.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/idl/exposed.https.html new file mode 100644 index 0000000000..8d421b7020 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/idl/exposed.https.html @@ -0,0 +1,13 @@ + + + + + WebGPU exposed items (HTTPS) + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_clear.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_clear.https.html new file mode 100644 index 0000000000..3639d3ca82 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_clear.https.html @@ -0,0 +1,12 @@ + + + WebGPU canvas_clear + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html new file mode 100644 index 0000000000..a0068dbf7a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html @@ -0,0 +1,23 @@ + + + WebGPU canvas_colorspace_bgra8unorm + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_rgba16float.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_rgba16float.https.html new file mode 100644 index 0000000000..b38fef9591 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_rgba16float.https.html @@ -0,0 +1,23 @@ + + + WebGPU canvas_colorspace_rgba16float + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html new file mode 100644 index 0000000000..404aed360c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html @@ -0,0 +1,23 @@ + + + WebGPU canvas_colorspace_rgba8unorm + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html new file mode 100644 index 0000000000..d378bdfcf5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html @@ -0,0 +1,24 @@ + + + WebGPU canvas_complex_bgra8unorm_copy + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html new file mode 100644 index 0000000000..99049e6e32 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html @@ -0,0 +1,24 @@ + + + WebGPU canvas_complex_bgra8unorm_draw + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_copy.https.html new file mode 100644 index 0000000000..400afa121b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_copy.https.html @@ -0,0 +1,24 @@ + + + WebGPU canvas_complex_rgba16float_copy + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_draw.https.html new file mode 100644 index 0000000000..a647fc2956 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_draw.https.html @@ -0,0 +1,24 @@ + + + WebGPU canvas_complex_rgba16float_draw + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_store.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_store.https.html new file mode 100644 index 0000000000..b812129b0b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba16float_store.https.html @@ -0,0 +1,24 @@ + + + WebGPU canvas_complex_rgba16float_store + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html new file mode 100644 index 0000000000..d2570a3bdf --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html @@ -0,0 +1,24 @@ + + + WebGPU canvas_complex_rgba8unorm_copy + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html new file mode 100644 index 0000000000..647a829259 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html @@ -0,0 +1,24 @@ + + + WebGPU canvas_complex_rgba8unorm_draw + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html new file mode 100644 index 0000000000..b82745658e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html @@ -0,0 +1,24 @@ + + + WebGPU canvas_complex_rgba8unorm_store + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html new file mode 100644 index 0000000000..60e8417c16 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html @@ -0,0 +1,21 @@ + + + WebGPU canvas_composite_alpha_bgra8unorm_opaque + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html new file mode 100644 index 0000000000..c0280a2a99 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html @@ -0,0 +1,21 @@ + + + WebGPU canvas_composite_alpha_bgra8unorm_opaque + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html new file mode 100644 index 0000000000..5c3b888fee --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html @@ -0,0 +1,22 @@ + + + WebGPU canvas_composite_alpha_bgra8unorm_premultiplied + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html new file mode 100644 index 0000000000..81335296c0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html @@ -0,0 +1,22 @@ + + + WebGPU canvas_composite_alpha_bgra8unorm_premultiplied + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html new file mode 100644 index 0000000000..4471f08480 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html @@ -0,0 +1,21 @@ + + + WebGPU canvas_composite_alpha_rgba16float_opaque + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html new file mode 100644 index 0000000000..11f0e73ec2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html @@ -0,0 +1,21 @@ + + + WebGPU canvas_composite_alpha_rgba16float_opaque + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html new file mode 100644 index 0000000000..28e2553fed --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html @@ -0,0 +1,22 @@ + + + WebGPU canvas_composite_alpha_rgba16float_premultiplied + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html new file mode 100644 index 0000000000..ca76fac7cd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html @@ -0,0 +1,22 @@ + + + WebGPU canvas_composite_alpha_rgba16float_premultiplied + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html new file mode 100644 index 0000000000..7147631d19 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html @@ -0,0 +1,21 @@ + + + WebGPU canvas_composite_alpha_rgba8unorm_opaque + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html new file mode 100644 index 0000000000..ec2bb05ed3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html @@ -0,0 +1,21 @@ + + + WebGPU canvas_composite_alpha_rgba8unorm_opaque + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html new file mode 100644 index 0000000000..7936e0b81c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html @@ -0,0 +1,22 @@ + + + WebGPU canvas_composite_alpha_rgba8unorm_premultiplied + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html new file mode 100644 index 0000000000..da48abd2be --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html @@ -0,0 +1,22 @@ + + + WebGPU canvas_composite_alpha_rgba8unorm_premultiplied + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_image_rendering.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_image_rendering.https.html new file mode 100644 index 0000000000..6a64b3da5d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/canvas_image_rendering.https.html @@ -0,0 +1,15 @@ + + + WebGPU canvas_image_rendering + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/delay_get_texture.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/delay_get_texture.https.html new file mode 100644 index 0000000000..054c352ac2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/delay_get_texture.https.html @@ -0,0 +1,10 @@ + + + WebGPU delay getCurrentTexture + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_clear-ref.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_clear-ref.html new file mode 100644 index 0000000000..e37b78c3a6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_clear-ref.html @@ -0,0 +1,22 @@ + + + WebGPU canvas_clear (ref) + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_colorspace-ref.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_colorspace-ref.html new file mode 100644 index 0000000000..a6da9f6748 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_colorspace-ref.html @@ -0,0 +1,17 @@ + + + WebGPU canvas_colorspace (ref) + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_complex-ref.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_complex-ref.html new file mode 100644 index 0000000000..b1d46c108a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_complex-ref.html @@ -0,0 +1,26 @@ + + + WebGPU canvas_complex (ref) + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html new file mode 100644 index 0000000000..94b9486514 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html @@ -0,0 +1,26 @@ + + + WebGPU canvas_composite_alpha_premultiplied (ref) + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html new file mode 100644 index 0000000000..635625ecc7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html @@ -0,0 +1,26 @@ + + + WebGPU canvas_composite_alpha_premultiplied (ref) + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_image_rendering-ref.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_image_rendering-ref.html new file mode 100644 index 0000000000..56e3453c56 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/canvas_image_rendering-ref.html @@ -0,0 +1,25 @@ + + + WebGPU canvas_image_rendering (ref) + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/delay_get_texture-ref.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/delay_get_texture-ref.html new file mode 100644 index 0000000000..fcf485dbe1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/delay_get_texture-ref.html @@ -0,0 +1,17 @@ + + + WebGPU delay getCurrentTexture (ref) + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/resize_observer-ref.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/resize_observer-ref.html new file mode 100644 index 0000000000..5259a25c27 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/ref/resize_observer-ref.html @@ -0,0 +1,90 @@ + + + WebGPU ResizeObserver test (ref) + + + + +
+
+ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/resize_observer.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/resize_observer.https.html new file mode 100644 index 0000000000..2845cc29eb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/web_platform/reftests/resize_observer.https.html @@ -0,0 +1,24 @@ + + + WebGPU resize_observer + + + + + + +
+
+ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/adapter/requestDevice/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/adapter/requestDevice/cts.https.html index edd19233c4..e2551568b7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/adapter/requestDevice/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/adapter/requestDevice/cts.https.html @@ -38,6 +38,7 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/memory_sync/texture/readonly_depth_stencil/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/memory_sync/texture/readonly_depth_stencil/cts.https.html new file mode 100644 index 0000000000..1da55c88aa --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/memory_sync/texture/readonly_depth_stencil/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/reflection/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/reflection/cts.https.html index e12ab28926..a9b8bdcf07 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/reflection/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/reflection/cts.https.html @@ -33,6 +33,9 @@ + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/rendering/3d_texture_slices/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/rendering/3d_texture_slices/cts.https.html new file mode 100644 index 0000000000..38ab7ddbe4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/rendering/3d_texture_slices/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/storage_texture/read_only/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/storage_texture/read_only/cts.https.html new file mode 100644 index 0000000000..a63eaa6a6c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/storage_texture/read_only/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/storage_texture/read_write/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/storage_texture/read_write/cts.https.html new file mode 100644 index 0000000000..d81bfb3601 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/operation/storage_texture/read_write/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/capability_checks/features/query_types/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/capability_checks/features/query_types/cts.https.html index 4d5639e434..f24ef50982 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/capability_checks/features/query_types/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/capability_checks/features/query_types/cts.https.html @@ -34,4 +34,4 @@ - + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers/cts.https.html new file mode 100644 index 0000000000..198c45e4f8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/compute_pipeline/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/compute_pipeline/cts.https.html index 29d3d1966c..167105affc 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/compute_pipeline/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/compute_pipeline/cts.https.html @@ -46,6 +46,7 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/createRenderBundleEncoder/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/createRenderBundleEncoder/cts.https.html index b92f6fc277..9dcbe50ea5 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/createRenderBundleEncoder/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/createRenderBundleEncoder/cts.https.html @@ -38,5 +38,4 @@ - diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat/cts.https.html index dd84adeb23..8d43f96f5e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat/cts.https.html @@ -38,6 +38,8 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/queries/general/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/queries/general/cts.https.html index 0c4e1a0ebf..65ab7a9bfa 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/queries/general/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/encoding/queries/general/cts.https.html @@ -36,6 +36,6 @@ - - - + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/layout_shader_compat/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/layout_shader_compat/cts.https.html new file mode 100644 index 0000000000..d2543b125f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/layout_shader_compat/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/queue/destroyed/query_set/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/queue/destroyed/query_set/cts.https.html index 42db3853c2..34f3f75182 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/queue/destroyed/query_set/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/queue/destroyed/query_set/cts.https.html @@ -35,4 +35,4 @@ - + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pass/render_pass_descriptor/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pass/render_pass_descriptor/cts.https.html index 7831601209..8dab846c64 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pass/render_pass_descriptor/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pass/render_pass_descriptor/cts.https.html @@ -39,6 +39,10 @@ + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/fragment_state/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/fragment_state/cts.https.html index a02e126c27..ae1a5d6251 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/fragment_state/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/fragment_state/cts.https.html @@ -41,5 +41,6 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/misc/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/misc/cts.https.html index df06d2c151..bcbb705113 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/misc/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/misc/cts.https.html @@ -34,5 +34,6 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/resource_compatibility/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/resource_compatibility/cts.https.html new file mode 100644 index 0000000000..b6d17d92af --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pipeline/resource_compatibility/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/shader_module/entry_point/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/shader_module/entry_point/cts.https.html index b929adfd6e..46434de4fe 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/shader_module/entry_point/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/shader_module/entry_point/cts.https.html @@ -34,5 +34,8 @@ + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/texture/bgra8unorm_storage/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/texture/bgra8unorm_storage/cts.https.html index a2c94e7147..9bcfb2e9ad 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/texture/bgra8unorm_storage/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/texture/bgra8unorm_storage/cts.https.html @@ -36,6 +36,4 @@ - - diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/createBindGroup/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/createBindGroup/cts.https.html new file mode 100644 index 0000000000..598b0f5920 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/createBindGroup/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/createBindGroupLayout/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/createBindGroupLayout/cts.https.html new file mode 100644 index 0000000000..49bfd6534d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/createBindGroupLayout/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/encoding/cmds/copyTextureToTexture/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/encoding/cmds/copyTextureToTexture/cts.https.html new file mode 100644 index 0000000000..3c8447474e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/encoding/cmds/copyTextureToTexture/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/render_pipeline/depth_stencil_state/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/render_pipeline/depth_stencil_state/cts.https.html new file mode 100644 index 0000000000..b381c4342b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/render_pipeline/depth_stencil_state/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/render_pipeline/shader_module/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/render_pipeline/shader_module/cts.https.html index 9349c3b0de..09451ab50c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/render_pipeline/shader_module/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/render_pipeline/shader_module/cts.https.html @@ -33,4 +33,8 @@ + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/texture/createTexture/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/texture/createTexture/cts.https.html index 9151e96f32..2f76c9aeb2 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/texture/createTexture/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/compat/api/validation/texture/createTexture/cts.https.html @@ -33,5 +33,9 @@ + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/idl/constructable/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/idl/constructable/cts.https.html new file mode 100644 index 0000000000..4f7d2e4239 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/idl/constructable/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/print_environment/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/print_environment/cts.https.html new file mode 100644 index 0000000000..862b318ec1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/print_environment/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/array/index/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/array/index/cts.https.html new file mode 100644 index 0000000000..9c9ec9e9e4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/array/index/cts.https.html @@ -0,0 +1,40 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/matrix/index/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/matrix/index/cts.https.html new file mode 100644 index 0000000000..dc6cb3f1e6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/matrix/index/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/structure/index/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/structure/index/cts.https.html new file mode 100644 index 0000000000..9f521f9162 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/structure/index/cts.https.html @@ -0,0 +1,43 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/vector/components/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/vector/components/cts.https.html new file mode 100644 index 0000000000..a23046fe8b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/vector/components/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/vector/index/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/vector/index/cts.https.html new file mode 100644 index 0000000000..f9b0863078 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/access/vector/index/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication/cts.https.html new file mode 100644 index 0000000000..94f9d43cc5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication/cts.https.html new file mode 100644 index 0000000000..a5c3d8381b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication/cts.https.html new file mode 100644 index 0000000000..453cca2a54 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/ai_arithmetic/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/ai_arithmetic/cts.https.html new file mode 100644 index 0000000000..cde5ee4e50 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/ai_arithmetic/cts.https.html @@ -0,0 +1,50 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/ai_comparison/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/ai_comparison/cts.https.html new file mode 100644 index 0000000000..dc5b57dfb1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/binary/ai_comparison/cts.https.html @@ -0,0 +1,41 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/bitcast/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/bitcast/cts.https.html index d61fbabd81..2e069aa282 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/bitcast/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/bitcast/cts.https.html @@ -33,6 +33,14 @@ + + + + + + + + @@ -46,6 +54,8 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/distance/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/distance/cts.https.html index 3cbbe0182d..76bf604f2c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/distance/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/distance/cts.https.html @@ -34,6 +34,9 @@ + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot/cts.https.html index 251705280d..da8ab36bde 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot/cts.https.html @@ -33,13 +33,21 @@ - - + + + + + + - - + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot4I8Packed/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot4I8Packed/cts.https.html new file mode 100644 index 0000000000..dd49ba7b7d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot4I8Packed/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot4U8Packed/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot4U8Packed/cts.https.html new file mode 100644 index 0000000000..85ac604773 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/dot4U8Packed/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/faceForward/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/faceForward/cts.https.html index 27f58bd167..988ffaa2b7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/faceForward/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/faceForward/cts.https.html @@ -33,7 +33,9 @@ - + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/frexp/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/frexp/cts.https.html index 5c94ddf50e..2f4d95dc0e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/frexp/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/frexp/cts.https.html @@ -33,6 +33,14 @@ + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/length/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/length/cts.https.html index 7ae43aaac2..ca7b11717c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/length/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/length/cts.https.html @@ -34,6 +34,9 @@ + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/normalize/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/normalize/cts.https.html index bf162274e1..4a14676345 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/normalize/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/normalize/cts.https.html @@ -33,7 +33,9 @@ - + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xI8/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xI8/cts.https.html new file mode 100644 index 0000000000..8012022887 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xI8/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xI8Clamp/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xI8Clamp/cts.https.html new file mode 100644 index 0000000000..a461f16e01 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xI8Clamp/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xU8/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xU8/cts.https.html new file mode 100644 index 0000000000..2ce0ff9c63 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xU8/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xU8Clamp/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xU8Clamp/cts.https.html new file mode 100644 index 0000000000..5768152f99 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/pack4xU8Clamp/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/reflect/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/reflect/cts.https.html index b35b5c4fff..2b74417ff2 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/reflect/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/reflect/cts.https.html @@ -33,7 +33,9 @@ - + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/refract/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/refract/cts.https.html index f4ac297425..68d007b3b9 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/refract/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/refract/cts.https.html @@ -33,7 +33,9 @@ - + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureDimension/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureDimension/cts.https.html deleted file mode 100644 index d71796e773..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureDimension/cts.https.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - -WebGPU CTS - - - - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureDimensions/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureDimensions/cts.https.html new file mode 100644 index 0000000000..c7ff1d0ae0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureDimensions/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSample/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSample/cts.https.html index aa2a5211b0..9b213028c9 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSample/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSample/cts.https.html @@ -39,8 +39,8 @@ + - diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSampleBias/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSampleBias/cts.https.html index 4c044b6bbc..eb0f19da12 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSampleBias/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSampleBias/cts.https.html @@ -35,7 +35,5 @@ - - diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSampleCompare/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSampleCompare/cts.https.html index 822aa8b251..f13d70170f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSampleCompare/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/textureSampleCompare/cts.https.html @@ -37,5 +37,3 @@ - - diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/unpack4xI8/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/unpack4xI8/cts.https.html new file mode 100644 index 0000000000..55177d2f0b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/unpack4xI8/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/unpack4xU8/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/unpack4xU8/cts.https.html new file mode 100644 index 0000000000..7f37b9edd6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/unpack4xU8/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/workgroupUniformLoad/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/workgroupUniformLoad/cts.https.html new file mode 100644 index 0000000000..b3ea2d9b51 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/builtin/workgroupUniformLoad/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/user/ptr_params/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/user/ptr_params/cts.https.html new file mode 100644 index 0000000000..4d4f0e67b9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/call/user/ptr_params/cts.https.html @@ -0,0 +1,44 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/constructor/non_zero/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/constructor/non_zero/cts.https.html new file mode 100644 index 0000000000..ceb74f1573 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/constructor/non_zero/cts.https.html @@ -0,0 +1,51 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/constructor/zero_value/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/constructor/zero_value/cts.https.html new file mode 100644 index 0000000000..a9c2ddc407 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/constructor/zero_value/cts.https.html @@ -0,0 +1,40 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/precedence/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/precedence/cts.https.html new file mode 100644 index 0000000000..4364575ab7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/precedence/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/address_of_and_indirection/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/address_of_and_indirection/cts.https.html new file mode 100644 index 0000000000..2413edab44 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/address_of_and_indirection/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_arithmetic/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_arithmetic/cts.https.html new file mode 100644 index 0000000000..3d73d77ade --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_arithmetic/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_assignment/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_assignment/cts.https.html new file mode 100644 index 0000000000..3aa04b4464 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_assignment/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_complement/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_complement/cts.https.html new file mode 100644 index 0000000000..b75207f089 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/ai_complement/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/f16_conversion/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/f16_conversion/cts.https.html index b058c65787..fe72e800fe 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/f16_conversion/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/f16_conversion/cts.https.html @@ -33,6 +33,9 @@ + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/i32_conversion/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/i32_conversion/cts.https.html index 2928999f71..04c46fc47c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/i32_conversion/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/i32_conversion/cts.https.html @@ -33,6 +33,8 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/u32_conversion/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/u32_conversion/cts.https.html index b9dfd9dbd2..84ca69cead 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/u32_conversion/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/expression/unary/u32_conversion/cts.https.html @@ -33,6 +33,7 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/call/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/call/cts.https.html index 17df849095..52e694c692 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/call/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/call/cts.https.html @@ -33,6 +33,10 @@ + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/for/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/for/cts.https.html index bfe852e353..995595c9af 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/for/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/for/cts.https.html @@ -42,5 +42,7 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/loop/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/loop/cts.https.html index c475971bbc..56378d019e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/loop/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/loop/cts.https.html @@ -34,6 +34,8 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/switch/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/switch/cts.https.html index 5a985e70bb..e8a3284850 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/switch/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/switch/cts.https.html @@ -36,5 +36,6 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/while/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/while/cts.https.html index 4f5a053243..b40e54a648 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/while/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/flow_control/while/cts.https.html @@ -36,5 +36,7 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/memory_layout/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/memory_layout/cts.https.html new file mode 100644 index 0000000000..7df714822a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/memory_layout/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/memory_model/texture_intra_invocation_coherence/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/memory_model/texture_intra_invocation_coherence/cts.https.html new file mode 100644 index 0000000000..72d19aaec6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/memory_model/texture_intra_invocation_coherence/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/fragment_builtins/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/fragment_builtins/cts.https.html new file mode 100644 index 0000000000..0076ff1590 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/fragment_builtins/cts.https.html @@ -0,0 +1,41 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/user_io/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/user_io/cts.https.html new file mode 100644 index 0000000000..64438d8f62 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/user_io/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/workgroup_size/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/workgroup_size/cts.https.html new file mode 100644 index 0000000000..b688e6b406 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/shader_io/workgroup_size/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/stage/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/stage/cts.https.html new file mode 100644 index 0000000000..4861a57c86 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/stage/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/statement/compound/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/statement/compound/cts.https.html new file mode 100644 index 0000000000..5f03e7af2f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/statement/compound/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/statement/discard/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/statement/discard/cts.https.html new file mode 100644 index 0000000000..fa65072216 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/execution/statement/discard/cts.https.html @@ -0,0 +1,41 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/compound_statement/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/compound_statement/cts.https.html new file mode 100644 index 0000000000..d1294eee28 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/compound_statement/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/const/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/const/cts.https.html index d9cca95d49..310e5d09ef 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/const/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/const/cts.https.html @@ -33,7 +33,10 @@ + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/context_dependent_resolution/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/context_dependent_resolution/cts.https.html new file mode 100644 index 0000000000..c7ee7c0a84 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/context_dependent_resolution/cts.https.html @@ -0,0 +1,44 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/let/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/let/cts.https.html new file mode 100644 index 0000000000..1a19bb2aa4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/let/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/override/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/override/cts.https.html index 55c0091184..215ac5ffb7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/override/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/override/cts.https.html @@ -33,5 +33,9 @@ + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/var/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/var/cts.https.html new file mode 100644 index 0000000000..6fd7b9a33b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/decl/var/cts.https.html @@ -0,0 +1,46 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/add_sub_mul/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/add_sub_mul/cts.https.html new file mode 100644 index 0000000000..7fc9d1f4fd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/add_sub_mul/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/and_or_xor/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/and_or_xor/cts.https.html new file mode 100644 index 0000000000..f5c62bc67c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/and_or_xor/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/bitwise_shift/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/bitwise_shift/cts.https.html index 1e096d540d..711c00c1d2 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/bitwise_shift/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/bitwise_shift/cts.https.html @@ -33,7 +33,7 @@ + + - - diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/comparison/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/comparison/cts.https.html new file mode 100644 index 0000000000..ac72c55fcb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/comparison/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/div_rem/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/div_rem/cts.https.html new file mode 100644 index 0000000000..408c6ad77d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/binary/div_rem/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/abs/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/abs/cts.https.html index d772926886..b65232dbbe 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/abs/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/abs/cts.https.html @@ -33,4 +33,5 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/acos/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/acos/cts.https.html index 13dce9fe12..64af88d6d6 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/acos/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/acos/cts.https.html @@ -34,4 +34,5 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/acosh/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/acosh/cts.https.html index fe2aa41eec..1c7557ac47 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/acosh/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/acosh/cts.https.html @@ -34,4 +34,5 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/all/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/all/cts.https.html new file mode 100644 index 0000000000..d67b1512d8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/all/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/any/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/any/cts.https.html new file mode 100644 index 0000000000..ad22a63327 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/any/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/arrayLength/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/arrayLength/cts.https.html new file mode 100644 index 0000000000..e7ba3fe65e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/arrayLength/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/asin/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/asin/cts.https.html index 8d5305e83d..5a7492d4f0 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/asin/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/asin/cts.https.html @@ -34,4 +34,5 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/asinh/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/asinh/cts.https.html index 52d74d75c8..d0cd450236 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/asinh/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/asinh/cts.https.html @@ -34,4 +34,5 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atan/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atan/cts.https.html index 80823df40b..c3525fd2be 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atan/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atan/cts.https.html @@ -34,4 +34,5 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atan2/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atan2/cts.https.html index 6f6c70206d..3419d0d1f5 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atan2/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atan2/cts.https.html @@ -33,6 +33,8 @@ - - + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atanh/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atanh/cts.https.html index 0e2a65cf5e..a974c8ac6e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atanh/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atanh/cts.https.html @@ -34,4 +34,5 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atomics/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atomics/cts.https.html index 9b82304aa6..1dacfdda02 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atomics/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/atomics/cts.https.html @@ -33,4 +33,7 @@ + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/barriers/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/barriers/cts.https.html new file mode 100644 index 0000000000..d43e0fbedb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/barriers/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cos/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cos/cts.https.html index 4f6ead08ae..85f6f004e3 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cos/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cos/cts.https.html @@ -33,5 +33,7 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cosh/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cosh/cts.https.html index 97b4aef554..0a42b5d934 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cosh/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cosh/cts.https.html @@ -33,5 +33,6 @@ - + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countLeadingZeros/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countLeadingZeros/cts.https.html new file mode 100644 index 0000000000..75587ee11f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countLeadingZeros/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countOneBits/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countOneBits/cts.https.html new file mode 100644 index 0000000000..a04c240f21 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countOneBits/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countTrailingZeros/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countTrailingZeros/cts.https.html new file mode 100644 index 0000000000..21ba7b014d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/countTrailingZeros/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cross/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cross/cts.https.html new file mode 100644 index 0000000000..1a8f642254 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/cross/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/degrees/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/degrees/cts.https.html index cf33579e4e..47193fe30d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/degrees/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/degrees/cts.https.html @@ -33,5 +33,7 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/derivatives/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/derivatives/cts.https.html new file mode 100644 index 0000000000..16e289777a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/derivatives/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/determinant/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/determinant/cts.https.html new file mode 100644 index 0000000000..e9d74b7f25 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/determinant/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/distance/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/distance/cts.https.html new file mode 100644 index 0000000000..0def485edf --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/distance/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/dot4I8Packed/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/dot4I8Packed/cts.https.html new file mode 100644 index 0000000000..c2a1674c7c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/dot4I8Packed/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/dot4U8Packed/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/dot4U8Packed/cts.https.html new file mode 100644 index 0000000000..682df2bdb9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/dot4U8Packed/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/exp/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/exp/cts.https.html index 2dccb5e18f..7eb5be91c0 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/exp/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/exp/cts.https.html @@ -33,5 +33,6 @@ - + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/exp2/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/exp2/cts.https.html index 2ff4ac3d29..a85b174253 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/exp2/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/exp2/cts.https.html @@ -33,5 +33,6 @@ - + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/extractBits/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/extractBits/cts.https.html new file mode 100644 index 0000000000..31af077e4e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/extractBits/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/faceForward/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/faceForward/cts.https.html new file mode 100644 index 0000000000..32d5ce9a2b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/faceForward/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/firstLeadingBit/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/firstLeadingBit/cts.https.html new file mode 100644 index 0000000000..1e7c343541 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/firstLeadingBit/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/firstTrailingBit/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/firstTrailingBit/cts.https.html new file mode 100644 index 0000000000..13bdc058e6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/firstTrailingBit/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/floor/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/floor/cts.https.html new file mode 100644 index 0000000000..b60e7fd8ed --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/floor/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/fract/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/fract/cts.https.html new file mode 100644 index 0000000000..b6f5ca9ea9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/fract/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/frexp/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/frexp/cts.https.html new file mode 100644 index 0000000000..8e857d24d5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/frexp/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/insertBits/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/insertBits/cts.https.html new file mode 100644 index 0000000000..822e73e047 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/insertBits/cts.https.html @@ -0,0 +1,40 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/inverseSqrt/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/inverseSqrt/cts.https.html index 3b761ea97a..008be75755 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/inverseSqrt/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/inverseSqrt/cts.https.html @@ -33,5 +33,6 @@ - + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/log/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/log/cts.https.html index 3e60dfb1f1..65494baac8 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/log/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/log/cts.https.html @@ -33,5 +33,7 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/log2/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/log2/cts.https.html index f4e975a8e4..df16ce5897 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/log2/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/log2/cts.https.html @@ -33,5 +33,7 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/max/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/max/cts.https.html new file mode 100644 index 0000000000..98eaf739ea --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/max/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/min/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/min/cts.https.html new file mode 100644 index 0000000000..adb943fa96 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/min/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/normalize/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/normalize/cts.https.html new file mode 100644 index 0000000000..7bd72c4a24 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/normalize/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack2x16snorm/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack2x16snorm/cts.https.html new file mode 100644 index 0000000000..038626ff4b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack2x16snorm/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack2x16unorm/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack2x16unorm/cts.https.html new file mode 100644 index 0000000000..e7892645e7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack2x16unorm/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4x8snorm/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4x8snorm/cts.https.html new file mode 100644 index 0000000000..4d7e34443d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4x8snorm/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4x8unorm/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4x8unorm/cts.https.html new file mode 100644 index 0000000000..f86cdc06cd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4x8unorm/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xI8/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xI8/cts.https.html new file mode 100644 index 0000000000..201e33cefc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xI8/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xI8Clamp/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xI8Clamp/cts.https.html new file mode 100644 index 0000000000..2ec95a95b6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xI8Clamp/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xU8/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xU8/cts.https.html new file mode 100644 index 0000000000..36147a70b0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xU8/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xU8Clamp/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xU8Clamp/cts.https.html new file mode 100644 index 0000000000..39f6c1bae5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/pack4xU8Clamp/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/quantizeToF16/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/quantizeToF16/cts.https.html new file mode 100644 index 0000000000..084299a10c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/quantizeToF16/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/radians/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/radians/cts.https.html index 99c0f5738b..1db57dca41 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/radians/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/radians/cts.https.html @@ -33,5 +33,7 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/reflect/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/reflect/cts.https.html new file mode 100644 index 0000000000..86ad44b02e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/reflect/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/reverseBits/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/reverseBits/cts.https.html new file mode 100644 index 0000000000..df72bf1488 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/reverseBits/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/select/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/select/cts.https.html new file mode 100644 index 0000000000..94b6de1d3e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/select/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sign/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sign/cts.https.html index e7753a1acb..5e6f336e64 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sign/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sign/cts.https.html @@ -33,5 +33,6 @@ - + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sin/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sin/cts.https.html index 2ca00f36a8..7247aa830d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sin/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sin/cts.https.html @@ -33,5 +33,7 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sinh/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sinh/cts.https.html index df424272b0..856a97252e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sinh/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sinh/cts.https.html @@ -33,5 +33,6 @@ - + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/smoothstep/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/smoothstep/cts.https.html new file mode 100644 index 0000000000..d118626d43 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/smoothstep/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sqrt/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sqrt/cts.https.html index 093fd2e319..974c04d049 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sqrt/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/sqrt/cts.https.html @@ -33,5 +33,7 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/step/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/step/cts.https.html new file mode 100644 index 0000000000..668161c66d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/step/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/tan/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/tan/cts.https.html index 3b99a17b78..b7a0164577 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/tan/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/tan/cts.https.html @@ -33,5 +33,6 @@ - + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/tanh/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/tanh/cts.https.html new file mode 100644 index 0000000000..5d3937a8ea --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/tanh/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureGather/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureGather/cts.https.html new file mode 100644 index 0000000000..46d63aebba --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureGather/cts.https.html @@ -0,0 +1,41 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureGatherCompare/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureGatherCompare/cts.https.html new file mode 100644 index 0000000000..1c8d9e2332 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureGatherCompare/cts.https.html @@ -0,0 +1,40 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureLoad/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureLoad/cts.https.html new file mode 100644 index 0000000000..db036d198b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureLoad/cts.https.html @@ -0,0 +1,41 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSample/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSample/cts.https.html new file mode 100644 index 0000000000..0af6428923 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSample/cts.https.html @@ -0,0 +1,40 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge/cts.https.html new file mode 100644 index 0000000000..b3652a1d10 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleBias/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleBias/cts.https.html new file mode 100644 index 0000000000..857a73ffe3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleBias/cts.https.html @@ -0,0 +1,41 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleCompare/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleCompare/cts.https.html new file mode 100644 index 0000000000..c3ea09f00e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleCompare/cts.https.html @@ -0,0 +1,41 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleCompareLevel/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleCompareLevel/cts.https.html new file mode 100644 index 0000000000..e06af57b82 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleCompareLevel/cts.https.html @@ -0,0 +1,40 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleGrad/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleGrad/cts.https.html new file mode 100644 index 0000000000..53589d8916 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleGrad/cts.https.html @@ -0,0 +1,41 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleLevel/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleLevel/cts.https.html new file mode 100644 index 0000000000..5d34b6a8a3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureSampleLevel/cts.https.html @@ -0,0 +1,40 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureStore/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureStore/cts.https.html new file mode 100644 index 0000000000..1f444ad125 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/textureStore/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/trunc/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/trunc/cts.https.html new file mode 100644 index 0000000000..e5f4a02689 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/trunc/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16float/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16float/cts.https.html new file mode 100644 index 0000000000..aeff074e09 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16float/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16snorm/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16snorm/cts.https.html new file mode 100644 index 0000000000..d258511abf --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16snorm/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16unorm/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16unorm/cts.https.html new file mode 100644 index 0000000000..82b72034af --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack2x16unorm/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4x8snorm/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4x8snorm/cts.https.html new file mode 100644 index 0000000000..e2c6412fb6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4x8snorm/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4x8unorm/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4x8unorm/cts.https.html new file mode 100644 index 0000000000..a6960ebfeb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4x8unorm/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4xI8/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4xI8/cts.https.html new file mode 100644 index 0000000000..8cfb8adabb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4xI8/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4xU8/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4xU8/cts.https.html new file mode 100644 index 0000000000..0e1c1df3a2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/unpack4xU8/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/workgroupUniformLoad/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/workgroupUniformLoad/cts.https.html new file mode 100644 index 0000000000..007243bfb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/call/builtin/workgroupUniformLoad/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/overload_resolution/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/overload_resolution/cts.https.html new file mode 100644 index 0000000000..8ae70985d5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/overload_resolution/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/precedence/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/precedence/cts.https.html new file mode 100644 index 0000000000..591fe3b37e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/precedence/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/address_of_and_indirection/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/address_of_and_indirection/cts.https.html new file mode 100644 index 0000000000..f8f577b5f1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/address_of_and_indirection/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/arithmetic_negation/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/arithmetic_negation/cts.https.html new file mode 100644 index 0000000000..604e5474c7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/arithmetic_negation/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/bitwise_complement/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/bitwise_complement/cts.https.html new file mode 100644 index 0000000000..09bf372a49 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/bitwise_complement/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/logical_negation/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/logical_negation/cts.https.html new file mode 100644 index 0000000000..081207357f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/expression/unary/logical_negation/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/extension/pointer_composite_access/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/extension/pointer_composite_access/cts.https.html new file mode 100644 index 0000000000..6d3da49630 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/extension/pointer_composite_access/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/extension/readonly_and_readwrite_storage_textures/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/extension/readonly_and_readwrite_storage_textures/cts.https.html new file mode 100644 index 0000000000..af5e14d857 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/extension/readonly_and_readwrite_storage_textures/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/functions/alias_analysis/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/functions/alias_analysis/cts.https.html index c0c2a2b5e2..f00c0f982d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/functions/alias_analysis/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/functions/alias_analysis/cts.https.html @@ -35,7 +35,16 @@ + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/functions/restrictions/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/functions/restrictions/cts.https.html index e4333302d9..14feb7f665 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/functions/restrictions/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/functions/restrictions/cts.https.html @@ -33,7 +33,9 @@ - + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/break_if/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/break_if/cts.https.html new file mode 100644 index 0000000000..f494e9daf9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/break_if/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/compound/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/compound/cts.https.html new file mode 100644 index 0000000000..225365d4b8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/compound/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/continuing/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/continuing/cts.https.html new file mode 100644 index 0000000000..8f6dec9aaf --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/continuing/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/diagnostic/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/diagnostic/cts.https.html index 03f434cfe0..67384a6f09 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/diagnostic/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/diagnostic/cts.https.html @@ -33,9 +33,11 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/must_use/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/must_use/cts.https.html index 6e413a3b04..71bb89f983 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/must_use/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/must_use/cts.https.html @@ -37,3 +37,4 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/pipeline_stage/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/pipeline_stage/cts.https.html index bc77f0bd9d..fda7008993 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/pipeline_stage/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/pipeline_stage/cts.https.html @@ -34,9 +34,9 @@ - - - + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/requires/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/requires/cts.https.html new file mode 100644 index 0000000000..d389742e39 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/requires/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/semicolon/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/semicolon/cts.https.html index 0d510c72b4..668a907b0c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/semicolon/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/semicolon/cts.https.html @@ -41,6 +41,7 @@ + @@ -59,6 +60,7 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/shadow_builtins/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/shadow_builtins/cts.https.html new file mode 100644 index 0000000000..1c2b621084 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/shadow_builtins/cts.https.html @@ -0,0 +1,44 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/statement_behavior/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/statement_behavior/cts.https.html new file mode 100644 index 0000000000..c72a33e005 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/parse/statement_behavior/cts.https.html @@ -0,0 +1,39 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/binding/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/binding/cts.https.html index 9dde54b51b..30129a8e01 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/binding/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/binding/cts.https.html @@ -35,4 +35,3 @@ - diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/group/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/group/cts.https.html index 19974f2dcf..e373dc4eba 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/group/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/group/cts.https.html @@ -35,4 +35,3 @@ - diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/layout_constraints/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/layout_constraints/cts.https.html new file mode 100644 index 0000000000..397c9356f0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/layout_constraints/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/locations/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/locations/cts.https.html index 98ad686ed8..30cff6886e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/locations/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/locations/cts.https.html @@ -36,6 +36,7 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/size/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/size/cts.https.html index d9bfbede3a..b40b7e0422 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/size/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/shader_io/size/cts.https.html @@ -34,5 +34,6 @@ + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/alias/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/alias/cts.https.html index 08e7d8d4f7..69d5504ade 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/alias/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/alias/cts.https.html @@ -33,6 +33,8 @@ + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/array/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/array/cts.https.html new file mode 100644 index 0000000000..ce3d567d87 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/array/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/atomics/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/atomics/cts.https.html new file mode 100644 index 0000000000..320ed79810 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/atomics/cts.https.html @@ -0,0 +1,38 @@ + + + + +WebGPU CTS + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/matrix/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/matrix/cts.https.html new file mode 100644 index 0000000000..4e8451fed4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/matrix/cts.https.html @@ -0,0 +1,37 @@ + + + + +WebGPU CTS + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/textures/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/textures/cts.https.html new file mode 100644 index 0000000000..ed3a7a516c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/shader/validation/types/textures/cts.https.html @@ -0,0 +1,42 @@ + + + + +WebGPU CTS + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/util/texture/color_space_conversions/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/util/texture/color_space_conversions/cts.https.html new file mode 100644 index 0000000000..5320960245 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/util/texture/color_space_conversions/cts.https.html @@ -0,0 +1,36 @@ + + + + +WebGPU CTS + + + + + + + + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/web_platform/external_texture/video/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/web_platform/external_texture/video/cts.https.html index 94d61c32ae..5bfb8e2f22 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/web_platform/external_texture/video/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/web_platform/external_texture/video/cts.https.html @@ -35,5 +35,5 @@ - + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/web_platform/worker/worker/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/web_platform/worker/worker/cts.https.html index 08f7bfbacd..ad1e87a1f4 100644 --- a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/web_platform/worker/worker/cts.https.html +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/web_platform/worker/worker/cts.https.html @@ -33,4 +33,6 @@ - + + + diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestAdapter.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestAdapter.worker.js new file mode 100644 index 0000000000..006b7d926b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestAdapter.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/adapter/requestAdapter.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestAdapterInfo.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestAdapterInfo.worker.js new file mode 100644 index 0000000000..88753e43e1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestAdapterInfo.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/adapter/requestAdapterInfo.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestDevice.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestDevice.worker.js new file mode 100644 index 0000000000..8e5aa7a329 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/adapter/requestDevice.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/adapter/requestDevice.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map.worker.js new file mode 100644 index 0000000000..ea5d50dcaa --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/buffers/map.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_ArrayBuffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_ArrayBuffer.worker.js new file mode 100644 index 0000000000..5f9c16e71a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_ArrayBuffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/buffers/map_ArrayBuffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_detach.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_detach.worker.js new file mode 100644 index 0000000000..60ca0d6b7c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_detach.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/buffers/map_detach.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_oom.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_oom.worker.js new file mode 100644 index 0000000000..c5adf88767 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/map_oom.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/buffers/map_oom.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/threading.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/threading.worker.js new file mode 100644 index 0000000000..d65a38a7be --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/buffers/threading.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/buffers/threading.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/basic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/basic.worker.js new file mode 100644 index 0000000000..56ebb361a1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/basic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/command_buffer/basic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/clearBuffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/clearBuffer.worker.js new file mode 100644 index 0000000000..ce7ed9a93d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/clearBuffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/command_buffer/clearBuffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/copyBufferToBuffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/copyBufferToBuffer.worker.js new file mode 100644 index 0000000000..4968696863 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/copyBufferToBuffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/command_buffer/copyBufferToBuffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/copyTextureToTexture.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/copyTextureToTexture.worker.js new file mode 100644 index 0000000000..fac5b03ea7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/copyTextureToTexture.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/command_buffer/copyTextureToTexture.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/image_copy.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/image_copy.worker.js new file mode 100644 index 0000000000..2e39a8358b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/image_copy.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/command_buffer/image_copy.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/programmable/state_tracking.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/programmable/state_tracking.worker.js new file mode 100644 index 0000000000..8e17f588ad --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/programmable/state_tracking.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/operation/command_buffer/programmable/state_tracking.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/queries/occlusionQuery.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/queries/occlusionQuery.worker.js new file mode 100644 index 0000000000..de05375bbf --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/queries/occlusionQuery.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/operation/command_buffer/queries/occlusionQuery.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/render/dynamic_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/render/dynamic_state.worker.js new file mode 100644 index 0000000000..a5e0b76f3e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/render/dynamic_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/operation/command_buffer/render/dynamic_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/render/state_tracking.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/render/state_tracking.worker.js new file mode 100644 index 0000000000..df05ffe4d3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/command_buffer/render/state_tracking.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/operation/command_buffer/render/state_tracking.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute/basic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute/basic.worker.js new file mode 100644 index 0000000000..4129b0f122 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute/basic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/compute/basic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute_pipeline/entry_point_name.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute_pipeline/entry_point_name.worker.js new file mode 100644 index 0000000000..e0359948b6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute_pipeline/entry_point_name.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/compute_pipeline/entry_point_name.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute_pipeline/overrides.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute_pipeline/overrides.worker.js new file mode 100644 index 0000000000..8fedbc8f51 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/compute_pipeline/overrides.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/compute_pipeline/overrides.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/device/lost.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/device/lost.worker.js new file mode 100644 index 0000000000..afb13ff4f6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/device/lost.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/device/lost.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/labels.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/labels.worker.js new file mode 100644 index 0000000000..e0dc7bae36 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/labels.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/operation/labels.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/buffer/multiple_buffers.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/buffer/multiple_buffers.worker.js new file mode 100644 index 0000000000..c5aaa8eeb6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/buffer/multiple_buffers.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/operation/memory_sync/buffer/multiple_buffers.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/buffer/single_buffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/buffer/single_buffer.worker.js new file mode 100644 index 0000000000..a5db55c892 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/buffer/single_buffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/operation/memory_sync/buffer/single_buffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/texture/readonly_depth_stencil.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/texture/readonly_depth_stencil.worker.js new file mode 100644 index 0000000000..4a91e7062c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/texture/readonly_depth_stencil.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/operation/memory_sync/texture/readonly_depth_stencil.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/texture/same_subresource.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/texture/same_subresource.worker.js new file mode 100644 index 0000000000..f716f5fbd2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/memory_sync/texture/same_subresource.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/operation/memory_sync/texture/same_subresource.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/onSubmittedWorkDone.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/onSubmittedWorkDone.worker.js new file mode 100644 index 0000000000..64fe2f204a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/onSubmittedWorkDone.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/operation/onSubmittedWorkDone.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/pipeline/default_layout.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/pipeline/default_layout.worker.js new file mode 100644 index 0000000000..bb32229817 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/pipeline/default_layout.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/pipeline/default_layout.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/queue/writeBuffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/queue/writeBuffer.worker.js new file mode 100644 index 0000000000..e471b6a15c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/queue/writeBuffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/queue/writeBuffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/reflection.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/reflection.worker.js new file mode 100644 index 0000000000..bcc052b651 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/reflection.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/operation/reflection.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/clear_value.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/clear_value.worker.js new file mode 100644 index 0000000000..aeb572ddc5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/clear_value.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/render_pass/clear_value.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/resolve.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/resolve.worker.js new file mode 100644 index 0000000000..ee1d6ac5b8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/resolve.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/render_pass/resolve.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/storeOp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/storeOp.worker.js new file mode 100644 index 0000000000..9fe4944f8e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/storeOp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/render_pass/storeOp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/storeop2.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/storeop2.worker.js new file mode 100644 index 0000000000..7b91a30302 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pass/storeop2.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/render_pass/storeop2.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/culling_tests.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/culling_tests.worker.js new file mode 100644 index 0000000000..b3e56a8171 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/culling_tests.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/render_pipeline/culling_tests.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/overrides.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/overrides.worker.js new file mode 100644 index 0000000000..4d35070f20 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/overrides.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/render_pipeline/overrides.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/pipeline_output_targets.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/pipeline_output_targets.worker.js new file mode 100644 index 0000000000..4752f3e538 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/pipeline_output_targets.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/render_pipeline/pipeline_output_targets.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/primitive_topology.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/primitive_topology.worker.js new file mode 100644 index 0000000000..9e3664a3fe --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/primitive_topology.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/render_pipeline/primitive_topology.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/sample_mask.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/sample_mask.worker.js new file mode 100644 index 0000000000..148f38687f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/sample_mask.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/render_pipeline/sample_mask.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/vertex_only_render_pipeline.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/vertex_only_render_pipeline.worker.js new file mode 100644 index 0000000000..03c7feee04 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/render_pipeline/vertex_only_render_pipeline.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/render_pipeline/vertex_only_render_pipeline.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/3d_texture_slices.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/3d_texture_slices.worker.js new file mode 100644 index 0000000000..aa13489087 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/3d_texture_slices.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/rendering/3d_texture_slices.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/basic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/basic.worker.js new file mode 100644 index 0000000000..5a68ad5d0f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/basic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/rendering/basic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/color_target_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/color_target_state.worker.js new file mode 100644 index 0000000000..e22643306d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/color_target_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/rendering/color_target_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth.worker.js new file mode 100644 index 0000000000..3887717ca0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/rendering/depth.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth_bias.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth_bias.worker.js new file mode 100644 index 0000000000..164c83d8e9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth_bias.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/rendering/depth_bias.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth_clip_clamp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth_clip_clamp.worker.js new file mode 100644 index 0000000000..dbb129adad --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/depth_clip_clamp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/rendering/depth_clip_clamp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/draw.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/draw.worker.js new file mode 100644 index 0000000000..4b7dcaa34a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/draw.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/rendering/draw.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/indirect_draw.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/indirect_draw.worker.js new file mode 100644 index 0000000000..1241861451 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/indirect_draw.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/rendering/indirect_draw.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/robust_access_index.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/robust_access_index.worker.js new file mode 100644 index 0000000000..88dcfa7bfb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/robust_access_index.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/rendering/robust_access_index.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/stencil.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/stencil.worker.js new file mode 100644 index 0000000000..386683f880 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/rendering/stencil.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/rendering/stencil.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/resource_init/buffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/resource_init/buffer.worker.js new file mode 100644 index 0000000000..a17cd337c4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/resource_init/buffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/resource_init/buffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/resource_init/texture_zero.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/resource_init/texture_zero.worker.js new file mode 100644 index 0000000000..e425408557 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/resource_init/texture_zero.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/resource_init/texture_zero.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/anisotropy.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/anisotropy.worker.js new file mode 100644 index 0000000000..634e853bb9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/anisotropy.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/sampling/anisotropy.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/filter_mode.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/filter_mode.worker.js new file mode 100644 index 0000000000..992f61f32a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/filter_mode.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/sampling/filter_mode.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/lod_clamp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/lod_clamp.worker.js new file mode 100644 index 0000000000..690ccdc922 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/sampling/lod_clamp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/sampling/lod_clamp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/shader_module/compilation_info.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/shader_module/compilation_info.worker.js new file mode 100644 index 0000000000..56650a37ae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/shader_module/compilation_info.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/shader_module/compilation_info.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/storage_texture/read_only.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/storage_texture/read_only.worker.js new file mode 100644 index 0000000000..1e1b3141cd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/storage_texture/read_only.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/storage_texture/read_only.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/storage_texture/read_write.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/storage_texture/read_write.worker.js new file mode 100644 index 0000000000..68a7804b94 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/storage_texture/read_write.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/storage_texture/read_write.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/format_reinterpretation.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/format_reinterpretation.worker.js new file mode 100644 index 0000000000..149586acae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/format_reinterpretation.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/texture_view/format_reinterpretation.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/read.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/read.worker.js new file mode 100644 index 0000000000..9cae75cc80 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/read.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/texture_view/read.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/write.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/write.worker.js new file mode 100644 index 0000000000..d5a8fef0b5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/texture_view/write.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/texture_view/write.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/uncapturederror.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/uncapturederror.worker.js new file mode 100644 index 0000000000..7f58278d95 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/uncapturederror.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/operation/uncapturederror.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/vertex_state/correctness.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/vertex_state/correctness.worker.js new file mode 100644 index 0000000000..409931bddc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/vertex_state/correctness.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/vertex_state/correctness.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/vertex_state/index_format.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/vertex_state/index_format.worker.js new file mode 100644 index 0000000000..131b3eec8a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/operation/vertex_state/index_format.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/operation/vertex_state/index_format.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/create.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/create.worker.js new file mode 100644 index 0000000000..9956d030db --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/create.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/buffer/create.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/destroy.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/destroy.worker.js new file mode 100644 index 0000000000..0bc23d441a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/destroy.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/buffer/destroy.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/mapping.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/mapping.worker.js new file mode 100644 index 0000000000..ced5a04bc2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/mapping.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/buffer/mapping.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/threading.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/threading.worker.js new file mode 100644 index 0000000000..87a0dcb546 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/buffer/threading.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/buffer/threading.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/features/query_types.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/features/query_types.worker.js new file mode 100644 index 0000000000..1b47f1ebe5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/features/query_types.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/features/query_types.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/features/texture_formats.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/features/texture_formats.worker.js new file mode 100644 index 0000000000..46be9cf8e6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/features/texture_formats.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/features/texture_formats.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindGroups.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindGroups.worker.js new file mode 100644 index 0000000000..a7ad4947d6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindGroups.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxBindGroups.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers.worker.js new file mode 100644 index 0000000000..77da34e1b9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindingsPerBindGroup.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindingsPerBindGroup.worker.js new file mode 100644 index 0000000000..34ce60042c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBindingsPerBindGroup.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxBindingsPerBindGroup.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBufferSize.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBufferSize.worker.js new file mode 100644 index 0000000000..e16e1a828b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxBufferSize.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxBufferSize.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxColorAttachmentBytesPerSample.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxColorAttachmentBytesPerSample.worker.js new file mode 100644 index 0000000000..53202de252 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxColorAttachmentBytesPerSample.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxColorAttachmentBytesPerSample.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxColorAttachments.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxColorAttachments.worker.js new file mode 100644 index 0000000000..93f409b9aa --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxColorAttachments.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxColorAttachments.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeInvocationsPerWorkgroup.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeInvocationsPerWorkgroup.worker.js new file mode 100644 index 0000000000..ca774003d6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeInvocationsPerWorkgroup.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxComputeInvocationsPerWorkgroup.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeX.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeX.worker.js new file mode 100644 index 0000000000..cf2dfd7d83 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeX.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxComputeWorkgroupSizeX.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeY.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeY.worker.js new file mode 100644 index 0000000000..fac5b8adb7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeY.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxComputeWorkgroupSizeY.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeZ.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeZ.worker.js new file mode 100644 index 0000000000..fc6ecee71a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupSizeZ.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxComputeWorkgroupSizeZ.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.worker.js new file mode 100644 index 0000000000..c621df8750 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupsPerDimension.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupsPerDimension.worker.js new file mode 100644 index 0000000000..0adb573ac3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxComputeWorkgroupsPerDimension.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxComputeWorkgroupsPerDimension.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxDynamicStorageBuffersPerPipelineLayout.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxDynamicStorageBuffersPerPipelineLayout.worker.js new file mode 100644 index 0000000000..348f858ab9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxDynamicStorageBuffersPerPipelineLayout.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxDynamicStorageBuffersPerPipelineLayout.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxDynamicUniformBuffersPerPipelineLayout.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxDynamicUniformBuffersPerPipelineLayout.worker.js new file mode 100644 index 0000000000..2f8f6eac6b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxDynamicUniformBuffersPerPipelineLayout.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxDynamicUniformBuffersPerPipelineLayout.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxInterStageShaderComponents.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxInterStageShaderComponents.worker.js new file mode 100644 index 0000000000..5141c00a5c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxInterStageShaderComponents.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxInterStageShaderComponents.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxInterStageShaderVariables.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxInterStageShaderVariables.worker.js new file mode 100644 index 0000000000..9eed84a023 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxInterStageShaderVariables.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxInterStageShaderVariables.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxSampledTexturesPerShaderStage.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxSampledTexturesPerShaderStage.worker.js new file mode 100644 index 0000000000..4c78628045 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxSampledTexturesPerShaderStage.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxSampledTexturesPerShaderStage.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxSamplersPerShaderStage.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxSamplersPerShaderStage.worker.js new file mode 100644 index 0000000000..171c51ba3e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxSamplersPerShaderStage.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxSamplersPerShaderStage.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageBufferBindingSize.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageBufferBindingSize.worker.js new file mode 100644 index 0000000000..fc013f5a33 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageBufferBindingSize.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxStorageBufferBindingSize.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageBuffersPerShaderStage.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageBuffersPerShaderStage.worker.js new file mode 100644 index 0000000000..0534c59931 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageBuffersPerShaderStage.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxStorageBuffersPerShaderStage.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageTexturesPerShaderStage.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageTexturesPerShaderStage.worker.js new file mode 100644 index 0000000000..7528bfcb76 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxStorageTexturesPerShaderStage.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxStorageTexturesPerShaderStage.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureArrayLayers.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureArrayLayers.worker.js new file mode 100644 index 0000000000..d9d4a2695b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureArrayLayers.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxTextureArrayLayers.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension1D.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension1D.worker.js new file mode 100644 index 0000000000..b01d232fb1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension1D.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxTextureDimension1D.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension2D.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension2D.worker.js new file mode 100644 index 0000000000..9e0be3b141 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension2D.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxTextureDimension2D.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension3D.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension3D.worker.js new file mode 100644 index 0000000000..8b7ab4335e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxTextureDimension3D.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxTextureDimension3D.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxUniformBufferBindingSize.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxUniformBufferBindingSize.worker.js new file mode 100644 index 0000000000..4b8569d283 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxUniformBufferBindingSize.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxUniformBufferBindingSize.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxUniformBuffersPerShaderStage.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxUniformBuffersPerShaderStage.worker.js new file mode 100644 index 0000000000..a39add9d22 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxUniformBuffersPerShaderStage.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxUniformBuffersPerShaderStage.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexAttributes.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexAttributes.worker.js new file mode 100644 index 0000000000..e5fb866a61 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexAttributes.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxVertexAttributes.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexBufferArrayStride.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexBufferArrayStride.worker.js new file mode 100644 index 0000000000..f8d938fcd8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexBufferArrayStride.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxVertexBufferArrayStride.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexBuffers.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexBuffers.worker.js new file mode 100644 index 0000000000..dead0eea96 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/maxVertexBuffers.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/maxVertexBuffers.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/minStorageBufferOffsetAlignment.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/minStorageBufferOffsetAlignment.worker.js new file mode 100644 index 0000000000..11228efe78 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/minStorageBufferOffsetAlignment.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/minStorageBufferOffsetAlignment.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/minUniformBufferOffsetAlignment.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/minUniformBufferOffsetAlignment.worker.js new file mode 100644 index 0000000000..b484c0f1da --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/capability_checks/limits/minUniformBufferOffsetAlignment.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/capability_checks/limits/minUniformBufferOffsetAlignment.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/compute_pipeline.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/compute_pipeline.worker.js new file mode 100644 index 0000000000..9ab87dd389 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/compute_pipeline.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/compute_pipeline.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createBindGroup.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createBindGroup.worker.js new file mode 100644 index 0000000000..c28e40bba9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createBindGroup.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/createBindGroup.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createBindGroupLayout.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createBindGroupLayout.worker.js new file mode 100644 index 0000000000..d0db0125d7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createBindGroupLayout.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/createBindGroupLayout.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createPipelineLayout.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createPipelineLayout.worker.js new file mode 100644 index 0000000000..7931f8f0a2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createPipelineLayout.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/createPipelineLayout.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createSampler.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createSampler.worker.js new file mode 100644 index 0000000000..980383283b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createSampler.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/createSampler.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createTexture.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createTexture.worker.js new file mode 100644 index 0000000000..bc8d5ca90f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createTexture.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/createTexture.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createView.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createView.worker.js new file mode 100644 index 0000000000..7a6d9fc330 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/createView.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/createView.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/debugMarker.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/debugMarker.worker.js new file mode 100644 index 0000000000..0fadeb557a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/debugMarker.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/debugMarker.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/beginComputePass.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/beginComputePass.worker.js new file mode 100644 index 0000000000..2e321f4129 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/beginComputePass.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/encoding/beginComputePass.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/beginRenderPass.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/beginRenderPass.worker.js new file mode 100644 index 0000000000..ed5e0d97b7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/beginRenderPass.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/encoding/beginRenderPass.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/clearBuffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/clearBuffer.worker.js new file mode 100644 index 0000000000..dcbd091e77 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/clearBuffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/cmds/clearBuffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/compute_pass.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/compute_pass.worker.js new file mode 100644 index 0000000000..02ef60bff8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/compute_pass.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/cmds/compute_pass.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/copyBufferToBuffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/copyBufferToBuffer.worker.js new file mode 100644 index 0000000000..6627e80465 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/copyBufferToBuffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/cmds/copyBufferToBuffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/copyTextureToTexture.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/copyTextureToTexture.worker.js new file mode 100644 index 0000000000..d0806be0f7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/copyTextureToTexture.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/cmds/copyTextureToTexture.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/debug.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/debug.worker.js new file mode 100644 index 0000000000..e46686daa0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/debug.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/cmds/debug.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/index_access.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/index_access.worker.js new file mode 100644 index 0000000000..e0afa5f787 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/index_access.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/cmds/index_access.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/draw.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/draw.worker.js new file mode 100644 index 0000000000..830d3af791 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/draw.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../api/validation/encoding/cmds/render/draw.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/dynamic_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/dynamic_state.worker.js new file mode 100644 index 0000000000..69993c2b18 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/dynamic_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../api/validation/encoding/cmds/render/dynamic_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/indirect_draw.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/indirect_draw.worker.js new file mode 100644 index 0000000000..0fc8c4297e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/indirect_draw.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../api/validation/encoding/cmds/render/indirect_draw.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setIndexBuffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setIndexBuffer.worker.js new file mode 100644 index 0000000000..e89a3d9e0b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setIndexBuffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../api/validation/encoding/cmds/render/setIndexBuffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setPipeline.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setPipeline.worker.js new file mode 100644 index 0000000000..7733659e3e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setPipeline.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../api/validation/encoding/cmds/render/setPipeline.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setVertexBuffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setVertexBuffer.worker.js new file mode 100644 index 0000000000..506c30d2f2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/setVertexBuffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../api/validation/encoding/cmds/render/setVertexBuffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/state_tracking.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/state_tracking.worker.js new file mode 100644 index 0000000000..0670d30095 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render/state_tracking.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../api/validation/encoding/cmds/render/state_tracking.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render_pass.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render_pass.worker.js new file mode 100644 index 0000000000..1e72576a2b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/render_pass.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/cmds/render_pass.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/setBindGroup.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/setBindGroup.worker.js new file mode 100644 index 0000000000..25ac67208d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/cmds/setBindGroup.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/cmds/setBindGroup.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/createRenderBundleEncoder.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/createRenderBundleEncoder.worker.js new file mode 100644 index 0000000000..67f3071613 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/createRenderBundleEncoder.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/encoding/createRenderBundleEncoder.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/encoder_open_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/encoder_open_state.worker.js new file mode 100644 index 0000000000..15124bde33 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/encoder_open_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/encoding/encoder_open_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/encoder_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/encoder_state.worker.js new file mode 100644 index 0000000000..f3a8102fd4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/encoder_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/encoding/encoder_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/programmable/pipeline_bind_group_compat.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/programmable/pipeline_bind_group_compat.worker.js new file mode 100644 index 0000000000..3d5af06ba0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/programmable/pipeline_bind_group_compat.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/programmable/pipeline_bind_group_compat.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/begin_end.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/begin_end.worker.js new file mode 100644 index 0000000000..b723940977 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/begin_end.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/queries/begin_end.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/general.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/general.worker.js new file mode 100644 index 0000000000..1a4a48d56f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/general.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/queries/general.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/resolveQuerySet.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/resolveQuerySet.worker.js new file mode 100644 index 0000000000..ef133a2e65 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/queries/resolveQuerySet.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/encoding/queries/resolveQuerySet.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/render_bundle.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/render_bundle.worker.js new file mode 100644 index 0000000000..b711a626b7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/encoding/render_bundle.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/encoding/render_bundle.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/error_scope.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/error_scope.worker.js new file mode 100644 index 0000000000..4134bbb2d2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/error_scope.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/error_scope.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/getBindGroupLayout.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/getBindGroupLayout.worker.js new file mode 100644 index 0000000000..008f952ac3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/getBindGroupLayout.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/getBindGroupLayout.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/gpu_external_texture_expiration.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/gpu_external_texture_expiration.worker.js new file mode 100644 index 0000000000..cc27a53cb3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/gpu_external_texture_expiration.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/gpu_external_texture_expiration.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/buffer_related.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/buffer_related.worker.js new file mode 100644 index 0000000000..2dd3ff15aa --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/buffer_related.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/image_copy/buffer_related.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/buffer_texture_copies.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/buffer_texture_copies.worker.js new file mode 100644 index 0000000000..4198982692 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/buffer_texture_copies.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/image_copy/buffer_texture_copies.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/layout_related.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/layout_related.worker.js new file mode 100644 index 0000000000..8247514810 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/layout_related.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/image_copy/layout_related.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/texture_related.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/texture_related.worker.js new file mode 100644 index 0000000000..750edbb59e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/image_copy/texture_related.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/image_copy/texture_related.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/layout_shader_compat.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/layout_shader_compat.worker.js new file mode 100644 index 0000000000..c62cff190f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/layout_shader_compat.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../api/validation/layout_shader_compat.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/query_set/create.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/query_set/create.worker.js new file mode 100644 index 0000000000..6b25b2e59a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/query_set/create.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/query_set/create.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/query_set/destroy.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/query_set/destroy.worker.js new file mode 100644 index 0000000000..18c5be2780 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/query_set/destroy.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/query_set/destroy.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/buffer_mapped.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/buffer_mapped.worker.js new file mode 100644 index 0000000000..2ef88aaba4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/buffer_mapped.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/queue/buffer_mapped.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/copyToTexture/CopyExternalImageToTexture.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/copyToTexture/CopyExternalImageToTexture.worker.js new file mode 100644 index 0000000000..dbeb649837 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/copyToTexture/CopyExternalImageToTexture.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/buffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/buffer.worker.js new file mode 100644 index 0000000000..b6ace0141b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/buffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/queue/destroyed/buffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/query_set.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/query_set.worker.js new file mode 100644 index 0000000000..7d0ad59976 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/query_set.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/queue/destroyed/query_set.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/texture.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/texture.worker.js new file mode 100644 index 0000000000..3a55f8ac8b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/destroyed/texture.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/queue/destroyed/texture.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/submit.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/submit.worker.js new file mode 100644 index 0000000000..dadadd8cca --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/submit.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/queue/submit.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/writeBuffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/writeBuffer.worker.js new file mode 100644 index 0000000000..3b08d8f6f8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/writeBuffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/queue/writeBuffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/writeTexture.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/writeTexture.worker.js new file mode 100644 index 0000000000..3c4aa50c90 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/queue/writeTexture.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/queue/writeTexture.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/attachment_compatibility.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/attachment_compatibility.worker.js new file mode 100644 index 0000000000..1e401477f9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/attachment_compatibility.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pass/attachment_compatibility.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/render_pass_descriptor.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/render_pass_descriptor.worker.js new file mode 100644 index 0000000000..5b0ff9dac3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/render_pass_descriptor.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pass/render_pass_descriptor.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/resolve.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/resolve.worker.js new file mode 100644 index 0000000000..03c82fe256 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pass/resolve.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pass/resolve.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/depth_stencil_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/depth_stencil_state.worker.js new file mode 100644 index 0000000000..6ac988850f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/depth_stencil_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pipeline/depth_stencil_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/fragment_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/fragment_state.worker.js new file mode 100644 index 0000000000..c72d44ea90 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/fragment_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pipeline/fragment_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/inter_stage.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/inter_stage.worker.js new file mode 100644 index 0000000000..1a15d1262c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/inter_stage.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pipeline/inter_stage.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/misc.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/misc.worker.js new file mode 100644 index 0000000000..8e4b205225 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/misc.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pipeline/misc.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/multisample_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/multisample_state.worker.js new file mode 100644 index 0000000000..58e9dafa35 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/multisample_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pipeline/multisample_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/overrides.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/overrides.worker.js new file mode 100644 index 0000000000..0390971fa3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/overrides.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pipeline/overrides.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/primitive_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/primitive_state.worker.js new file mode 100644 index 0000000000..0989905dd1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/primitive_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pipeline/primitive_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/resource_compatibility.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/resource_compatibility.worker.js new file mode 100644 index 0000000000..34a92baee9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/resource_compatibility.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pipeline/resource_compatibility.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/shader_module.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/shader_module.worker.js new file mode 100644 index 0000000000..2a183cac86 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/shader_module.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pipeline/shader_module.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/vertex_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/vertex_state.worker.js new file mode 100644 index 0000000000..a9107e3782 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/render_pipeline/vertex_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/render_pipeline/vertex_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/buffer/in_pass_encoder.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/buffer/in_pass_encoder.worker.js new file mode 100644 index 0000000000..210d2a2db1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/buffer/in_pass_encoder.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/resource_usages/buffer/in_pass_encoder.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/buffer/in_pass_misc.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/buffer/in_pass_misc.worker.js new file mode 100644 index 0000000000..4f6eaca9c4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/buffer/in_pass_misc.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/resource_usages/buffer/in_pass_misc.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_pass_encoder.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_pass_encoder.worker.js new file mode 100644 index 0000000000..77dabff1d4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_pass_encoder.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/resource_usages/texture/in_pass_encoder.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_render_common.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_render_common.worker.js new file mode 100644 index 0000000000..12158a6fd1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_render_common.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/resource_usages/texture/in_render_common.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_render_misc.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_render_misc.worker.js new file mode 100644 index 0000000000..113a040aed --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/resource_usages/texture/in_render_misc.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/resource_usages/texture/in_render_misc.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/shader_module/entry_point.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/shader_module/entry_point.worker.js new file mode 100644 index 0000000000..6f395fba80 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/shader_module/entry_point.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/shader_module/entry_point.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/shader_module/overrides.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/shader_module/overrides.worker.js new file mode 100644 index 0000000000..e3144b7fc4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/shader_module/overrides.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/shader_module/overrides.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/state/device_lost/destroy.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/state/device_lost/destroy.worker.js new file mode 100644 index 0000000000..7aca230019 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/state/device_lost/destroy.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../api/validation/state/device_lost/destroy.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/bgra8unorm_storage.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/bgra8unorm_storage.worker.js new file mode 100644 index 0000000000..e77ed783ae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/bgra8unorm_storage.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/texture/bgra8unorm_storage.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/destroy.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/destroy.worker.js new file mode 100644 index 0000000000..92b96ec9ad --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/destroy.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/texture/destroy.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/float32_filterable.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/float32_filterable.worker.js new file mode 100644 index 0000000000..09ea5238bb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/float32_filterable.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/texture/float32_filterable.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/rg11b10ufloat_renderable.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/rg11b10ufloat_renderable.worker.js new file mode 100644 index 0000000000..795241e1d8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/api/validation/texture/rg11b10ufloat_renderable.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../api/validation/texture/rg11b10ufloat_renderable.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/createBindGroup.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/createBindGroup.worker.js new file mode 100644 index 0000000000..2d81691f8f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/createBindGroup.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../compat/api/validation/createBindGroup.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/createBindGroupLayout.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/createBindGroupLayout.worker.js new file mode 100644 index 0000000000..3305962eb8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/createBindGroupLayout.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../compat/api/validation/createBindGroupLayout.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/cmds/copyTextureToBuffer.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/cmds/copyTextureToBuffer.worker.js new file mode 100644 index 0000000000..ad24236d47 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/cmds/copyTextureToBuffer.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../compat/api/validation/encoding/cmds/copyTextureToBuffer.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/cmds/copyTextureToTexture.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/cmds/copyTextureToTexture.worker.js new file mode 100644 index 0000000000..f8e1928824 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/cmds/copyTextureToTexture.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../compat/api/validation/encoding/cmds/copyTextureToTexture.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/programmable/pipeline_bind_group_compat.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/programmable/pipeline_bind_group_compat.worker.js new file mode 100644 index 0000000000..af10ab581c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/encoding/programmable/pipeline_bind_group_compat.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../compat/api/validation/encoding/programmable/pipeline_bind_group_compat.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/depth_stencil_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/depth_stencil_state.worker.js new file mode 100644 index 0000000000..d24b5fa745 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/depth_stencil_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../compat/api/validation/render_pipeline/depth_stencil_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/fragment_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/fragment_state.worker.js new file mode 100644 index 0000000000..98196d03d1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/fragment_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../compat/api/validation/render_pipeline/fragment_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/shader_module.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/shader_module.worker.js new file mode 100644 index 0000000000..802dbe6232 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/shader_module.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../compat/api/validation/render_pipeline/shader_module.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/vertex_state.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/vertex_state.worker.js new file mode 100644 index 0000000000..20e8dd4ce7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/render_pipeline/vertex_state.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../compat/api/validation/render_pipeline/vertex_state.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/texture/createTexture.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/texture/createTexture.worker.js new file mode 100644 index 0000000000..d0fb1f6d70 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/texture/createTexture.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../compat/api/validation/texture/createTexture.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/texture/cubeArray.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/texture/cubeArray.worker.js new file mode 100644 index 0000000000..53286a2488 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/compat/api/validation/texture/cubeArray.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../compat/api/validation/texture/cubeArray.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/examples.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/examples.worker.js new file mode 100644 index 0000000000..ecd9374c22 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/examples.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../examples.spec.js'; +import { wrapTestGroupForWorker } from '../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/idl/constants/flags.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/idl/constants/flags.worker.js new file mode 100644 index 0000000000..f54be7798f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/idl/constants/flags.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../idl/constants/flags.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/idl/constructable.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/idl/constructable.worker.js new file mode 100644 index 0000000000..fe624207cb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/idl/constructable.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../idl/constructable.spec.js'; +import { wrapTestGroupForWorker } from '../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/print_environment.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/print_environment.worker.js new file mode 100644 index 0000000000..71ab073cc1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/print_environment.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../print_environment.spec.js'; +import { wrapTestGroupForWorker } from '../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/array/index.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/array/index.worker.js new file mode 100644 index 0000000000..9cc97b7c4e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/array/index.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/access/array/index.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/matrix/index.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/matrix/index.worker.js new file mode 100644 index 0000000000..9538240899 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/matrix/index.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/access/matrix/index.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/structure/index.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/structure/index.worker.js new file mode 100644 index 0000000000..9aa32ce479 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/structure/index.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/access/structure/index.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/vector/components.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/vector/components.worker.js new file mode 100644 index 0000000000..076c7fed90 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/vector/components.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/access/vector/components.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/vector/index.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/vector/index.worker.js new file mode 100644 index 0000000000..3781e618ff --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/access/vector/index.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/access/vector/index.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_addition.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_addition.worker.js new file mode 100644 index 0000000000..3f25d7f105 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_addition.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_addition.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_comparison.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_comparison.worker.js new file mode 100644 index 0000000000..7cf5dd3314 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_comparison.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_comparison.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_division.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_division.worker.js new file mode 100644 index 0000000000..17a9993f95 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_division.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_division.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_addition.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_addition.worker.js new file mode 100644 index 0000000000..2bc11305ae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_addition.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_matrix_addition.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_matrix_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_matrix_multiplication.worker.js new file mode 100644 index 0000000000..c22a0382f9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_matrix_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_matrix_matrix_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_scalar_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_scalar_multiplication.worker.js new file mode 100644 index 0000000000..b5b23f073c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_scalar_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_matrix_scalar_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_subtraction.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_subtraction.worker.js new file mode 100644 index 0000000000..926d93f629 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_subtraction.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_matrix_subtraction.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_vector_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_vector_multiplication.worker.js new file mode 100644 index 0000000000..8e2de76fda --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_matrix_vector_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_matrix_vector_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_multiplication.worker.js new file mode 100644 index 0000000000..2a313bcbe7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_remainder.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_remainder.worker.js new file mode 100644 index 0000000000..79ff0a10a7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_remainder.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_remainder.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_subtraction.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_subtraction.worker.js new file mode 100644 index 0000000000..59de223470 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/af_subtraction.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/af_subtraction.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/ai_arithmetic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/ai_arithmetic.worker.js new file mode 100644 index 0000000000..35c5bad2bb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/ai_arithmetic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/ai_arithmetic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/ai_comparison.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/ai_comparison.worker.js new file mode 100644 index 0000000000..bf119f5a82 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/ai_comparison.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/ai_comparison.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bitwise.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bitwise.worker.js new file mode 100644 index 0000000000..1b78a11416 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bitwise.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/bitwise.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bitwise_shift.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bitwise_shift.worker.js new file mode 100644 index 0000000000..50df7799cc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bitwise_shift.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/bitwise_shift.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bool_logical.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bool_logical.worker.js new file mode 100644 index 0000000000..c97a65500a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/bool_logical.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/bool_logical.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_addition.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_addition.worker.js new file mode 100644 index 0000000000..b4d1ba4e9a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_addition.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_addition.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_comparison.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_comparison.worker.js new file mode 100644 index 0000000000..343e81cd66 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_comparison.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_comparison.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_division.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_division.worker.js new file mode 100644 index 0000000000..df89b1d70f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_division.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_division.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_addition.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_addition.worker.js new file mode 100644 index 0000000000..3d37d6b028 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_addition.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_matrix_addition.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_matrix_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_matrix_multiplication.worker.js new file mode 100644 index 0000000000..f66a6197dc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_matrix_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_matrix_matrix_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_scalar_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_scalar_multiplication.worker.js new file mode 100644 index 0000000000..560e1f8d73 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_scalar_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_matrix_scalar_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_subtraction.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_subtraction.worker.js new file mode 100644 index 0000000000..f8b9a5c9fb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_subtraction.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_matrix_subtraction.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_vector_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_vector_multiplication.worker.js new file mode 100644 index 0000000000..d15ae4e874 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_matrix_vector_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_matrix_vector_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_multiplication.worker.js new file mode 100644 index 0000000000..07a20c242c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_remainder.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_remainder.worker.js new file mode 100644 index 0000000000..2062f2f6c2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_remainder.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_remainder.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_subtraction.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_subtraction.worker.js new file mode 100644 index 0000000000..0812e2596a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f16_subtraction.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f16_subtraction.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_addition.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_addition.worker.js new file mode 100644 index 0000000000..6a4e856781 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_addition.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_addition.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_comparison.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_comparison.worker.js new file mode 100644 index 0000000000..24be70b2b1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_comparison.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_comparison.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_division.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_division.worker.js new file mode 100644 index 0000000000..c4c529c8f4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_division.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_division.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_addition.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_addition.worker.js new file mode 100644 index 0000000000..f1782f5375 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_addition.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_matrix_addition.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_matrix_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_matrix_multiplication.worker.js new file mode 100644 index 0000000000..039780dcae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_matrix_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_matrix_matrix_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_scalar_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_scalar_multiplication.worker.js new file mode 100644 index 0000000000..4438ac0342 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_scalar_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_matrix_scalar_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_subtraction.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_subtraction.worker.js new file mode 100644 index 0000000000..02f57adfac --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_subtraction.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_matrix_subtraction.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_vector_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_vector_multiplication.worker.js new file mode 100644 index 0000000000..ddb363aaa4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_matrix_vector_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_matrix_vector_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_multiplication.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_multiplication.worker.js new file mode 100644 index 0000000000..7fec7f76d5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_multiplication.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_multiplication.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_remainder.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_remainder.worker.js new file mode 100644 index 0000000000..05b5a3c79f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_remainder.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_remainder.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_subtraction.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_subtraction.worker.js new file mode 100644 index 0000000000..c227a5eab5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/f32_subtraction.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/f32_subtraction.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/i32_arithmetic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/i32_arithmetic.worker.js new file mode 100644 index 0000000000..9cb5320d76 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/i32_arithmetic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/i32_arithmetic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/i32_comparison.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/i32_comparison.worker.js new file mode 100644 index 0000000000..54b62bca25 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/i32_comparison.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/i32_comparison.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/u32_arithmetic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/u32_arithmetic.worker.js new file mode 100644 index 0000000000..a630ff22b3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/u32_arithmetic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/u32_arithmetic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/u32_comparison.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/u32_comparison.worker.js new file mode 100644 index 0000000000..f554e8aa26 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/binary/u32_comparison.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/binary/u32_comparison.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/abs.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/abs.worker.js new file mode 100644 index 0000000000..1a0c5737c4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/abs.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/abs.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/acos.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/acos.worker.js new file mode 100644 index 0000000000..918deeca0a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/acos.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/acos.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/acosh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/acosh.worker.js new file mode 100644 index 0000000000..eebceffa12 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/acosh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/acosh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/all.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/all.worker.js new file mode 100644 index 0000000000..9232689fb1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/all.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/all.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/any.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/any.worker.js new file mode 100644 index 0000000000..ee03b527c3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/any.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/any.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/arrayLength.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/arrayLength.worker.js new file mode 100644 index 0000000000..d13d0e9412 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/arrayLength.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/arrayLength.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/asin.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/asin.worker.js new file mode 100644 index 0000000000..84b154faae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/asin.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/asin.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/asinh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/asinh.worker.js new file mode 100644 index 0000000000..94eef38c0d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/asinh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/asinh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atan.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atan.worker.js new file mode 100644 index 0000000000..0e583ed82f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atan.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/atan.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atan2.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atan2.worker.js new file mode 100644 index 0000000000..04e39bb68e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atan2.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/atan2.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atanh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atanh.worker.js new file mode 100644 index 0000000000..6c807c08bb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atanh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/atanh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicAdd.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicAdd.worker.js new file mode 100644 index 0000000000..76f5f7443f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicAdd.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicAdd.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicAnd.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicAnd.worker.js new file mode 100644 index 0000000000..a86260b414 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicAnd.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicAnd.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicCompareExchangeWeak.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicCompareExchangeWeak.worker.js new file mode 100644 index 0000000000..ba86a54244 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicCompareExchangeWeak.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicCompareExchangeWeak.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicExchange.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicExchange.worker.js new file mode 100644 index 0000000000..53f4028fa4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicExchange.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicExchange.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicLoad.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicLoad.worker.js new file mode 100644 index 0000000000..aac4f05de0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicLoad.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicLoad.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicMax.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicMax.worker.js new file mode 100644 index 0000000000..d000bc90ad --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicMax.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicMax.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicMin.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicMin.worker.js new file mode 100644 index 0000000000..12db37164b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicMin.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicMin.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicOr.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicOr.worker.js new file mode 100644 index 0000000000..0416b23e84 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicOr.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicOr.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicStore.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicStore.worker.js new file mode 100644 index 0000000000..591ea6c135 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicStore.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicStore.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicSub.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicSub.worker.js new file mode 100644 index 0000000000..8767389e87 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicSub.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicSub.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicXor.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicXor.worker.js new file mode 100644 index 0000000000..c239fc2797 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/atomics/atomicXor.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../../shader/execution/expression/call/builtin/atomics/atomicXor.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/bitcast.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/bitcast.worker.js new file mode 100644 index 0000000000..481abb1d26 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/bitcast.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/bitcast.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/ceil.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/ceil.worker.js new file mode 100644 index 0000000000..c24b27665d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/ceil.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/ceil.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/clamp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/clamp.worker.js new file mode 100644 index 0000000000..19ab86e3ff --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/clamp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/clamp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cos.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cos.worker.js new file mode 100644 index 0000000000..b10ddecef7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cos.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/cos.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cosh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cosh.worker.js new file mode 100644 index 0000000000..f5613135c4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cosh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/cosh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countLeadingZeros.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countLeadingZeros.worker.js new file mode 100644 index 0000000000..9b3e765eb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countLeadingZeros.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/countLeadingZeros.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countOneBits.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countOneBits.worker.js new file mode 100644 index 0000000000..755c44f883 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countOneBits.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/countOneBits.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countTrailingZeros.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countTrailingZeros.worker.js new file mode 100644 index 0000000000..023d8979a6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/countTrailingZeros.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/countTrailingZeros.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cross.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cross.worker.js new file mode 100644 index 0000000000..e741a038c2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/cross.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/cross.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/degrees.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/degrees.worker.js new file mode 100644 index 0000000000..11a9befc7c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/degrees.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/degrees.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/determinant.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/determinant.worker.js new file mode 100644 index 0000000000..d7b2083a0c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/determinant.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/determinant.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/distance.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/distance.worker.js new file mode 100644 index 0000000000..d08c9b959f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/distance.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/distance.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot.worker.js new file mode 100644 index 0000000000..ba9b9861c4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/dot.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot4I8Packed.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot4I8Packed.worker.js new file mode 100644 index 0000000000..47e81aee2c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot4I8Packed.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/dot4I8Packed.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot4U8Packed.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot4U8Packed.worker.js new file mode 100644 index 0000000000..1997d58883 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dot4U8Packed.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/dot4U8Packed.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdx.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdx.worker.js new file mode 100644 index 0000000000..1f23c8f743 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdx.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/dpdx.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdxCoarse.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdxCoarse.worker.js new file mode 100644 index 0000000000..332238aa98 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdxCoarse.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/dpdxCoarse.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdxFine.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdxFine.worker.js new file mode 100644 index 0000000000..45d0dd15f6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdxFine.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/dpdxFine.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdy.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdy.worker.js new file mode 100644 index 0000000000..d7fa774c70 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdy.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/dpdy.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdyCoarse.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdyCoarse.worker.js new file mode 100644 index 0000000000..f818422cf4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdyCoarse.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/dpdyCoarse.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdyFine.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdyFine.worker.js new file mode 100644 index 0000000000..b96b3c2d7b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/dpdyFine.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/dpdyFine.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/exp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/exp.worker.js new file mode 100644 index 0000000000..b3f99653b1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/exp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/exp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/exp2.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/exp2.worker.js new file mode 100644 index 0000000000..943f79d3fa --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/exp2.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/exp2.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/extractBits.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/extractBits.worker.js new file mode 100644 index 0000000000..1e720dea49 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/extractBits.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/extractBits.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/faceForward.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/faceForward.worker.js new file mode 100644 index 0000000000..771f30a6ab --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/faceForward.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/faceForward.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/firstLeadingBit.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/firstLeadingBit.worker.js new file mode 100644 index 0000000000..560b19314c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/firstLeadingBit.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/firstLeadingBit.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/firstTrailingBit.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/firstTrailingBit.worker.js new file mode 100644 index 0000000000..6a4da57be1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/firstTrailingBit.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/firstTrailingBit.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/floor.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/floor.worker.js new file mode 100644 index 0000000000..577ee0ff0f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/floor.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/floor.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fma.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fma.worker.js new file mode 100644 index 0000000000..278df59865 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fma.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/fma.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fract.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fract.worker.js new file mode 100644 index 0000000000..f96aff459e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fract.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/fract.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/frexp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/frexp.worker.js new file mode 100644 index 0000000000..08efc30280 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/frexp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/frexp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidth.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidth.worker.js new file mode 100644 index 0000000000..ebb0a1e612 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidth.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/fwidth.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidthCoarse.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidthCoarse.worker.js new file mode 100644 index 0000000000..17e286ccf2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidthCoarse.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/fwidthCoarse.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidthFine.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidthFine.worker.js new file mode 100644 index 0000000000..a8ec6865ac --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/fwidthFine.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/fwidthFine.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/insertBits.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/insertBits.worker.js new file mode 100644 index 0000000000..244c0aef8d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/insertBits.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/insertBits.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/inversesqrt.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/inversesqrt.worker.js new file mode 100644 index 0000000000..3808e163f6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/inversesqrt.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/inversesqrt.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/ldexp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/ldexp.worker.js new file mode 100644 index 0000000000..538d662fe1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/ldexp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/ldexp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/length.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/length.worker.js new file mode 100644 index 0000000000..e9a7510c00 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/length.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/length.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/log.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/log.worker.js new file mode 100644 index 0000000000..a4726143d2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/log.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/log.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/log2.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/log2.worker.js new file mode 100644 index 0000000000..17f7b31233 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/log2.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/log2.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/max.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/max.worker.js new file mode 100644 index 0000000000..071ee77eb1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/max.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/max.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/min.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/min.worker.js new file mode 100644 index 0000000000..1f713e0877 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/min.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/min.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/mix.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/mix.worker.js new file mode 100644 index 0000000000..8d31ff9367 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/mix.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/mix.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/modf.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/modf.worker.js new file mode 100644 index 0000000000..b6f1af2f66 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/modf.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/modf.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/normalize.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/normalize.worker.js new file mode 100644 index 0000000000..41eba8d1ea --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/normalize.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/normalize.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16float.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16float.worker.js new file mode 100644 index 0000000000..0b607cc615 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16float.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/pack2x16float.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16snorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16snorm.worker.js new file mode 100644 index 0000000000..f4b1a9fc96 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16snorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/pack2x16snorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16unorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16unorm.worker.js new file mode 100644 index 0000000000..867aacc608 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack2x16unorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/pack2x16unorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4x8snorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4x8snorm.worker.js new file mode 100644 index 0000000000..80520d1f0b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4x8snorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/pack4x8snorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4x8unorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4x8unorm.worker.js new file mode 100644 index 0000000000..d78be03afb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4x8unorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/pack4x8unorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xI8.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xI8.worker.js new file mode 100644 index 0000000000..9e15ccc5c7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xI8.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/pack4xI8.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xI8Clamp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xI8Clamp.worker.js new file mode 100644 index 0000000000..2f3e6fe2da --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xI8Clamp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/pack4xI8Clamp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xU8.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xU8.worker.js new file mode 100644 index 0000000000..fd46e2f76b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xU8.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/pack4xU8.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xU8Clamp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xU8Clamp.worker.js new file mode 100644 index 0000000000..6f3ddc8d63 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pack4xU8Clamp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/pack4xU8Clamp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pow.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pow.worker.js new file mode 100644 index 0000000000..6bd477c788 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/pow.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/pow.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/quantizeToF16.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/quantizeToF16.worker.js new file mode 100644 index 0000000000..d99fc9bbab --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/quantizeToF16.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/quantizeToF16.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/radians.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/radians.worker.js new file mode 100644 index 0000000000..19f07b4d98 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/radians.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/radians.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/reflect.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/reflect.worker.js new file mode 100644 index 0000000000..cd834840ad --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/reflect.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/reflect.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/refract.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/refract.worker.js new file mode 100644 index 0000000000..a8a1de177d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/refract.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/refract.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/reverseBits.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/reverseBits.worker.js new file mode 100644 index 0000000000..11f63b1017 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/reverseBits.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/reverseBits.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/round.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/round.worker.js new file mode 100644 index 0000000000..3d159b6718 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/round.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/round.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/saturate.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/saturate.worker.js new file mode 100644 index 0000000000..81d2f8f62f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/saturate.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/saturate.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/select.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/select.worker.js new file mode 100644 index 0000000000..35a204c1c1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/select.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/select.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sign.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sign.worker.js new file mode 100644 index 0000000000..7125ebd4ea --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sign.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/sign.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sin.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sin.worker.js new file mode 100644 index 0000000000..9cd044bf3b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sin.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/sin.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sinh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sinh.worker.js new file mode 100644 index 0000000000..d248983ec1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sinh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/sinh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/smoothstep.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/smoothstep.worker.js new file mode 100644 index 0000000000..e7c6422316 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/smoothstep.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/smoothstep.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sqrt.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sqrt.worker.js new file mode 100644 index 0000000000..c5718ef571 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/sqrt.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/sqrt.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/step.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/step.worker.js new file mode 100644 index 0000000000..78b2e7056d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/step.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/step.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/storageBarrier.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/storageBarrier.worker.js new file mode 100644 index 0000000000..bc40263641 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/storageBarrier.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/storageBarrier.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/tan.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/tan.worker.js new file mode 100644 index 0000000000..4ed7807bda --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/tan.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/tan.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/tanh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/tanh.worker.js new file mode 100644 index 0000000000..f24791180a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/tanh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/tanh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureDimensions.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureDimensions.worker.js new file mode 100644 index 0000000000..eda70ffb33 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureDimensions.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureDimensions.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureGather.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureGather.worker.js new file mode 100644 index 0000000000..c632b85bb8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureGather.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureGather.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureGatherCompare.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureGatherCompare.worker.js new file mode 100644 index 0000000000..cf00fc8ae6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureGatherCompare.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureGatherCompare.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureLoad.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureLoad.worker.js new file mode 100644 index 0000000000..3f7aeaf39b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureLoad.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureLoad.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumLayers.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumLayers.worker.js new file mode 100644 index 0000000000..5cad50f39d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumLayers.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureNumLayers.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumLevels.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumLevels.worker.js new file mode 100644 index 0000000000..d1d13ca8f1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumLevels.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureNumLevels.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumSamples.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumSamples.worker.js new file mode 100644 index 0000000000..3636b6fc5c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureNumSamples.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureNumSamples.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSample.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSample.worker.js new file mode 100644 index 0000000000..8d6cffd972 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSample.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureSample.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleBias.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleBias.worker.js new file mode 100644 index 0000000000..6f15b0455f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleBias.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureSampleBias.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleCompare.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleCompare.worker.js new file mode 100644 index 0000000000..7b2442f62e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleCompare.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureSampleCompare.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleCompareLevel.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleCompareLevel.worker.js new file mode 100644 index 0000000000..ce8edf2a39 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleCompareLevel.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureSampleCompareLevel.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleGrad.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleGrad.worker.js new file mode 100644 index 0000000000..4b93570bb6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleGrad.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureSampleGrad.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleLevel.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleLevel.worker.js new file mode 100644 index 0000000000..36c0342b3c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureSampleLevel.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureSampleLevel.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureStore.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureStore.worker.js new file mode 100644 index 0000000000..7c3ef351ef --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/textureStore.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/textureStore.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/transpose.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/transpose.worker.js new file mode 100644 index 0000000000..ad5e60d152 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/transpose.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/transpose.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/trunc.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/trunc.worker.js new file mode 100644 index 0000000000..0b312f07a8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/trunc.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/trunc.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16float.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16float.worker.js new file mode 100644 index 0000000000..b2fd425c06 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16float.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/unpack2x16float.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16snorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16snorm.worker.js new file mode 100644 index 0000000000..6eb4703282 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16snorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/unpack2x16snorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16unorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16unorm.worker.js new file mode 100644 index 0000000000..6b8b918cf0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack2x16unorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/unpack2x16unorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4x8snorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4x8snorm.worker.js new file mode 100644 index 0000000000..281dd18ee9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4x8snorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/unpack4x8snorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4x8unorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4x8unorm.worker.js new file mode 100644 index 0000000000..d67901b286 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4x8unorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/unpack4x8unorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4xI8.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4xI8.worker.js new file mode 100644 index 0000000000..c5b84ae2c5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4xI8.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/unpack4xI8.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4xU8.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4xU8.worker.js new file mode 100644 index 0000000000..59d7cf25b3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/unpack4xU8.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/unpack4xU8.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/workgroupBarrier.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/workgroupBarrier.worker.js new file mode 100644 index 0000000000..5a2ff0b830 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/workgroupBarrier.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/workgroupBarrier.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/workgroupUniformLoad.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/workgroupUniformLoad.worker.js new file mode 100644 index 0000000000..9b341af87d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/builtin/workgroupUniformLoad.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/builtin/workgroupUniformLoad.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/user/ptr_params.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/user/ptr_params.worker.js new file mode 100644 index 0000000000..850fec5f5f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/call/user/ptr_params.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/execution/expression/call/user/ptr_params.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/constructor/non_zero.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/constructor/non_zero.worker.js new file mode 100644 index 0000000000..ae66debc94 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/constructor/non_zero.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/constructor/non_zero.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/constructor/zero_value.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/constructor/zero_value.worker.js new file mode 100644 index 0000000000..9ddbaa9dae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/constructor/zero_value.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/constructor/zero_value.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/precedence.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/precedence.worker.js new file mode 100644 index 0000000000..a83f045413 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/precedence.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/expression/precedence.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/address_of_and_indirection.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/address_of_and_indirection.worker.js new file mode 100644 index 0000000000..e893985692 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/address_of_and_indirection.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/address_of_and_indirection.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/af_arithmetic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/af_arithmetic.worker.js new file mode 100644 index 0000000000..d0c1b8f3d5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/af_arithmetic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/af_arithmetic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/af_assignment.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/af_assignment.worker.js new file mode 100644 index 0000000000..cc871a1984 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/af_assignment.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/af_assignment.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_arithmetic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_arithmetic.worker.js new file mode 100644 index 0000000000..ba35df7186 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_arithmetic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/ai_arithmetic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_assignment.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_assignment.worker.js new file mode 100644 index 0000000000..9431211f17 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_assignment.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/ai_assignment.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_complement.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_complement.worker.js new file mode 100644 index 0000000000..db525f760b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/ai_complement.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/ai_complement.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/bool_conversion.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/bool_conversion.worker.js new file mode 100644 index 0000000000..303fc054ef --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/bool_conversion.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/bool_conversion.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/bool_logical.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/bool_logical.worker.js new file mode 100644 index 0000000000..77674f07c7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/bool_logical.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/bool_logical.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f16_arithmetic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f16_arithmetic.worker.js new file mode 100644 index 0000000000..1bcd1bdd23 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f16_arithmetic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/f16_arithmetic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f16_conversion.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f16_conversion.worker.js new file mode 100644 index 0000000000..a6b5ac343a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f16_conversion.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/f16_conversion.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f32_arithmetic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f32_arithmetic.worker.js new file mode 100644 index 0000000000..8ec016fb00 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f32_arithmetic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/f32_arithmetic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f32_conversion.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f32_conversion.worker.js new file mode 100644 index 0000000000..d175bd5dca --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/f32_conversion.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/f32_conversion.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_arithmetic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_arithmetic.worker.js new file mode 100644 index 0000000000..f435320547 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_arithmetic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/i32_arithmetic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_complement.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_complement.worker.js new file mode 100644 index 0000000000..00ea9f8c25 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_complement.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/i32_complement.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_conversion.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_conversion.worker.js new file mode 100644 index 0000000000..28302ac1fc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/i32_conversion.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/i32_conversion.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/u32_complement.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/u32_complement.worker.js new file mode 100644 index 0000000000..c2a5ca0688 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/u32_complement.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/u32_complement.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/u32_conversion.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/u32_conversion.worker.js new file mode 100644 index 0000000000..ac55bd61e2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/expression/unary/u32_conversion.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/execution/expression/unary/u32_conversion.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/float_parse.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/float_parse.worker.js new file mode 100644 index 0000000000..070bb888f6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/float_parse.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../shader/execution/float_parse.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/call.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/call.worker.js new file mode 100644 index 0000000000..03930d032c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/call.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/flow_control/call.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/complex.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/complex.worker.js new file mode 100644 index 0000000000..1cd99e11c0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/complex.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/flow_control/complex.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/eval_order.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/eval_order.worker.js new file mode 100644 index 0000000000..78b9b84fd3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/eval_order.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/flow_control/eval_order.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/for.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/for.worker.js new file mode 100644 index 0000000000..379c29f9ce --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/for.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/flow_control/for.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/if.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/if.worker.js new file mode 100644 index 0000000000..9b086d3ed7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/if.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/flow_control/if.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/loop.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/loop.worker.js new file mode 100644 index 0000000000..bab864b5c3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/loop.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/flow_control/loop.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/phony.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/phony.worker.js new file mode 100644 index 0000000000..5badcd1df8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/phony.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/flow_control/phony.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/return.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/return.worker.js new file mode 100644 index 0000000000..8e545f3fae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/return.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/flow_control/return.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/switch.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/switch.worker.js new file mode 100644 index 0000000000..845493427b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/switch.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/flow_control/switch.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/while.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/while.worker.js new file mode 100644 index 0000000000..3eae348390 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/flow_control/while.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/flow_control/while.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_layout.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_layout.worker.js new file mode 100644 index 0000000000..a89aac4149 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_layout.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../shader/execution/memory_layout.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/adjacent.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/adjacent.worker.js new file mode 100644 index 0000000000..3c7ead1467 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/adjacent.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/memory_model/adjacent.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/atomicity.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/atomicity.worker.js new file mode 100644 index 0000000000..d26549c1e3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/atomicity.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/memory_model/atomicity.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/barrier.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/barrier.worker.js new file mode 100644 index 0000000000..e97bc4eb86 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/barrier.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/memory_model/barrier.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/coherence.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/coherence.worker.js new file mode 100644 index 0000000000..289c01b354 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/coherence.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/memory_model/coherence.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/texture_intra_invocation_coherence.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/texture_intra_invocation_coherence.worker.js new file mode 100644 index 0000000000..00a5fabc3a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/texture_intra_invocation_coherence.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/memory_model/texture_intra_invocation_coherence.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/weak.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/weak.worker.js new file mode 100644 index 0000000000..fc4486c6e3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/memory_model/weak.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/memory_model/weak.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/padding.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/padding.worker.js new file mode 100644 index 0000000000..23e642f6c1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/padding.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../shader/execution/padding.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/robust_access.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/robust_access.worker.js new file mode 100644 index 0000000000..9651705007 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/robust_access.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../shader/execution/robust_access.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/robust_access_vertex.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/robust_access_vertex.worker.js new file mode 100644 index 0000000000..909c40a797 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/robust_access_vertex.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../shader/execution/robust_access_vertex.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/compute_builtins.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/compute_builtins.worker.js new file mode 100644 index 0000000000..1050903769 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/compute_builtins.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/shader_io/compute_builtins.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/fragment_builtins.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/fragment_builtins.worker.js new file mode 100644 index 0000000000..b8332b455a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/fragment_builtins.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/shader_io/fragment_builtins.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/shared_structs.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/shared_structs.worker.js new file mode 100644 index 0000000000..399b32a33b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/shared_structs.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/shader_io/shared_structs.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/user_io.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/user_io.worker.js new file mode 100644 index 0000000000..2b4570a48c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/user_io.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/shader_io/user_io.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/workgroup_size.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/workgroup_size.worker.js new file mode 100644 index 0000000000..31827b5e39 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shader_io/workgroup_size.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/shader_io/workgroup_size.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shadow.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shadow.worker.js new file mode 100644 index 0000000000..b0c166c51c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/shadow.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../shader/execution/shadow.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/stage.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/stage.worker.js new file mode 100644 index 0000000000..c30bb087de --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/stage.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../shader/execution/stage.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/compound.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/compound.worker.js new file mode 100644 index 0000000000..e25b55ffdf --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/compound.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/statement/compound.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/discard.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/discard.worker.js new file mode 100644 index 0000000000..16353062fd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/discard.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/statement/discard.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/increment_decrement.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/increment_decrement.worker.js new file mode 100644 index 0000000000..6d82f16828 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/statement/increment_decrement.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/execution/statement/increment_decrement.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/zero_init.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/zero_init.worker.js new file mode 100644 index 0000000000..5e79410031 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/execution/zero_init.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../shader/execution/zero_init.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/const_assert/const_assert.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/const_assert/const_assert.worker.js new file mode 100644 index 0000000000..58990b9148 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/const_assert/const_assert.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/const_assert/const_assert.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/compound_statement.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/compound_statement.worker.js new file mode 100644 index 0000000000..815908c745 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/compound_statement.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/decl/compound_statement.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/const.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/const.worker.js new file mode 100644 index 0000000000..37baed5e7f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/const.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/decl/const.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/context_dependent_resolution.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/context_dependent_resolution.worker.js new file mode 100644 index 0000000000..c2ebfd9e90 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/context_dependent_resolution.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/decl/context_dependent_resolution.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/let.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/let.worker.js new file mode 100644 index 0000000000..75234ef572 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/let.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/decl/let.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/override.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/override.worker.js new file mode 100644 index 0000000000..bfe7adb3c1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/override.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/decl/override.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/ptr_spelling.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/ptr_spelling.worker.js new file mode 100644 index 0000000000..e2e4f51335 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/ptr_spelling.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/decl/ptr_spelling.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/var.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/var.worker.js new file mode 100644 index 0000000000..832a4601cf --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/var.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/decl/var.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/var_access_mode.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/var_access_mode.worker.js new file mode 100644 index 0000000000..b9d4a17093 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/decl/var_access_mode.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/decl/var_access_mode.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/access/vector.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/access/vector.worker.js new file mode 100644 index 0000000000..dc667d4538 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/access/vector.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/validation/expression/access/vector.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/add_sub_mul.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/add_sub_mul.worker.js new file mode 100644 index 0000000000..34ae46a86f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/add_sub_mul.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/validation/expression/binary/add_sub_mul.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/and_or_xor.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/and_or_xor.worker.js new file mode 100644 index 0000000000..d5423e6225 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/and_or_xor.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/validation/expression/binary/and_or_xor.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/bitwise_shift.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/bitwise_shift.worker.js new file mode 100644 index 0000000000..b1b74edf02 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/bitwise_shift.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/validation/expression/binary/bitwise_shift.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/comparison.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/comparison.worker.js new file mode 100644 index 0000000000..b44f38ccee --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/comparison.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/validation/expression/binary/comparison.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/div_rem.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/div_rem.worker.js new file mode 100644 index 0000000000..4d1e0c841d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/binary/div_rem.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/validation/expression/binary/div_rem.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/abs.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/abs.worker.js new file mode 100644 index 0000000000..efa3463179 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/abs.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/abs.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/acos.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/acos.worker.js new file mode 100644 index 0000000000..0575195da9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/acos.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/acos.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/acosh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/acosh.worker.js new file mode 100644 index 0000000000..ede7c1e3d1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/acosh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/acosh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/all.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/all.worker.js new file mode 100644 index 0000000000..e744084877 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/all.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/all.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/any.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/any.worker.js new file mode 100644 index 0000000000..f79ee3ccb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/any.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/any.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/arrayLength.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/arrayLength.worker.js new file mode 100644 index 0000000000..efea85fabf --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/arrayLength.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/arrayLength.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/asin.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/asin.worker.js new file mode 100644 index 0000000000..d8037c639e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/asin.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/asin.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/asinh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/asinh.worker.js new file mode 100644 index 0000000000..255cbdce4c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/asinh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/asinh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atan.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atan.worker.js new file mode 100644 index 0000000000..7dd6276878 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atan.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/atan.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atan2.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atan2.worker.js new file mode 100644 index 0000000000..db2d9a6ac3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atan2.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/atan2.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atanh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atanh.worker.js new file mode 100644 index 0000000000..2d610e868a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atanh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/atanh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atomics.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atomics.worker.js new file mode 100644 index 0000000000..94fa14244e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/atomics.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/atomics.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/barriers.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/barriers.worker.js new file mode 100644 index 0000000000..6055fde465 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/barriers.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/barriers.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/bitcast.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/bitcast.worker.js new file mode 100644 index 0000000000..00b3673e4b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/bitcast.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/bitcast.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/ceil.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/ceil.worker.js new file mode 100644 index 0000000000..ab5ec7adf7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/ceil.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/ceil.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/clamp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/clamp.worker.js new file mode 100644 index 0000000000..3d09f8f68d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/clamp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/clamp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cos.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cos.worker.js new file mode 100644 index 0000000000..cf9af678f3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cos.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/cos.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cosh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cosh.worker.js new file mode 100644 index 0000000000..e29d253a6f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cosh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/cosh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countLeadingZeros.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countLeadingZeros.worker.js new file mode 100644 index 0000000000..1555d2b211 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countLeadingZeros.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/countLeadingZeros.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countOneBits.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countOneBits.worker.js new file mode 100644 index 0000000000..7116dae8ba --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countOneBits.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/countOneBits.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countTrailingZeros.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countTrailingZeros.worker.js new file mode 100644 index 0000000000..fab97cbfd7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/countTrailingZeros.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/countTrailingZeros.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cross.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cross.worker.js new file mode 100644 index 0000000000..7a69266441 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/cross.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/cross.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/degrees.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/degrees.worker.js new file mode 100644 index 0000000000..b5653c8ca1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/degrees.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/degrees.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/derivatives.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/derivatives.worker.js new file mode 100644 index 0000000000..3c127105b9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/derivatives.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/derivatives.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/determinant.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/determinant.worker.js new file mode 100644 index 0000000000..191c4352e4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/determinant.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/determinant.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/distance.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/distance.worker.js new file mode 100644 index 0000000000..0d7c43c2a1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/distance.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/distance.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/dot4I8Packed.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/dot4I8Packed.worker.js new file mode 100644 index 0000000000..f30e513574 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/dot4I8Packed.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/dot4I8Packed.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/dot4U8Packed.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/dot4U8Packed.worker.js new file mode 100644 index 0000000000..decdbc1387 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/dot4U8Packed.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/dot4U8Packed.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/exp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/exp.worker.js new file mode 100644 index 0000000000..247338299d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/exp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/exp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/exp2.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/exp2.worker.js new file mode 100644 index 0000000000..1f6aaf585b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/exp2.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/exp2.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/extractBits.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/extractBits.worker.js new file mode 100644 index 0000000000..a869a585ef --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/extractBits.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/extractBits.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/faceForward.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/faceForward.worker.js new file mode 100644 index 0000000000..d61b7555cc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/faceForward.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/faceForward.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/firstLeadingBit.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/firstLeadingBit.worker.js new file mode 100644 index 0000000000..a7c401830a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/firstLeadingBit.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/firstLeadingBit.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/firstTrailingBit.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/firstTrailingBit.worker.js new file mode 100644 index 0000000000..d1079ddf88 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/firstTrailingBit.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/firstTrailingBit.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/floor.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/floor.worker.js new file mode 100644 index 0000000000..636e721f14 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/floor.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/floor.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/fract.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/fract.worker.js new file mode 100644 index 0000000000..0bcd6610eb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/fract.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/fract.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/frexp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/frexp.worker.js new file mode 100644 index 0000000000..89c4f4d5ef --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/frexp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/frexp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/insertBits.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/insertBits.worker.js new file mode 100644 index 0000000000..fa96c1d121 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/insertBits.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/insertBits.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/inverseSqrt.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/inverseSqrt.worker.js new file mode 100644 index 0000000000..6decc3216c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/inverseSqrt.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/inverseSqrt.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/length.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/length.worker.js new file mode 100644 index 0000000000..609f0bd26a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/length.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/length.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/log.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/log.worker.js new file mode 100644 index 0000000000..339e911dcd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/log.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/log.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/log2.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/log2.worker.js new file mode 100644 index 0000000000..bd2490ee01 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/log2.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/log2.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/max.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/max.worker.js new file mode 100644 index 0000000000..0660d196f2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/max.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/max.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/min.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/min.worker.js new file mode 100644 index 0000000000..4d0d4896cf --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/min.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/min.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/modf.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/modf.worker.js new file mode 100644 index 0000000000..55f2b00583 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/modf.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/modf.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/normalize.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/normalize.worker.js new file mode 100644 index 0000000000..cb8077d1d6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/normalize.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/normalize.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack2x16snorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack2x16snorm.worker.js new file mode 100644 index 0000000000..21d8d4b881 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack2x16snorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/pack2x16snorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack2x16unorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack2x16unorm.worker.js new file mode 100644 index 0000000000..1df8200fd3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack2x16unorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/pack2x16unorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4x8snorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4x8snorm.worker.js new file mode 100644 index 0000000000..2bc4b2737c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4x8snorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/pack4x8snorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4x8unorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4x8unorm.worker.js new file mode 100644 index 0000000000..32b359c074 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4x8unorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/pack4x8unorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xI8.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xI8.worker.js new file mode 100644 index 0000000000..1f7ea4059f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xI8.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/pack4xI8.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xI8Clamp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xI8Clamp.worker.js new file mode 100644 index 0000000000..504ef65f54 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xI8Clamp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/pack4xI8Clamp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xU8.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xU8.worker.js new file mode 100644 index 0000000000..50378494c3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xU8.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/pack4xU8.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xU8Clamp.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xU8Clamp.worker.js new file mode 100644 index 0000000000..a4392cae9d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/pack4xU8Clamp.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/pack4xU8Clamp.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/quantizeToF16.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/quantizeToF16.worker.js new file mode 100644 index 0000000000..0fe919929f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/quantizeToF16.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/quantizeToF16.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/radians.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/radians.worker.js new file mode 100644 index 0000000000..6c4a0ffcd4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/radians.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/radians.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/reflect.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/reflect.worker.js new file mode 100644 index 0000000000..9c5978d38d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/reflect.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/reflect.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/reverseBits.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/reverseBits.worker.js new file mode 100644 index 0000000000..e28c74fb71 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/reverseBits.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/reverseBits.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/round.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/round.worker.js new file mode 100644 index 0000000000..d2f3ad201d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/round.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/round.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/saturate.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/saturate.worker.js new file mode 100644 index 0000000000..f2c2f6c78f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/saturate.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/saturate.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/select.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/select.worker.js new file mode 100644 index 0000000000..b512734928 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/select.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/select.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sign.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sign.worker.js new file mode 100644 index 0000000000..24b9c617ad --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sign.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/sign.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sin.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sin.worker.js new file mode 100644 index 0000000000..daa78363cd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sin.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/sin.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sinh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sinh.worker.js new file mode 100644 index 0000000000..f09269f690 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sinh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/sinh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/smoothstep.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/smoothstep.worker.js new file mode 100644 index 0000000000..9c990e153c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/smoothstep.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/smoothstep.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sqrt.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sqrt.worker.js new file mode 100644 index 0000000000..8edaa59086 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/sqrt.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/sqrt.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/step.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/step.worker.js new file mode 100644 index 0000000000..bd3b7ba060 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/step.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/step.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/tan.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/tan.worker.js new file mode 100644 index 0000000000..39f53bb173 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/tan.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/tan.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/tanh.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/tanh.worker.js new file mode 100644 index 0000000000..9e9a1a438e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/tanh.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/tanh.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureGather.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureGather.worker.js new file mode 100644 index 0000000000..5cdd6b2f90 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureGather.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureGather.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureGatherCompare.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureGatherCompare.worker.js new file mode 100644 index 0000000000..9d4cb5ddcd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureGatherCompare.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureGatherCompare.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureLoad.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureLoad.worker.js new file mode 100644 index 0000000000..2ece8f78bd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureLoad.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureLoad.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSample.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSample.worker.js new file mode 100644 index 0000000000..9c8718f0e7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSample.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureSample.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge.worker.js new file mode 100644 index 0000000000..a22b541dc1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureSampleBaseClampToEdge.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleBias.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleBias.worker.js new file mode 100644 index 0000000000..0e13ca82dd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleBias.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureSampleBias.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleCompare.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleCompare.worker.js new file mode 100644 index 0000000000..0e7adb6429 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleCompare.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureSampleCompare.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleCompareLevel.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleCompareLevel.worker.js new file mode 100644 index 0000000000..3bb98849e1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleCompareLevel.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureSampleCompareLevel.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleGrad.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleGrad.worker.js new file mode 100644 index 0000000000..560763704f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleGrad.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureSampleGrad.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleLevel.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleLevel.worker.js new file mode 100644 index 0000000000..2ecbac54e1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureSampleLevel.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureSampleLevel.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureStore.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureStore.worker.js new file mode 100644 index 0000000000..edf8490943 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/textureStore.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/textureStore.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/trunc.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/trunc.worker.js new file mode 100644 index 0000000000..c21736648e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/trunc.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/trunc.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16float.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16float.worker.js new file mode 100644 index 0000000000..f9be70e83e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16float.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/unpack2x16float.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16snorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16snorm.worker.js new file mode 100644 index 0000000000..9b33b71784 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16snorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/unpack2x16snorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16unorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16unorm.worker.js new file mode 100644 index 0000000000..c3a856b8a4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack2x16unorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/unpack2x16unorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4x8snorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4x8snorm.worker.js new file mode 100644 index 0000000000..d1a576a28c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4x8snorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/unpack4x8snorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4x8unorm.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4x8unorm.worker.js new file mode 100644 index 0000000000..8d43d6ddd1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4x8unorm.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/unpack4x8unorm.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4xI8.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4xI8.worker.js new file mode 100644 index 0000000000..422c6d5a52 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4xI8.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/unpack4xI8.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4xU8.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4xU8.worker.js new file mode 100644 index 0000000000..e8b87e5b42 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/unpack4xU8.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/unpack4xU8.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/workgroupUniformLoad.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/workgroupUniformLoad.worker.js new file mode 100644 index 0000000000..8597dedce2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/call/builtin/workgroupUniformLoad.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../../shader/validation/expression/call/builtin/workgroupUniformLoad.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/overload_resolution.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/overload_resolution.worker.js new file mode 100644 index 0000000000..be8db508eb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/overload_resolution.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/expression/overload_resolution.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/precedence.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/precedence.worker.js new file mode 100644 index 0000000000..3cd2a99b0c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/precedence.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/expression/precedence.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/address_of_and_indirection.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/address_of_and_indirection.worker.js new file mode 100644 index 0000000000..a9474b7386 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/address_of_and_indirection.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/validation/expression/unary/address_of_and_indirection.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/arithmetic_negation.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/arithmetic_negation.worker.js new file mode 100644 index 0000000000..a62640f655 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/arithmetic_negation.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/validation/expression/unary/arithmetic_negation.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/bitwise_complement.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/bitwise_complement.worker.js new file mode 100644 index 0000000000..0ae7343d89 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/bitwise_complement.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/validation/expression/unary/bitwise_complement.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/logical_negation.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/logical_negation.worker.js new file mode 100644 index 0000000000..11e8044927 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/expression/unary/logical_negation.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../../shader/validation/expression/unary/logical_negation.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/extension/pointer_composite_access.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/extension/pointer_composite_access.worker.js new file mode 100644 index 0000000000..d773ad793d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/extension/pointer_composite_access.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/extension/pointer_composite_access.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/extension/readonly_and_readwrite_storage_textures.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/extension/readonly_and_readwrite_storage_textures.worker.js new file mode 100644 index 0000000000..8479487b10 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/extension/readonly_and_readwrite_storage_textures.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/extension/readonly_and_readwrite_storage_textures.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/functions/alias_analysis.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/functions/alias_analysis.worker.js new file mode 100644 index 0000000000..807f1217c2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/functions/alias_analysis.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/functions/alias_analysis.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/functions/restrictions.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/functions/restrictions.worker.js new file mode 100644 index 0000000000..6f73a16411 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/functions/restrictions.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/functions/restrictions.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/align.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/align.worker.js new file mode 100644 index 0000000000..57ca90b965 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/align.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/align.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/attribute.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/attribute.worker.js new file mode 100644 index 0000000000..acf3a57601 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/attribute.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/attribute.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/binary_ops.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/binary_ops.worker.js new file mode 100644 index 0000000000..6f0bcb6d57 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/binary_ops.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/binary_ops.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/blankspace.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/blankspace.worker.js new file mode 100644 index 0000000000..33333b84fe --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/blankspace.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/blankspace.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/break.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/break.worker.js new file mode 100644 index 0000000000..95f7cb9b86 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/break.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/break.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/break_if.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/break_if.worker.js new file mode 100644 index 0000000000..dfbd00dbf1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/break_if.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/break_if.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/builtin.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/builtin.worker.js new file mode 100644 index 0000000000..1e5cda49fa --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/builtin.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/builtin.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/comments.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/comments.worker.js new file mode 100644 index 0000000000..5f035ebcfc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/comments.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/comments.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/compound.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/compound.worker.js new file mode 100644 index 0000000000..91d11b6cf5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/compound.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/compound.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/const.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/const.worker.js new file mode 100644 index 0000000000..6c8671dd9f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/const.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/const.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/const_assert.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/const_assert.worker.js new file mode 100644 index 0000000000..deeedb07fd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/const_assert.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/const_assert.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/continuing.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/continuing.worker.js new file mode 100644 index 0000000000..d985904192 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/continuing.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/continuing.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/diagnostic.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/diagnostic.worker.js new file mode 100644 index 0000000000..a311d903a1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/diagnostic.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/diagnostic.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/discard.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/discard.worker.js new file mode 100644 index 0000000000..d9cfb613b2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/discard.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/discard.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/enable.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/enable.worker.js new file mode 100644 index 0000000000..8722aa3ec6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/enable.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/enable.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/identifiers.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/identifiers.worker.js new file mode 100644 index 0000000000..d3f98b121b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/identifiers.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/identifiers.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/literal.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/literal.worker.js new file mode 100644 index 0000000000..ef24ba83fd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/literal.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/literal.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/must_use.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/must_use.worker.js new file mode 100644 index 0000000000..888541ed1d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/must_use.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/must_use.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/pipeline_stage.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/pipeline_stage.worker.js new file mode 100644 index 0000000000..5243355f60 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/pipeline_stage.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/pipeline_stage.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/requires.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/requires.worker.js new file mode 100644 index 0000000000..dba1589829 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/requires.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/requires.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/semicolon.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/semicolon.worker.js new file mode 100644 index 0000000000..036f7b6d41 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/semicolon.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/semicolon.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/shadow_builtins.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/shadow_builtins.worker.js new file mode 100644 index 0000000000..843b1e9a99 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/shadow_builtins.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/shadow_builtins.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/source.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/source.worker.js new file mode 100644 index 0000000000..cfc5a6870c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/source.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/source.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/statement_behavior.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/statement_behavior.worker.js new file mode 100644 index 0000000000..d7ef5fa731 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/statement_behavior.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/statement_behavior.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/unary_ops.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/unary_ops.worker.js new file mode 100644 index 0000000000..b108097a39 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/unary_ops.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/unary_ops.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/var_and_let.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/var_and_let.worker.js new file mode 100644 index 0000000000..d3b5701953 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/parse/var_and_let.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/parse/var_and_let.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/binding.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/binding.worker.js new file mode 100644 index 0000000000..93747e17b9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/binding.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/binding.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/builtins.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/builtins.worker.js new file mode 100644 index 0000000000..c616848fa9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/builtins.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/builtins.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/entry_point.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/entry_point.worker.js new file mode 100644 index 0000000000..7df3a5679a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/entry_point.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/entry_point.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/group.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/group.worker.js new file mode 100644 index 0000000000..91cc5ee843 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/group.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/group.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/group_and_binding.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/group_and_binding.worker.js new file mode 100644 index 0000000000..de145c124f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/group_and_binding.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/group_and_binding.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/id.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/id.worker.js new file mode 100644 index 0000000000..94bfbb1d9e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/id.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/id.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/interpolate.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/interpolate.worker.js new file mode 100644 index 0000000000..1ef4a8537a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/interpolate.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/interpolate.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/invariant.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/invariant.worker.js new file mode 100644 index 0000000000..c443c1c766 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/invariant.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/invariant.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/layout_constraints.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/layout_constraints.worker.js new file mode 100644 index 0000000000..bd6e43ab66 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/layout_constraints.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/layout_constraints.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/locations.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/locations.worker.js new file mode 100644 index 0000000000..bcc4bf954f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/locations.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/locations.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/size.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/size.worker.js new file mode 100644 index 0000000000..639041ced4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/size.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/size.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/workgroup_size.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/workgroup_size.worker.js new file mode 100644 index 0000000000..da1c4058d5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/shader_io/workgroup_size.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/shader_io/workgroup_size.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/alias.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/alias.worker.js new file mode 100644 index 0000000000..318e1606c7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/alias.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/types/alias.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/array.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/array.worker.js new file mode 100644 index 0000000000..ba738910ee --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/array.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/types/array.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/atomics.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/atomics.worker.js new file mode 100644 index 0000000000..dbbf764275 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/atomics.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/types/atomics.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/matrix.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/matrix.worker.js new file mode 100644 index 0000000000..a3879d8e5e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/matrix.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/types/matrix.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/struct.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/struct.worker.js new file mode 100644 index 0000000000..97155cb9b0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/struct.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/types/struct.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/textures.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/textures.worker.js new file mode 100644 index 0000000000..a0198cd3f7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/textures.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/types/textures.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/vector.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/vector.worker.js new file mode 100644 index 0000000000..6d1b6ab76c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/types/vector.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/types/vector.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/uniformity/uniformity.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/uniformity/uniformity.worker.js new file mode 100644 index 0000000000..9a03cf6a33 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/shader/validation/uniformity/uniformity.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../../shader/validation/uniformity/uniformity.spec.js'; +import { wrapTestGroupForWorker } from '../../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/color_space_conversions.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/color_space_conversions.worker.js new file mode 100644 index 0000000000..92b7e45c2f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/color_space_conversions.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../util/texture/color_space_conversions.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/texel_data.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/texel_data.worker.js new file mode 100644 index 0000000000..401eed9d2d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/texel_data.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../util/texture/texel_data.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/texture_ok.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/texture_ok.worker.js new file mode 100644 index 0000000000..a12097bc55 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/util/texture/texture_ok.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../util/texture/texture_ok.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/configure.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/configure.worker.js new file mode 100644 index 0000000000..63126497f6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/configure.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/canvas/configure.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/context_creation.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/context_creation.worker.js new file mode 100644 index 0000000000..5165c5dd60 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/context_creation.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/canvas/context_creation.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/getCurrentTexture.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/getCurrentTexture.worker.js new file mode 100644 index 0000000000..776783039f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/getCurrentTexture.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/canvas/getCurrentTexture.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/getPreferredCanvasFormat.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/getPreferredCanvasFormat.worker.js new file mode 100644 index 0000000000..c412fea229 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/getPreferredCanvasFormat.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/canvas/getPreferredCanvasFormat.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/readbackFromWebGPUCanvas.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/readbackFromWebGPUCanvas.worker.js new file mode 100644 index 0000000000..f9a9f362f7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/canvas/readbackFromWebGPUCanvas.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/canvas/readbackFromWebGPUCanvas.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/ImageBitmap.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/ImageBitmap.worker.js new file mode 100644 index 0000000000..7d5f20ff00 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/ImageBitmap.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/copyToTexture/ImageBitmap.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/ImageData.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/ImageData.worker.js new file mode 100644 index 0000000000..8cc3f679e4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/ImageData.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/copyToTexture/ImageData.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/canvas.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/canvas.worker.js new file mode 100644 index 0000000000..d582697984 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/canvas.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/copyToTexture/canvas.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/image.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/image.worker.js new file mode 100644 index 0000000000..1aa1ad8c4f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/image.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/copyToTexture/image.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/video.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/video.worker.js new file mode 100644 index 0000000000..dc686d044f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/copyToTexture/video.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/copyToTexture/video.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/external_texture/video.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/external_texture/video.worker.js new file mode 100644 index 0000000000..610a887179 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/external_texture/video.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/external_texture/video.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/worker/worker.worker.js b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/worker/worker.worker.js new file mode 100644 index 0000000000..09109c2527 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/cts/webworker/web_platform/worker/worker.worker.js @@ -0,0 +1,6 @@ +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. + +import { g } from '../../../web_platform/worker/worker.spec.js'; +import { wrapTestGroupForWorker } from '../../../../common/runtime/helper/wrap_for_worker.js'; + +wrapTestGroupForWorker(g); diff --git a/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js index 138c3378a5..5a3e7f2f00 100644 --- a/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js +++ b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js @@ -390,6 +390,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -467,4 +487,11 @@ /** * Returns the nearest half-precision float representation of a number. * @param x A numeric expression. + */ + + +/** + * Returns the nearest half-precision float representation of a number. + * @alias f16round + * @param x A numeric expression. */export {}; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js index 42543cdea1..11db53a4fd 100644 --- a/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js +++ b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js @@ -1,6 +1,6 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/ /*! @petamoriken/float16 v3.6.6 | MIT License - https://github.com/petamoriken/float16 */const THIS_IS_NOT_AN_OBJECT = "This is not an object"; +**/ /*! @petamoriken/float16 v3.8.6 | MIT License - https://github.com/petamoriken/float16 */const THIS_IS_NOT_AN_OBJECT = "This is not an object"; const THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT = "This is not a Float16Array object"; const THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY = "This constructor is not a subclass of Float16Array"; @@ -19,6 +19,8 @@ const CANNOT_MIX_BIGINT_AND_OTHER_TYPES = const ITERATOR_PROPERTY_IS_NOT_CALLABLE = "@@iterator property is not callable"; const REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE = "Reduce of empty array with no initial value"; +const THE_COMPARISON_FUNCTION_MUST_BE_EITHER_A_FUNCTION_OR_UNDEFINED = +"The comparison function must be either a function or undefined"; const OFFSET_IS_OUT_OF_BOUNDS = "Offset is out of bounds"; function uncurryThis(target) { @@ -48,7 +50,8 @@ const { } = Reflect; const NativeProxy = Proxy; const { - MAX_SAFE_INTEGER: MAX_SAFE_INTEGER, + EPSILON, + MAX_SAFE_INTEGER, isFinite: NumberIsFinite, isNaN: NumberIsNaN } = Number; @@ -97,7 +100,10 @@ const ArrayPrototypeToLocaleString = uncurryThis( ); const NativeArrayPrototypeSymbolIterator = ArrayPrototype[SymbolIterator]; const ArrayPrototypeSymbolIterator = uncurryThis(NativeArrayPrototypeSymbolIterator); -const MathTrunc = Math.trunc; +const { + abs: MathAbs, + trunc: MathTrunc +} = Math; const NativeArrayBuffer = ArrayBuffer; const ArrayBufferIsView = NativeArrayBuffer.isView; const ArrayBufferPrototype = NativeArrayBuffer.prototype; @@ -146,6 +152,7 @@ const TypedArrayPrototypeGetSymbolToStringTag = uncurryThisGetter( TypedArrayPrototype, SymbolToStringTag ); +const NativeUint8Array = Uint8Array; const NativeUint16Array = Uint16Array; const Uint16ArrayFrom = (...args) => { return ReflectApply(TypedArrayFrom, NativeUint16Array, args); @@ -190,7 +197,10 @@ const SafeIteratorPrototype = ObjectCreate(null, { } }); function safeIfNeeded(array) { - if (array[SymbolIterator] === NativeArrayPrototypeSymbolIterator) { + if ( + array[SymbolIterator] === NativeArrayPrototypeSymbolIterator && + ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext) + { return array; } const safe = ObjectCreate(SafeIteratorPrototype); @@ -221,8 +231,10 @@ function wrap(generator) { } function isObject(value) { - return value !== null && typeof value === "object" || - typeof value === "function"; + return ( + value !== null && typeof value === "object" || + typeof value === "function"); + } function isObjectLike(value) { return value !== null && typeof value === "object"; @@ -232,11 +244,16 @@ function isNativeTypedArray(value) { } function isNativeBigIntTypedArray(value) { const typedArrayName = TypedArrayPrototypeGetSymbolToStringTag(value); - return typedArrayName === "BigInt64Array" || - typedArrayName === "BigUint64Array"; + return ( + typedArrayName === "BigInt64Array" || + typedArrayName === "BigUint64Array"); + } function isArrayBuffer(value) { try { + if (ArrayIsArray(value)) { + return false; + } ArrayBufferPrototypeGetByteLength(value); return true; } catch (e) { @@ -254,25 +271,26 @@ function isSharedArrayBuffer(value) { return false; } } +function isAnyArrayBuffer(value) { + return isArrayBuffer(value) || isSharedArrayBuffer(value); +} function isOrdinaryArray(value) { if (!ArrayIsArray(value)) { return false; } - if (value[SymbolIterator] === NativeArrayPrototypeSymbolIterator) { - return true; - } - const iterator = value[SymbolIterator](); - return iterator[SymbolToStringTag] === "Array Iterator"; + return ( + value[SymbolIterator] === NativeArrayPrototypeSymbolIterator && + ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext); + } function isOrdinaryNativeTypedArray(value) { if (!isNativeTypedArray(value)) { return false; } - if (value[SymbolIterator] === NativeTypedArrayPrototypeSymbolIterator) { - return true; - } - const iterator = value[SymbolIterator](); - return iterator[SymbolToStringTag] === "Array Iterator"; + return ( + value[SymbolIterator] === NativeTypedArrayPrototypeSymbolIterator && + ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext); + } function isCanonicalIntegerIndexString(value) { if (typeof value !== "string") { @@ -307,11 +325,37 @@ function hasFloat16ArrayBrand(target) { return ReflectHas(constructor, brand); } +const INVERSE_OF_EPSILON = 1 / EPSILON; +function roundTiesToEven(num) { + return num + INVERSE_OF_EPSILON - INVERSE_OF_EPSILON; +} +const FLOAT16_MIN_VALUE = 6.103515625e-05; +const FLOAT16_MAX_VALUE = 65504; +const FLOAT16_EPSILON = 0.0009765625; +const FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE = FLOAT16_EPSILON * FLOAT16_MIN_VALUE; +const FLOAT16_EPSILON_DEVIDED_BY_EPSILON = FLOAT16_EPSILON * INVERSE_OF_EPSILON; +function roundToFloat16(num) { + const number = +num; + if (!NumberIsFinite(number) || number === 0) { + return number; + } + const sign = number > 0 ? 1 : -1; + const absolute = MathAbs(number); + if (absolute < FLOAT16_MIN_VALUE) { + return sign * roundTiesToEven(absolute / FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE) * FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE; + } + const temp = (1 + FLOAT16_EPSILON_DEVIDED_BY_EPSILON) * absolute; + const result = temp - (temp - absolute); + if (result > FLOAT16_MAX_VALUE || NumberIsNaN(result)) { + return sign * Infinity; + } + return sign * result; +} const buffer = new NativeArrayBuffer(4); const floatView = new NativeFloat32Array(buffer); const uint32View = new NativeUint32Array(buffer); -const baseTable = new NativeUint32Array(512); -const shiftTable = new NativeUint32Array(512); +const baseTable = new NativeUint16Array(512); +const shiftTable = new NativeUint8Array(512); for (let i = 0; i < 256; ++i) { const e = i - 127; if (e < -27) { @@ -342,14 +386,12 @@ for (let i = 0; i < 256; ++i) { } } function roundToFloat16Bits(num) { - floatView[0] = num; + floatView[0] = roundToFloat16(num); const f = uint32View[0]; const e = f >> 23 & 0x1ff; return baseTable[e] + ((f & 0x007fffff) >> shiftTable[e]); } const mantissaTable = new NativeUint32Array(2048); -const exponentTable = new NativeUint32Array(64); -const offsetTable = new NativeUint32Array(64); for (let i = 1; i < 1024; ++i) { let m = i << 13; let e = 0; @@ -364,6 +406,7 @@ for (let i = 1; i < 1024; ++i) { for (let i = 1024; i < 2048; ++i) { mantissaTable[i] = 0x38000000 + (i - 1024 << 13); } +const exponentTable = new NativeUint32Array(64); for (let i = 1; i < 31; ++i) { exponentTable[i] = i << 23; } @@ -373,14 +416,15 @@ for (let i = 33; i < 63; ++i) { exponentTable[i] = 0x80000000 + (i - 32 << 23); } exponentTable[63] = 0xc7800000; +const offsetTable = new NativeUint16Array(64); for (let i = 1; i < 64; ++i) { if (i !== 32) { offsetTable[i] = 1024; } } function convertToNumber(float16bits) { - const m = float16bits >> 10; - uint32View[0] = mantissaTable[offsetTable[m] + (float16bits & 0x3ff)] + exponentTable[m]; + const i = float16bits >> 10; + uint32View[0] = mantissaTable[offsetTable[i] + (float16bits & 0x3ff)] + exponentTable[i]; return floatView[0]; } @@ -572,26 +616,20 @@ class Float16Array { let float16bitsArray; if (isFloat16Array(input)) { float16bitsArray = ReflectConstruct(NativeUint16Array, [getFloat16BitsArray(input)], new.target); - } else if (isObject(input) && !isArrayBuffer(input)) { + } else if (isObject(input) && !isAnyArrayBuffer(input)) { let list; let length; if (isNativeTypedArray(input)) { list = input; length = TypedArrayPrototypeGetLength(input); const buffer = TypedArrayPrototypeGetBuffer(input); - const BufferConstructor = !isSharedArrayBuffer(buffer) ? - SpeciesConstructor( - buffer, - NativeArrayBuffer - ) : - NativeArrayBuffer; if (IsDetachedBuffer(buffer)) { throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER); } if (isNativeBigIntTypedArray(input)) { throw NativeTypeError(CANNOT_MIX_BIGINT_AND_OTHER_TYPES); } - const data = new BufferConstructor( + const data = new NativeArrayBuffer( length * BYTES_PER_ELEMENT ); float16bitsArray = ReflectConstruct(NativeUint16Array, [data], new.target); @@ -758,6 +796,30 @@ class Float16Array { } return convertToNumber(float16bitsArray[k]); } + with(index, value) { + assertFloat16Array(this); + const float16bitsArray = getFloat16BitsArray(this); + const length = TypedArrayPrototypeGetLength(float16bitsArray); + const relativeIndex = ToIntegerOrInfinity(index); + const k = relativeIndex >= 0 ? relativeIndex : length + relativeIndex; + const number = +value; + if (k < 0 || k >= length) { + throw NativeRangeError(OFFSET_IS_OUT_OF_BOUNDS); + } + const uint16 = new NativeUint16Array( + TypedArrayPrototypeGetBuffer(float16bitsArray), + TypedArrayPrototypeGetByteOffset(float16bitsArray), + TypedArrayPrototypeGetLength(float16bitsArray) + ); + const cloned = new Float16Array( + TypedArrayPrototypeGetBuffer( + TypedArrayPrototypeSlice(uint16) + ) + ); + const array = getFloat16BitsArray(cloned); + array[k] = roundToFloat16Bits(number); + return cloned; + } map(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); @@ -995,6 +1057,23 @@ class Float16Array { TypedArrayPrototypeReverse(float16bitsArray); return this; } + toReversed() { + assertFloat16Array(this); + const float16bitsArray = getFloat16BitsArray(this); + const uint16 = new NativeUint16Array( + TypedArrayPrototypeGetBuffer(float16bitsArray), + TypedArrayPrototypeGetByteOffset(float16bitsArray), + TypedArrayPrototypeGetLength(float16bitsArray) + ); + const cloned = new Float16Array( + TypedArrayPrototypeGetBuffer( + TypedArrayPrototypeSlice(uint16) + ) + ); + const clonedFloat16bitsArray = getFloat16BitsArray(cloned); + TypedArrayPrototypeReverse(clonedFloat16bitsArray); + return cloned; + } fill(value, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); @@ -1020,6 +1099,29 @@ class Float16Array { }); return this; } + toSorted(compareFn) { + assertFloat16Array(this); + const float16bitsArray = getFloat16BitsArray(this); + if (compareFn !== undefined && typeof compareFn !== "function") { + throw new NativeTypeError(THE_COMPARISON_FUNCTION_MUST_BE_EITHER_A_FUNCTION_OR_UNDEFINED); + } + const sortCompare = compareFn !== undefined ? compareFn : defaultCompare; + const uint16 = new NativeUint16Array( + TypedArrayPrototypeGetBuffer(float16bitsArray), + TypedArrayPrototypeGetByteOffset(float16bitsArray), + TypedArrayPrototypeGetLength(float16bitsArray) + ); + const cloned = new Float16Array( + TypedArrayPrototypeGetBuffer( + TypedArrayPrototypeSlice(uint16) + ) + ); + const clonedFloat16bitsArray = getFloat16BitsArray(cloned); + TypedArrayPrototypeSort(clonedFloat16bitsArray, (x, y) => { + return sortCompare(convertToNumber(x), convertToNumber(y)); + }); + return cloned; + } slice(start, end) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); @@ -1216,13 +1318,8 @@ function setFloat16(dataView, byteOffset, value, ...opts) { ); } -function hfround(x) { - const number = +x; - if (!NumberIsFinite(number) || number === 0) { - return number; - } - const x16 = roundToFloat16Bits(number); - return convertToNumber(x16); +function f16round(x) { + return roundToFloat16(x); } -export { Float16Array, getFloat16, hfround, isFloat16Array, isTypedArray, setFloat16 }; \ No newline at end of file +export { Float16Array, f16round, getFloat16, f16round as hfround, isFloat16Array, isTypedArray, setFloat16 }; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/README.md b/testing/web-platform/mozilla/tests/webgpu/resources/README.md index 28f23f288b..a1ed060417 100644 --- a/testing/web-platform/mozilla/tests/webgpu/resources/README.md +++ b/testing/web-platform/mozilla/tests/webgpu/resources/README.md @@ -2,13 +2,92 @@ Always use `getResourcePath()` to get the appropriate path to these resources de on the context (WPT, standalone, worker, etc.) -The test video files were generated with the ffmpeg cmds below: -ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx -pix_fmt yuv420p -frames 500 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv four-colors-vp8-bt601.webm -ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libx264 -pix_fmt yuv420p -frames 500 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv four-colors-h264-bt601.mp4 -ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 500 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv four-colors-vp9-bt601.webm -ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 500 -colorspace bt709 -color_primaries bt709 -color_trc bt709 -color_range tv -vf scale=out_color_matrix=bt709:out_range=tv four-colors-vp9-bt709.webm - -These rotation test files are copies of four-colors-h264-bt601.mp4 with metadata changes. -ffmpeg.exe -i .\four-colors-h264-bt601.mp4 -c copy -metadata:s:v rotate=90 four-colors-h264-bt601-rotate-90.mp4 -ffmpeg.exe -i .\four-colors-h264-bt601.mp4 -c copy -metadata:s:v rotate=180 four-colors-h264-bt601-rotate-180.mp4 -ffmpeg.exe -i .\four-colors-h264-bt601.mp4 -c copy -metadata:s:v rotate=270 four-colors-h264-bt601-rotate-270.mp4 +The test video files were generated with by ffmpeg cmds below: +``` +// Generate four-colors-vp8-bt601.webm, mimeType: 'video/webm; codecs=vp8' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv four-colors-vp8-bt601.webm + +// Generate four-colors-h264-bt601.mp4, mimeType: 'video/mp4; codecs=avc1.4d400c' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libx264 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv four-colors-h264-bt601.mp4 + +// Generate four-colors-vp9-bt601.webm, mimeType: 'video/webm; codecs=vp9' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv four-colors-vp9-bt601.webm + +// Generate four-colors-vp9-bt709.webm, mimeType: 'video/webm; codecs=vp9' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace bt709 -color_primaries bt709 -color_trc bt709 -color_range tv -vf scale=out_color_matrix=bt709:out_range=tv four-colors-vp9-bt709.webm + +// Generate four-colors-vp9-bt601.mp4, mimeType: 'video/mp4; codecs=vp9' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv four-colors-vp9-bt601.mp4 +``` + +Generate video files to test rotation behaviour. +Use ffmepg to rotate video content x degrees in cw direction (by using `transpose`) and update transform matrix in metadata through `display_rotation` to x degrees to apply ccw direction rotation. + +H264 rotated video files are generated by ffmpeg cmds below: +``` +// Generate four-colors-h264-bt601-rotate-90.mp4, mimeType: 'video/mp4; codecs=avc1.4d400c' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libx264 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv -vf transpose=2 temp.mp4 +ffmpeg -display_rotation 270 -i temp.mp4 -c copy four-colors-h264-bt601-rotate-90.mp4 +rm temp.mp4 + +// Generate four-colors-h264-bt601-rotate-180.mp4, mimeType: 'video/mp4; codecs=avc1.4d400c' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libx264 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv -vf transpose=2,transpose=2 temp.mp4 +ffmpeg -display_rotation 180 -i temp.mp4 -c copy four-colors-h264-bt601-rotate-180.mp4 +rm temp.mp4 + +// Generate four-colors-h264-bt601-rotate-270.mp4, mimeType: 'video/mp4; codecs=avc1.4d400c' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libx264 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv -vf transpose=1 temp.mp4 +ffmpeg -display_rotation 90 -i temp.mp4 -c copy four-colors-h264-bt601-rotate-270.mp4 +rm temp.mp4 + +``` + +Vp9 rotated video files are generated by ffmpeg cmds below: +``` +// Generate four-colors-vp9-bt601-rotate-90.mp4, mimeType: 'video/mp4; codecs=vp9' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv -vf transpose=2 temp.mp4 +ffmpeg -display_rotation 270 -i temp.mp4 -c copy four-colors-vp9-bt601-rotate-90.mp4 +rm temp.mp4 + +// Generate four-colors-vp9-bt601-rotate-180.mp4, mimeType: 'video/mp4; codecs=vp9' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv -vf transpose=2,transpose=2 temp.mp4 +ffmpeg -display_rotation 180 -i temp.mp4 -c copy four-colors-vp9-bt601-rotate-180.mp4 +rm temp.mp4 + +// Generate four-colors-vp9-bt601-rotate-270.mp4, mimeType: 'video/mp4; codecs=vp9' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv -vf transpose=1 temp.mp4 +ffmpeg -display_rotation 90 -i temp.mp4 -c copy four-colors-vp9-bt601-rotate-270.mp4 +rm temp.mp4 + +``` + +Generate video files to test flip behaviour. +Use ffmpeg to flip video content. Using `display_hflip` to do horizontal flip and `display_vflip` to do vertical flip. + +H264 flip video files are generated by ffmpeg cmds below: +``` +// Generate four-colors-h264-bt601-hflip.mp4, mimeType: 'video/mp4; codecs=avc1.4d400c' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libx264 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv temp.mp4 +ffmpeg -display_hflip -i temp.mp4 -c copy four-colors-h264-bt601-hflip.mp4 +rm temp.mp4 + +// Generate four-colors-h264-bt601-vflip.mp4, mimeType: 'video/mp4; codecs=avc1.4d400c' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libx264 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv temp.mp4 +ffmpeg -display_vflip -i temp.mp4 -c copy four-colors-h264-bt601-vflip.mp4 +rm temp.mp4 + +``` + +Vp9 flip video files are generated by ffmpeg cmds below: +``` +// Generate four-colors-vp9-bt601-hflip.mp4, mimeType: 'video/mp4; codecs=vp09.00.10.08' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv temp.mp4 +ffmpeg -display_hflip -i temp.mp4 -c copy four-colors-vp9-bt601-hflip.mp4 +rm temp.mp4 + +// Generate four-colors-vp9-bt601-vflip.mp4, mimeType: 'video/mp4; codecs=vp09.00.10.08' +ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv temp.mp4 +ffmpeg -display_vflip -i temp.mp4 -c copy four-colors-vp9-bt601-vflip.mp4 +rm temp.mp4 + +``` diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/hashes.json b/testing/web-platform/mozilla/tests/webgpu/resources/cache/hashes.json new file mode 100644 index 0000000000..90efb474ad --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/resources/cache/hashes.json @@ -0,0 +1,111 @@ +{ + "webgpu/shader/execution/binary/af_addition.bin": "17c26b18", + "webgpu/shader/execution/binary/af_logical.bin": "b4fdda88", + "webgpu/shader/execution/binary/af_division.bin": "fa1fc451", + "webgpu/shader/execution/binary/af_matrix_addition.bin": "a2bebfc0", + "webgpu/shader/execution/binary/af_matrix_subtraction.bin": "5456944c", + "webgpu/shader/execution/binary/af_multiplication.bin": "fc54cae0", + "webgpu/shader/execution/binary/af_remainder.bin": "2ee1a014", + "webgpu/shader/execution/binary/af_subtraction.bin": "ba82dab3", + "webgpu/shader/execution/binary/f16_addition.bin": "4ccf0cde", + "webgpu/shader/execution/binary/f16_logical.bin": "5ffb4769", + "webgpu/shader/execution/binary/f16_division.bin": "c69d5326", + "webgpu/shader/execution/binary/f16_matrix_addition.bin": "23006f90", + "webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin": "3b581360", + "webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin": "4c2cf2fa", + "webgpu/shader/execution/binary/f16_matrix_subtraction.bin": "902ffcbc", + "webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin": "48acf022", + "webgpu/shader/execution/binary/f16_multiplication.bin": "e83fedc6", + "webgpu/shader/execution/binary/f16_remainder.bin": "68178090", + "webgpu/shader/execution/binary/f16_subtraction.bin": "de63294a", + "webgpu/shader/execution/binary/f32_addition.bin": "d693585", + "webgpu/shader/execution/binary/f32_logical.bin": "57b9e9da", + "webgpu/shader/execution/binary/f32_division.bin": "79048538", + "webgpu/shader/execution/binary/f32_matrix_addition.bin": "301c58ba", + "webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin": "41bae804", + "webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin": "d8a1003a", + "webgpu/shader/execution/binary/f32_matrix_subtraction.bin": "3b1cc190", + "webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin": "66a57dbc", + "webgpu/shader/execution/binary/f32_multiplication.bin": "c0bf07da", + "webgpu/shader/execution/binary/f32_remainder.bin": "238fd8eb", + "webgpu/shader/execution/binary/f32_subtraction.bin": "d977904f", + "webgpu/shader/execution/binary/i32_arithmetic.bin": "8168bdb4", + "webgpu/shader/execution/binary/i32_comparison.bin": "eae9d767", + "webgpu/shader/execution/binary/u32_arithmetic.bin": "5c313ea9", + "webgpu/shader/execution/binary/u32_comparison.bin": "5ef80f48", + "webgpu/shader/execution/abs.bin": "1a23882d", + "webgpu/shader/execution/acos.bin": "66020d3b", + "webgpu/shader/execution/acosh.bin": "eeed5b15", + "webgpu/shader/execution/asin.bin": "e38b87bf", + "webgpu/shader/execution/asinh.bin": "d5cf509e", + "webgpu/shader/execution/atan.bin": "780f5bf9", + "webgpu/shader/execution/atan2.bin": "242c3f80", + "webgpu/shader/execution/atanh.bin": "2c6771e5", + "webgpu/shader/execution/bitcast.bin": "4ebd46da", + "webgpu/shader/execution/ceil.bin": "b190ce63", + "webgpu/shader/execution/clamp.bin": "9ba5f3c9", + "webgpu/shader/execution/cos.bin": "edeb923", + "webgpu/shader/execution/cosh.bin": "c12c748b", + "webgpu/shader/execution/cross.bin": "4cfaddf8", + "webgpu/shader/execution/degrees.bin": "dc77e03b", + "webgpu/shader/execution/determinant.bin": "a87e4d61", + "webgpu/shader/execution/distance.bin": "9e397f5a", + "webgpu/shader/execution/dot.bin": "db692304", + "webgpu/shader/execution/exp.bin": "b0cbd306", + "webgpu/shader/execution/exp2.bin": "b32745cd", + "webgpu/shader/execution/faceForward.bin": "f0cc892a", + "webgpu/shader/execution/floor.bin": "4a460013", + "webgpu/shader/execution/fma.bin": "c89c3d19", + "webgpu/shader/execution/fract.bin": "f6230a96", + "webgpu/shader/execution/frexp.bin": "132962c", + "webgpu/shader/execution/inverseSqrt.bin": "cc1b943c", + "webgpu/shader/execution/ldexp.bin": "4e14b67d", + "webgpu/shader/execution/length.bin": "a75b23ef", + "webgpu/shader/execution/log.bin": "61175a12", + "webgpu/shader/execution/log2.bin": "d24b375d", + "webgpu/shader/execution/max.bin": "5689d61b", + "webgpu/shader/execution/min.bin": "8fd8d393", + "webgpu/shader/execution/mix.bin": "caf44b85", + "webgpu/shader/execution/modf.bin": "223ff03f", + "webgpu/shader/execution/normalize.bin": "e0634ba", + "webgpu/shader/execution/pack2x16float.bin": "a8ca6b51", + "webgpu/shader/execution/pow.bin": "b2bbd5ce", + "webgpu/shader/execution/quantizeToF16.bin": "be9ef6ab", + "webgpu/shader/execution/radians.bin": "afaf4f61", + "webgpu/shader/execution/reflect.bin": "742b05b4", + "webgpu/shader/execution/refract.bin": "ad05949f", + "webgpu/shader/execution/round.bin": "3a006c0c", + "webgpu/shader/execution/saturate.bin": "61753b4f", + "webgpu/shader/execution/sign.bin": "71e6517c", + "webgpu/shader/execution/sin.bin": "17c44cc8", + "webgpu/shader/execution/sinh.bin": "151ae2d1", + "webgpu/shader/execution/smoothstep.bin": "35db8f9a", + "webgpu/shader/execution/sqrt.bin": "a4b4bdf9", + "webgpu/shader/execution/step.bin": "e3cc0f86", + "webgpu/shader/execution/tan.bin": "9ad0e1f1", + "webgpu/shader/execution/tanh.bin": "99454fdd", + "webgpu/shader/execution/transpose.bin": "959a2407", + "webgpu/shader/execution/trunc.bin": "1a47263e", + "webgpu/shader/execution/unpack2x16float.bin": "39f959fe", + "webgpu/shader/execution/unpack2x16snorm.bin": "b409d047", + "webgpu/shader/execution/unpack2x16unorm.bin": "49a89145", + "webgpu/shader/execution/unpack4x8snorm.bin": "e53a7842", + "webgpu/shader/execution/unpack4x8unorm.bin": "9bc3f0ea", + "webgpu/shader/execution/unary/af_arithmetic.bin": "e9e06bc7", + "webgpu/shader/execution/unary/af_assignment.bin": "5c9160c2", + "webgpu/shader/execution/unary/bool_conversion.bin": "a2260d3a", + "webgpu/shader/execution/unary/f16_arithmetic.bin": "7a3fd3db", + "webgpu/shader/execution/unary/f16_conversion.bin": "b9407945", + "webgpu/shader/execution/unary/f32_arithmetic.bin": "6e392701", + "webgpu/shader/execution/unary/f32_conversion.bin": "6ae4cce9", + "webgpu/shader/execution/unary/i32_arithmetic.bin": "f5ef6485", + "webgpu/shader/execution/unary/i32_conversion.bin": "75435733", + "webgpu/shader/execution/unary/u32_conversion.bin": "26baf99", + "webgpu/shader/execution/unary/ai_assignment.bin": "d1b00a8", + "webgpu/shader/execution/binary/ai_arithmetic.bin": "dc777f4e", + "webgpu/shader/execution/unary/ai_arithmetic.bin": "272c5df2", + "webgpu/shader/execution/binary/af_matrix_matrix_multiplication.bin": "ab6db19f", + "webgpu/shader/execution/binary/af_matrix_scalar_multiplication.bin": "1de2ec75", + "webgpu/shader/execution/binary/af_matrix_vector_multiplication.bin": "e665650a", + "webgpu/shader/execution/derivatives.bin": "899e4e4c" +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/abs.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/abs.bin new file mode 100644 index 0000000000..4cba9b72df Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/abs.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/acos.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/acos.bin new file mode 100644 index 0000000000..2ecaaa389a Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/acos.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/acosh.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/acosh.bin new file mode 100644 index 0000000000..d48659f3c3 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/acosh.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/asin.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/asin.bin new file mode 100644 index 0000000000..b199953eaf Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/asin.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/asinh.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/asinh.bin new file mode 100644 index 0000000000..b370c53b01 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/asinh.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atan.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atan.bin new file mode 100644 index 0000000000..6ab0ba106a Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atan.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atan2.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atan2.bin new file mode 100644 index 0000000000..0109ddbc37 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atan2.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atanh.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atanh.bin new file mode 100644 index 0000000000..e6a190b35d Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/atanh.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_addition.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_addition.bin new file mode 100644 index 0000000000..ebd757c1b6 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_addition.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_division.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_division.bin new file mode 100644 index 0000000000..656356d32e Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_division.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_logical.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_logical.bin new file mode 100644 index 0000000000..e3594458f2 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_logical.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_addition.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_addition.bin new file mode 100644 index 0000000000..ba9d123cbf Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_addition.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_matrix_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_matrix_multiplication.bin new file mode 100644 index 0000000000..58d0d40cb9 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_matrix_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_scalar_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_scalar_multiplication.bin new file mode 100644 index 0000000000..c8a3b7205a Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_scalar_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_subtraction.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_subtraction.bin new file mode 100644 index 0000000000..8f88d196ce Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_subtraction.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_vector_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_vector_multiplication.bin new file mode 100644 index 0000000000..545a5112cf Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_matrix_vector_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_multiplication.bin new file mode 100644 index 0000000000..552d8b4892 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_remainder.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_remainder.bin new file mode 100644 index 0000000000..c45792abf4 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_remainder.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_subtraction.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_subtraction.bin new file mode 100644 index 0000000000..6f0be29785 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/af_subtraction.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/ai_arithmetic.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/ai_arithmetic.bin new file mode 100644 index 0000000000..658eb46d39 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/ai_arithmetic.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_addition.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_addition.bin new file mode 100644 index 0000000000..30f099139d Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_addition.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_division.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_division.bin new file mode 100644 index 0000000000..22e60bef81 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_division.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_logical.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_logical.bin new file mode 100644 index 0000000000..932af58208 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_logical.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_addition.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_addition.bin new file mode 100644 index 0000000000..452376760b Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_addition.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin new file mode 100644 index 0000000000..e823daac6c Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin new file mode 100644 index 0000000000..b48be81ebd Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_subtraction.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_subtraction.bin new file mode 100644 index 0000000000..386558c3f7 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_subtraction.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin new file mode 100644 index 0000000000..cbf224a6b6 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_multiplication.bin new file mode 100644 index 0000000000..e9d27019a3 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_remainder.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_remainder.bin new file mode 100644 index 0000000000..d21370aec9 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_remainder.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_subtraction.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_subtraction.bin new file mode 100644 index 0000000000..97080a8ce5 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f16_subtraction.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_addition.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_addition.bin new file mode 100644 index 0000000000..be7b997bd8 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_addition.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_division.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_division.bin new file mode 100644 index 0000000000..f80461c21b Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_division.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_logical.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_logical.bin new file mode 100644 index 0000000000..a819eab08c Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_logical.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_addition.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_addition.bin new file mode 100644 index 0000000000..b1d7179264 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_addition.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin new file mode 100644 index 0000000000..232760828a Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin new file mode 100644 index 0000000000..76f867b959 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_subtraction.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_subtraction.bin new file mode 100644 index 0000000000..0d0fd2460d Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_subtraction.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin new file mode 100644 index 0000000000..e139fc9713 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_multiplication.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_multiplication.bin new file mode 100644 index 0000000000..1837ce922c Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_multiplication.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_remainder.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_remainder.bin new file mode 100644 index 0000000000..3febfca1d1 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_remainder.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_subtraction.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_subtraction.bin new file mode 100644 index 0000000000..32b34f690c Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/f32_subtraction.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/i32_arithmetic.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/i32_arithmetic.bin new file mode 100644 index 0000000000..bacd4c0c54 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/i32_arithmetic.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/i32_comparison.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/i32_comparison.bin new file mode 100644 index 0000000000..d5a745e85c Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/i32_comparison.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/u32_arithmetic.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/u32_arithmetic.bin new file mode 100644 index 0000000000..56ef292864 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/u32_arithmetic.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/u32_comparison.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/u32_comparison.bin new file mode 100644 index 0000000000..5ba639b3cd Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/binary/u32_comparison.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/bitcast.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/bitcast.bin new file mode 100644 index 0000000000..2acc4a318b Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/bitcast.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/ceil.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/ceil.bin new file mode 100644 index 0000000000..9b93ed416f Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/ceil.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/clamp.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/clamp.bin new file mode 100644 index 0000000000..492be017aa Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/clamp.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cos.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cos.bin new file mode 100644 index 0000000000..4e34eff3f1 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cos.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cosh.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cosh.bin new file mode 100644 index 0000000000..5b30d2786c Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cosh.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cross.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cross.bin new file mode 100644 index 0000000000..c8ee9d3e1a Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/cross.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/degrees.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/degrees.bin new file mode 100644 index 0000000000..662558d78a Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/degrees.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/derivatives.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/derivatives.bin new file mode 100644 index 0000000000..d6d0788775 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/derivatives.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/determinant.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/determinant.bin new file mode 100644 index 0000000000..16d58c6db6 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/determinant.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/distance.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/distance.bin new file mode 100644 index 0000000000..23a4756a69 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/distance.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/dot.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/dot.bin new file mode 100644 index 0000000000..13622a686b Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/dot.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/exp.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/exp.bin new file mode 100644 index 0000000000..29361a2b27 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/exp.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/exp2.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/exp2.bin new file mode 100644 index 0000000000..367b5a8e90 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/exp2.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/faceForward.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/faceForward.bin new file mode 100644 index 0000000000..8f065bb97c Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/faceForward.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/floor.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/floor.bin new file mode 100644 index 0000000000..b5341907f8 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/floor.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/fma.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/fma.bin new file mode 100644 index 0000000000..eb4cb9ebbe Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/fma.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/fract.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/fract.bin new file mode 100644 index 0000000000..f889961d8f Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/fract.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/frexp.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/frexp.bin new file mode 100644 index 0000000000..6811dfa295 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/frexp.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/inverseSqrt.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/inverseSqrt.bin new file mode 100644 index 0000000000..5039345ad0 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/inverseSqrt.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/ldexp.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/ldexp.bin new file mode 100644 index 0000000000..bab78ed2af Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/ldexp.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/length.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/length.bin new file mode 100644 index 0000000000..3644d9b683 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/length.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/log.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/log.bin new file mode 100644 index 0000000000..ba591faad8 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/log.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/log2.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/log2.bin new file mode 100644 index 0000000000..00641ce119 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/log2.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/max.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/max.bin new file mode 100644 index 0000000000..3861a94aca Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/max.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/min.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/min.bin new file mode 100644 index 0000000000..21c29e62ed Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/min.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/mix.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/mix.bin new file mode 100644 index 0000000000..c42b2aa067 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/mix.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/modf.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/modf.bin new file mode 100644 index 0000000000..363cc161fd Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/modf.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/normalize.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/normalize.bin new file mode 100644 index 0000000000..01b8eab700 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/normalize.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/pack2x16float.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/pack2x16float.bin new file mode 100644 index 0000000000..e95227d36e Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/pack2x16float.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/pow.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/pow.bin new file mode 100644 index 0000000000..4f5faf3293 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/pow.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/quantizeToF16.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/quantizeToF16.bin new file mode 100644 index 0000000000..9e4308d5cd Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/quantizeToF16.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/radians.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/radians.bin new file mode 100644 index 0000000000..f5285d1087 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/radians.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/reflect.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/reflect.bin new file mode 100644 index 0000000000..30cd7ee925 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/reflect.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/refract.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/refract.bin new file mode 100644 index 0000000000..c428285817 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/refract.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/round.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/round.bin new file mode 100644 index 0000000000..c3b30b68f0 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/round.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/saturate.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/saturate.bin new file mode 100644 index 0000000000..2e1eb821a9 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/saturate.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sign.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sign.bin new file mode 100644 index 0000000000..033f2e8158 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sign.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sin.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sin.bin new file mode 100644 index 0000000000..a2ca632008 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sin.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sinh.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sinh.bin new file mode 100644 index 0000000000..1176cd472b Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sinh.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/smoothstep.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/smoothstep.bin new file mode 100644 index 0000000000..73b65d17c2 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/smoothstep.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sqrt.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sqrt.bin new file mode 100644 index 0000000000..6dd8088c08 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/sqrt.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/step.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/step.bin new file mode 100644 index 0000000000..f6c6c7b5f3 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/step.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/tan.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/tan.bin new file mode 100644 index 0000000000..572bee4df2 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/tan.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/tanh.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/tanh.bin new file mode 100644 index 0000000000..a13028b165 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/tanh.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/transpose.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/transpose.bin new file mode 100644 index 0000000000..d1b6bf04ee Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/transpose.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/trunc.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/trunc.bin new file mode 100644 index 0000000000..ba81e2ada4 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/trunc.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/af_arithmetic.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/af_arithmetic.bin new file mode 100644 index 0000000000..21d3d702ae Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/af_arithmetic.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/af_assignment.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/af_assignment.bin new file mode 100644 index 0000000000..a92279b5ce Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/af_assignment.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/ai_arithmetic.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/ai_arithmetic.bin new file mode 100644 index 0000000000..2fa273ff19 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/ai_arithmetic.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/ai_assignment.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/ai_assignment.bin new file mode 100644 index 0000000000..7956b3652a Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/ai_assignment.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/bool_conversion.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/bool_conversion.bin new file mode 100644 index 0000000000..98a90ea45b Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/bool_conversion.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f16_arithmetic.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f16_arithmetic.bin new file mode 100644 index 0000000000..acf8a702ce Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f16_arithmetic.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f16_conversion.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f16_conversion.bin new file mode 100644 index 0000000000..14299da766 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f16_conversion.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f32_arithmetic.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f32_arithmetic.bin new file mode 100644 index 0000000000..ebc60029fa Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f32_arithmetic.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f32_conversion.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f32_conversion.bin new file mode 100644 index 0000000000..bdcc0c7298 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/f32_conversion.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/i32_arithmetic.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/i32_arithmetic.bin new file mode 100644 index 0000000000..4753b020c9 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/i32_arithmetic.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/i32_conversion.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/i32_conversion.bin new file mode 100644 index 0000000000..04841df607 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/i32_conversion.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/u32_conversion.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/u32_conversion.bin new file mode 100644 index 0000000000..277ffc4d76 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unary/u32_conversion.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16float.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16float.bin new file mode 100644 index 0000000000..7f06cb0df6 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16float.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16snorm.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16snorm.bin new file mode 100644 index 0000000000..08c6af9e93 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16snorm.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16unorm.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16unorm.bin new file mode 100644 index 0000000000..1bb97b9c55 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack2x16unorm.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack4x8snorm.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack4x8snorm.bin new file mode 100644 index 0000000000..1db9856b05 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack4x8snorm.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack4x8unorm.bin b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack4x8unorm.bin new file mode 100644 index 0000000000..8d1f3dc7fb Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/cache/webgpu/shader/execution/unpack4x8unorm.bin differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-hflip.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-hflip.mp4 new file mode 100644 index 0000000000..f83b4f9698 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-hflip.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-180.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-180.mp4 index 1f0e9094a5..6665ea900d 100644 Binary files a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-180.mp4 and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-180.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-270.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-270.mp4 index e0480ceff2..b1e32bc83a 100644 Binary files a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-270.mp4 and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-270.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-90.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-90.mp4 index 9a6261056e..66a98d0ed0 100644 Binary files a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-90.mp4 and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-rotate-90.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-vflip.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-vflip.mp4 new file mode 100644 index 0000000000..90c3297a9a Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601-vflip.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601.mp4 index 81a5ade435..5317bbf7c6 100644 Binary files a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601.mp4 and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-h264-bt601.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp8-bt601.webm b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp8-bt601.webm index 20a2178596..d1504ee332 100644 Binary files a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp8-bt601.webm and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp8-bt601.webm differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-hflip.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-hflip.mp4 new file mode 100644 index 0000000000..f782c32651 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-hflip.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-180.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-180.mp4 new file mode 100644 index 0000000000..fc712becd7 Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-180.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-270.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-270.mp4 new file mode 100644 index 0000000000..a83558f53c Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-270.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-90.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-90.mp4 new file mode 100644 index 0000000000..73a03795ba Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-rotate-90.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-vflip.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-vflip.mp4 new file mode 100644 index 0000000000..c9de14696a Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601-vflip.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601.mp4 new file mode 100644 index 0000000000..0d8d4f829c Binary files /dev/null and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601.mp4 differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601.webm b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601.webm index a4044a9209..47a43a0695 100644 Binary files a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601.webm and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt601.webm differ diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt709.webm b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt709.webm index 189e422035..a9e069ee1c 100644 Binary files a/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt709.webm and b/testing/web-platform/mozilla/tests/webgpu/resources/four-colors-vp9-bt709.webm differ diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestDevice.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestDevice.spec.js index e01474f3f7..3d69c132c5 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestDevice.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestDevice.spec.js @@ -311,6 +311,65 @@ fn(async (t) => { t.shouldReject('OperationError', adapter.requestDevice({ requiredLimits })); }); +g.test('limit,out_of_range'). +desc( + ` + Test that specifying limits that are out of range (<0, >MAX_SAFE_INTEGER, >2**31-2 for 32-bit + limits, =0 for alignment limits) produce the appropriate error (TypeError or OperationError). + ` +). +params((u) => +u. +combine('limit', kLimits). +beginSubcases(). +expand('value', function* () { + yield -(2 ** 64); + yield Number.MIN_SAFE_INTEGER - 3; + yield Number.MIN_SAFE_INTEGER - 1; + yield Number.MIN_SAFE_INTEGER; + yield -(2 ** 32); + yield -1; + yield 0; + yield 2 ** 32 - 2; + yield 2 ** 32 - 1; + yield 2 ** 32; + yield 2 ** 32 + 1; + yield 2 ** 32 + 2; + yield Number.MAX_SAFE_INTEGER; + yield Number.MAX_SAFE_INTEGER + 1; + yield Number.MAX_SAFE_INTEGER + 3; + yield 2 ** 64; + yield Number.MAX_VALUE; +}) +). +fn(async (t) => { + const { limit, value } = t.params; + + const gpu = getGPU(t.rec); + const adapter = await gpu.requestAdapter(); + assert(adapter !== null); + const limitInfo = getDefaultLimitsForAdapter(adapter)[limit]; + + const requiredLimits = { + [limit]: value + }; + + const errorName = + value < 0 || value > Number.MAX_SAFE_INTEGER ? + 'TypeError' : + limitInfo.class === 'maximum' && value > adapter.limits[limit] ? + 'OperationError' : + limitInfo.class === 'alignment' && (value > 2 ** 31 || !isPowerOfTwo(value)) ? + 'OperationError' : + false; + + if (errorName) { + t.shouldReject(errorName, adapter.requestDevice({ requiredLimits })); + } else { + await adapter.requestDevice({ requiredLimits }); + } +}); + g.test('limit,worse_than_default'). desc( ` diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.js index bc42d07326..17b9b2b6e6 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.js @@ -1,7 +1,7 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = `copyTextureToTexture operation tests`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; -import { assert, memcpy, unreachable } from '../../../../common/util/util.js'; +import { assert, ErrorWithExtra, memcpy } from '../../../../common/util/util.js'; import { kBufferSizeAlignment, kMinDynamicBufferOffsetAlignment, @@ -17,15 +17,19 @@ import { isCompressedTextureFormat, - viewCompatible } from + viewCompatible, + + isRegularTextureFormat } from '../../../format_info.js'; import { GPUTest, TextureTestMixin } from '../../../gpu_test.js'; import { makeBufferWithContents } from '../../../util/buffer.js'; -import { checkElementsEqual, checkElementsEqualEither } from '../../../util/check_contents.js'; +import { checkElementsEqual } from '../../../util/check_contents.js'; import { align } from '../../../util/math.js'; import { physicalMipSize } from '../../../util/texture/base.js'; import { DataArrayGenerator } from '../../../util/texture/data_generation.js'; import { kBytesPerRowAlignment, dataBytesForCopyOrFail } from '../../../util/texture/layout.js'; +import { TexelView } from '../../../util/texture/texel_view.js'; +import { findFailedPixels } from '../../../util/texture/texture_ok.js'; const dataGenerator = new DataArrayGenerator(); @@ -207,7 +211,7 @@ class F extends TextureTestMixin(GPUTest) { align(dstBlocksPerRow * bytesPerBlock, 4); if (isCompressedTextureFormat(dstTexture.format) && this.isCompatibility) { - assert(viewCompatible(srcFormat, dstFormat)); + assert(viewCompatible(this.isCompatibility, srcFormat, dstFormat)); // compare by rendering. We need the expected texture to match // the dstTexture so we'll create a texture where we supply // all of the data in JavaScript. @@ -304,6 +308,7 @@ class F extends TextureTestMixin(GPUTest) { y: appliedDstOffset.y / blockHeight, z: appliedDstOffset.z }; + const bytesInRow = appliedCopyBlocksPerRow * bytesPerBlock; for (let z = 0; z < appliedCopyDepth; ++z) { const srcOffsetZ = srcCopyOffsetInBlocks.z + z; @@ -321,7 +326,6 @@ class F extends TextureTestMixin(GPUTest) { srcBlockRowsPerImage * srcOffsetZ + srcOffsetYInBlocks) + srcCopyOffsetInBlocks.x * bytesPerBlock; - const bytesInRow = appliedCopyBlocksPerRow * bytesPerBlock; memcpy( { src: expectedUint8Data, start: expectedDataOffset, length: bytesInRow }, { dst: expectedUint8DataWithPadding, start: expectedDataWithPaddingOffset } @@ -329,46 +333,69 @@ class F extends TextureTestMixin(GPUTest) { } } - let alternateExpectedData = expectedUint8DataWithPadding; - // For 8-byte snorm formats, allow an alternative encoding of -1. - // MAINTENANCE_TODO: Use textureContentIsOKByT2B with TexelView. - if (srcFormat.includes('snorm')) { - switch (srcFormat) { - case 'r8snorm': - case 'rg8snorm': - case 'rgba8snorm': - alternateExpectedData = alternateExpectedData.slice(); - for (let i = 0; i < alternateExpectedData.length; ++i) { - if (alternateExpectedData[i] === 128) { - alternateExpectedData[i] = 129; - } else if (alternateExpectedData[i] === 129) { - alternateExpectedData[i] = 128; - } - } - break; - case 'bc4-r-snorm': - case 'bc5-rg-snorm': - case 'eac-r11snorm': - case 'eac-rg11snorm': - break; - default: - unreachable(); - } + if (isCompressedTextureFormat(dstFormat)) { + this.expectGPUBufferValuesPassCheck( + dstBuffer, + (vals) => checkElementsEqual(vals, expectedUint8DataWithPadding), + { + srcByteOffset: 0, + type: Uint8Array, + typedLength: expectedUint8DataWithPadding.length + } + ); + return; } + assert(isRegularTextureFormat(dstFormat)); + const regularDstFormat = dstFormat; + // Verify the content of the whole subresource of dstTexture at dstCopyLevel (in dstBuffer) is expected. - this.expectGPUBufferValuesPassCheck( - dstBuffer, - alternateExpectedData === expectedUint8DataWithPadding ? - (vals) => checkElementsEqual(vals, expectedUint8DataWithPadding) : - (vals) => - checkElementsEqualEither(vals, [expectedUint8DataWithPadding, alternateExpectedData]), - { - srcByteOffset: 0, - type: Uint8Array, - typedLength: expectedUint8DataWithPadding.length + const checkByTextureFormat = (actual) => { + const zero = { x: 0, y: 0, z: 0 }; + + const actTexelView = TexelView.fromTextureDataByReference(regularDstFormat, actual, { + bytesPerRow: bytesInRow, + rowsPerImage: dstBlockRowsPerImage, + subrectOrigin: zero, + subrectSize: dstTextureSizeAtLevel + }); + const expTexelView = TexelView.fromTextureDataByReference( + regularDstFormat, + expectedUint8DataWithPadding, + { + bytesPerRow: bytesInRow, + rowsPerImage: dstBlockRowsPerImage, + subrectOrigin: zero, + subrectSize: dstTextureSizeAtLevel + } + ); + + const failedPixelsMessage = findFailedPixels( + regularDstFormat, + zero, + dstTextureSizeAtLevel, + { actTexelView, expTexelView }, + { + maxFractionalDiff: 0 + } + ); + + if (failedPixelsMessage !== undefined) { + const msg = 'Texture level had unexpected contents:\n' + failedPixelsMessage; + return new ErrorWithExtra(msg, () => ({ + expTexelView, + actTexelView + })); } - ); + + return undefined; + }; + + this.expectGPUBufferValuesPassCheck(dstBuffer, checkByTextureFormat, { + srcByteOffset: 0, + type: Uint8Array, + typedLength: expectedUint8DataWithPadding.length + }); } InitializeStencilAspect( @@ -1349,6 +1376,9 @@ desc( texture can only be 1. ` ). +beforeAllSubcases((t) => { + t.skipIf(t.isCompatibility, 'multisample textures are not copyable in compatibility mode'); +}). fn((t) => { const textureSize = [32, 16, 1]; const kColorFormat = 'rgba8unorm'; @@ -1537,6 +1567,9 @@ desc( texture can only be 1. ` ). +beforeAllSubcases((t) => { + t.skipIf(t.isCompatibility, 'multisample textures are not copyable in compatibility mode'); +}). fn((t) => { const textureSize = [32, 16, 1]; const kDepthFormat = 'depth24plus'; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/image_copy.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/image_copy.spec.js index a86ebec917..e054cea3a8 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/image_copy.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/image_copy.spec.js @@ -25,8 +25,9 @@ * copy_with_no_image_or_slice_padding_and_undefined_values: test that when copying a single row we can set any bytesPerRow value and when copying a single\ slice we can set rowsPerImage to 0. Also test setting offset, rowsPerImage, mipLevel, origin, origin.{x,y,z} to undefined. +Note: more coverage of memory synchronization for different read and write texture methods are in same_subresource.spec.ts. + * TODO: - - add another initMethod which renders the texture [3] - test copyT2B with buffer size not divisible by 4 (not done because expectContents 4-byte alignment) - Convert the float32 values in initialData into the ones compatible to the depth aspect of depthFormats when depth16unorm is supported by the browsers in @@ -86,7 +87,7 @@ import { findFailedPixels } from '../../../util/texture/texture_ok.js'; * - PartialCopyT2B: do CopyT2B to check that the part of the texture we copied to with InitMethod * matches the data we were copying and that we don't overwrite any data in the target buffer that * we're not supposed to - that's primarily for testing CopyT2B functionality. - * - FullCopyT2B: do CopyT2B on the whole texture and check wether the part we copied to matches + * - FullCopyT2B: do CopyT2B on the whole texture and check whether the part we copied to matches * the data we were copying and that the nothing else was modified - that's primarily for testing * WriteTexture and CopyB2T. * @@ -1132,6 +1133,10 @@ class ImageCopyTest extends TextureTestMixin(GPUTest) { copySize ); + const use2DArray = this.isCompatibility && inputTexture.depthOrArrayLayers > 1; + const [textureType, layerCode] = use2DArray ? + ['texture_2d_array', ', baseArrayLayer'] : + ['texture_2d', '']; const renderPipeline = this.device.createRenderPipeline({ layout: 'auto', vertex: { @@ -1154,10 +1159,11 @@ class ImageCopyTest extends TextureTestMixin(GPUTest) { fragment: { module: this.device.createShaderModule({ code: ` - @group(0) @binding(0) var inputTexture: texture_2d; + @group(0) @binding(0) var inputTexture: ${textureType}; + @group(0) @binding(1) var baseArrayLayer: u32; @fragment fn main(@builtin(position) fragcoord : vec4) -> @builtin(frag_depth) f32 { - var depthValue : vec4 = textureLoad(inputTexture, vec2(fragcoord.xy), 0); + var depthValue : vec4 = textureLoad(inputTexture, vec2(fragcoord.xy)${layerCode}, 0); return depthValue.x; }` }), @@ -1200,19 +1206,26 @@ class ImageCopyTest extends TextureTestMixin(GPUTest) { }); renderPass.setPipeline(renderPipeline); + const uniformBufferEntry = use2DArray ? + [this.createUniformBufferAndBindGroupEntryForBaseArrayLayer(z)] : + []; + const bindGroup = this.device.createBindGroup({ layout: renderPipeline.getBindGroupLayout(0), entries: [ { binding: 0, resource: inputTexture.createView({ - dimension: '2d', - baseArrayLayer: z, - arrayLayerCount: 1, + dimension: use2DArray ? '2d-array' : '2d', + ...(!use2DArray && { + baseArrayLayer: z, + arrayLayerCount: 1 + }), baseMipLevel: 0, mipLevelCount: 1 }) - }] + }, + ...uniformBufferEntry] }); renderPass.setBindGroup(0, bindGroup); @@ -1223,6 +1236,23 @@ class ImageCopyTest extends TextureTestMixin(GPUTest) { this.queue.submit([encoder.finish()]); } + createUniformBufferAndBindGroupEntryForBaseArrayLayer(z) { + const buffer = this.device.createBuffer({ + usage: GPUBufferUsage.UNIFORM, + size: 4, + mappedAtCreation: true + }); + this.trackForCleanup(buffer); + new Uint32Array(buffer.getMappedRange()).set([z]); + buffer.unmap(); + return { + binding: 1, + resource: { + buffer + } + }; + } + DoCopyTextureToBufferWithDepthAspectTest( format, copySize, @@ -1328,8 +1358,6 @@ class ImageCopyTest extends TextureTestMixin(GPUTest) { /** * This is a helper function used for filtering test parameters - * - * [3]: Modify this after introducing tests with rendering. */ function formatCanBeTested({ format }) { return kTextureFormatInfo[format].color.copyDst && kTextureFormatInfo[format].color.copySrc; @@ -1491,6 +1519,12 @@ works for every format with 2d and 2d-array textures. offset + bytesInCopyExtentPerRow { ==, > } bytesPerRow offset > bytesInACompleteCopyImage + Covers spceial cases for OpenGL Compat: + offset % 4 > 0 while: + - padding bytes at end of each row/layer: bytesPerRow % 256 > 0 || rowsPerImage > copyDepth + - rows/layers are compact: bytesPerRow % 256 == 0 && rowsPerImage == copyDepth + - padding bytes at front and end of the same 4-byte word: format == 'r8snorm' && copyWidth <= 2 + TODO: Cover the special code paths for 3D textures in D3D12. TODO: Make a variant for depth-stencil formats. ` @@ -1505,7 +1539,19 @@ filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, beginSubcases(). combineWithParams(kOffsetsAndSizesParams.offsetsAndPaddings). combine('copyDepth', kOffsetsAndSizesParams.copyDepth) // 2d and 2d-array textures -.unless((p) => p.dimension === '1d' && p.copyDepth !== 1) +.combine('copyWidth', [3, 1, 2, 127, 128, 255, 256]) // copyWidth === 3 is the default. Others covers special cases for r8snorm and rg8snorm on compatiblity mode. +.filter(({ format, copyWidth }) => { + switch (format) { + case 'r8snorm': + case 'rg8snorm': + return true; + default: + // Restrict test parameters to save run time. + return copyWidth === 3; + } +}). +combine('rowsPerImageEqualsCopyHeight', [true, false]). +unless((p) => p.dimension === '1d' && p.copyDepth !== 1) ). beforeAllSubcases((t) => { const info = kTextureFormatInfo[t.params.format]; @@ -1520,26 +1566,44 @@ fn((t) => { format, dimension, initMethod, - checkMethod + checkMethod, + copyWidth, + rowsPerImageEqualsCopyHeight } = t.params; + + // Skip test cases designed for special cases coverage on compatibility mode to save run time. + if (!(t.isCompatibility && (format === 'r8snorm' || format === 'rg8snorm'))) { + if (rowsPerImageEqualsCopyHeight === false) { + t.skip( + 'rowsPerImageEqualsCopyHeight === false is only for r8snorm and rg8snorm on compatibility mode' + ); + } + + if (copyWidth !== 3) { + t.skip('copyWidth !== 3 is only for r8snorm and rg8snorm on compatibility mode'); + } + } + const info = kTextureFormatInfo[format]; const offset = offsetInBlocks * info.color.bytes; + const copyHeight = 3; const copySize = { - width: 3 * info.blockWidth, - height: 3 * info.blockHeight, + width: copyWidth * info.blockWidth, + height: copyHeight * info.blockHeight, depthOrArrayLayers: copyDepth }; let textureHeight = 4 * info.blockHeight; - let rowsPerImage = 3; - const bytesPerRow = 256; + let rowsPerImage = rowsPerImageEqualsCopyHeight ? copyHeight : copyHeight + 1; + const bytesPerRow = align(copyWidth * info.color.bytes, 256); if (dimension === '1d') { copySize.height = 1; textureHeight = info.blockHeight; rowsPerImage = 1; } - const textureSize = [4 * info.blockWidth, textureHeight, copyDepth]; + // Add textureWidth by 1 to make sure we are doing a partial copy. + const textureSize = [(copyWidth + 1) * info.blockWidth, textureHeight, copyDepth]; const minDataSize = dataBytesForCopyOrFail({ layout: { offset, bytesPerRow, rowsPerImage }, @@ -1549,7 +1613,7 @@ fn((t) => { }); const dataSize = minDataSize + dataPaddingInBytes; - // We're copying a (3 x 3 x copyDepth) (in texel blocks) part of a (4 x 4 x copyDepth) + // We're copying a (copyWidth x 3 x copyDepth) (in texel blocks) part of a ((copyWidth + 1) x 4 x copyDepth) // (in texel blocks) texture with no origin. t.uploadTextureAndVerifyCopy({ textureDataLayout: { offset, bytesPerRow, rowsPerImage }, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/queries/occlusionQuery.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/queries/occlusionQuery.spec.js index 716b59fd6f..fc25802db4 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/queries/occlusionQuery.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/queries/occlusionQuery.spec.js @@ -695,7 +695,7 @@ fn(async (t) => { const expectPassed = !occluded; t.expect( !!passed === expectPassed, - `queryIndex: ${queryIndex}, scissorCase: ${scissorCase}, was: ${!!passed}, expected: ${expectPassed}, ${name}` + `queryIndex: ${queryIndex}, scissorCase: ${scissorCase}, was: ${!!passed}, expected: ${expectPassed}` ); } ); @@ -739,7 +739,7 @@ fn(async (t) => { const expectPassed = queryIndex % 2 === 0; t.expect( !!passed === expectPassed, - `queryIndex: ${queryIndex}, was: ${!!passed}, expected: ${expectPassed}, ${name}` + `queryIndex: ${queryIndex}, was: ${!!passed}, expected: ${expectPassed}` ); } ); @@ -783,7 +783,7 @@ fn(async (t) => { const expectPassed = queryIndex % 2 === 0; t.expect( !!passed === expectPassed, - `queryIndex: ${queryIndex}, was: ${!!passed}, expected: ${expectPassed}, ${name}` + `queryIndex: ${queryIndex}, was: ${!!passed}, expected: ${expectPassed}` ); } ); @@ -851,7 +851,7 @@ fn(async (t) => { const expectPassed = !!(sampleMask & drawMask); t.expect( !!passed === expectPassed, - `queryIndex: ${queryIndex}, was: ${!!passed}, expected: ${expectPassed}, ${name}` + `queryIndex: ${queryIndex}, was: ${!!passed}, expected: ${expectPassed}` ); } ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/readonly_depth_stencil.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/readonly_depth_stencil.spec.js new file mode 100644 index 0000000000..a52c12f8e9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/readonly_depth_stencil.spec.js @@ -0,0 +1,329 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Memory synchronization tests for depth-stencil attachments in a single pass, with checks for readonlyness. +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { kDepthStencilFormats, kTextureFormatInfo } from '../../../../format_info.js'; +import { GPUTest } from '../../../../gpu_test.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('sampling_while_testing'). +desc( + `Tests concurrent sampling and testing of readonly depth-stencil attachments in a render pass. + - Test for all depth-stencil formats. + - Test for all valid combinations of depth/stencilReadOnly. + +In particular this test checks that a non-readonly aspect can be rendered to, and used for depth/stencil +testing while the other one is used for sampling. + ` +). +params((p) => +p. +combine('format', kDepthStencilFormats) // +.combine('depthReadOnly', [true, false, undefined]). +combine('stencilReadOnly', [true, false, undefined]). +filter((p) => { + const info = kTextureFormatInfo[p.format]; + const depthMatch = info.depth === undefined === (p.depthReadOnly === undefined); + const stencilMatch = info.stencil === undefined === (p.stencilReadOnly === undefined); + return depthMatch && stencilMatch; +}) +). +beforeAllSubcases((t) => { + const { format } = t.params; + const formatInfo = kTextureFormatInfo[format]; + const hasDepth = formatInfo.depth !== undefined; + const hasStencil = formatInfo.stencil !== undefined; + + t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format); + t.skipIf( + t.isCompatibility && hasDepth && hasStencil, + 'compatibility mode does not support different TEXTURE_BINDING views of the same texture in a single draw calls' + ); +}). +fn((t) => { + const { format, depthReadOnly, stencilReadOnly } = t.params; + const formatInfo = kTextureFormatInfo[format]; + const hasDepth = formatInfo.depth !== undefined; + const hasStencil = formatInfo.stencil !== undefined; + + // The 3x3 depth stencil texture used for the tests. + const ds = t.device.createTexture({ + label: 'testTexture', + size: [3, 3], + format, + usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING + }); + t.trackForCleanup(ds); + + // Fill the texture along the X axis with stencil values 1, 2, 3 and along the Y axis depth + // values 0.1, 0.2, 0.3. The depth value is written using @builtin(frag_depth) while the + // stencil is written using stencil operation and modifying the stencilReference. + const initModule = t.device.createShaderModule({ + code: ` + @vertex fn vs( + @builtin(instance_index) x : u32, @builtin(vertex_index) y : u32 + ) -> @builtin(position) vec4f { + let texcoord = (vec2f(f32(x), f32(y)) + vec2f(0.5)) / 3; + return vec4f((texcoord * 2) - vec2f(1.0), 0, 1); + } + @fragment fn fs_with_depth(@builtin(position) pos : vec4f) -> @builtin(frag_depth) f32 { + return (pos.y + 0.5) / 10; + } + @fragment fn fs_no_depth() { + } + ` + }); + const initPipeline = t.device.createRenderPipeline({ + layout: 'auto', + label: 'initPipeline', + vertex: { module: initModule }, + fragment: { + module: initModule, + targets: [], + entryPoint: hasDepth ? 'fs_with_depth' : 'fs_no_depth' + }, + depthStencil: { + format, + ...(hasDepth && { + depthWriteEnabled: true, + depthCompare: 'always' + }), + ...(hasStencil && { + stencilBack: { compare: 'always', passOp: 'replace' }, + stencilFront: { compare: 'always', passOp: 'replace' } + }) + }, + primitive: { topology: 'point-list' } + }); + + const encoder = t.device.createCommandEncoder(); + + const initPass = encoder.beginRenderPass({ + colorAttachments: [], + depthStencilAttachment: { + view: ds.createView(), + ...(hasDepth && { + depthStoreOp: 'store', + depthLoadOp: 'clear', + depthClearValue: 0 + }), + ...(hasStencil && { + stencilStoreOp: 'store', + stencilLoadOp: 'clear', + stencilClearValue: 0 + }) + } + }); + initPass.setPipeline(initPipeline); + for (let i = 0; i < 3; i++) { + initPass.setStencilReference(i + 1); + // Draw 3 points (Y = 0, 1, 2) at X = instance_index = i. + initPass.draw(3, 1, 0, i); + } + initPass.end(); + + // Perform the actual test: + // - The shader outputs depth 0.15 and stencil 2 (via stencilReference). + // - Test that the fragdepth / stencilref must be <= to what's in the depth-stencil attachment. + // -> Fragments that have depth 0.1 or stencil 1 are tested out. + // - Test that sampling the depth / stencil (when possible) is <= 0.2 for depth, <= 2 for stencil + // -> Fragments that have depth 0.3 or stencil 3 are discarded if that aspect is readonly. + // - Write the depth / increment the stencil if the aspect is not readonly. + // -> After the test, fragments that passed will have non-readonly aspects updated. + const kFragDepth = 0.15; + const kStencilRef = 2; + const testAndCheckModule = t.device.createShaderModule({ + code: ` + @group(0) @binding(0) var depthTex : texture_2d; + @group(0) @binding(1) var stencilTex : texture_2d; + + @vertex fn full_quad_vs(@builtin(vertex_index) id : u32) -> @builtin(position) vec4f { + let pos = array(vec2f(-3, -1), vec2(3, -1), vec2(0, 2)); + return vec4f(pos[id], ${kFragDepth}, 1.0); + } + + @fragment fn test_texture(@builtin(position) pos : vec4f) { + let texel = vec2u(floor(pos.xy)); + if ${!!stencilReadOnly} && textureLoad(stencilTex, texel, 0).r > 2 { + discard; + } + if ${!!depthReadOnly} && textureLoad(depthTex, texel, 0).r > 0.21 { + discard; + } + } + + @fragment fn check_texture(@builtin(position) pos : vec4f) -> @location(0) u32 { + let texel = vec2u(floor(pos.xy)); + + // The current values in the framebuffer. + let initStencil = texel.x + 1; + let initDepth = f32(texel.y + 1) / 10.0; + + // Expected results of the test_texture step. + let stencilTestPasses = !${hasStencil} || ${kStencilRef} <= initStencil; + let depthTestPasses = !${hasDepth} || ${kFragDepth} <= initDepth; + let fsDiscards = (${!!stencilReadOnly} && initStencil > 2) || + (${!!depthReadOnly} && initDepth > 0.21); + + // Compute the values that should be in the framebuffer. + var stencil = initStencil; + var depth = initDepth; + + // When the fragments aren't discarded, fragment output operations happen. + if depthTestPasses && stencilTestPasses && !fsDiscards { + if ${!stencilReadOnly} { + stencil += 1; + } + if ${!depthReadOnly} { + depth = ${kFragDepth}; + } + } + + if ${hasStencil} && textureLoad(stencilTex, texel, 0).r != stencil { + return 0; + } + if ${hasDepth} && abs(textureLoad(depthTex, texel, 0).r - depth) > 0.01 { + return 0; + } + return 1; + } + ` + }); + const testPipeline = t.device.createRenderPipeline({ + label: 'testPipeline', + layout: 'auto', + vertex: { module: testAndCheckModule }, + fragment: { module: testAndCheckModule, entryPoint: 'test_texture', targets: [] }, + depthStencil: { + format, + ...(hasDepth && { + depthCompare: 'less-equal', + depthWriteEnabled: !depthReadOnly + }), + ...(hasStencil && { + stencilBack: { + compare: 'less-equal', + passOp: stencilReadOnly ? 'keep' : 'increment-clamp' + }, + stencilFront: { + compare: 'less-equal', + passOp: stencilReadOnly ? 'keep' : 'increment-clamp' + } + }) + }, + primitive: { topology: 'triangle-list' } + }); + + // Make fake stencil or depth textures to put in the bindgroup if the aspect is not readonly. + const fakeStencil = t.device.createTexture({ + label: 'fakeStencil', + format: 'r32uint', + size: [1, 1], + usage: GPUTextureUsage.TEXTURE_BINDING + }); + t.trackForCleanup(fakeStencil); + const fakeDepth = t.device.createTexture({ + label: 'fakeDepth', + format: 'r32float', + size: [1, 1], + usage: GPUTextureUsage.TEXTURE_BINDING + }); + t.trackForCleanup(fakeDepth); + const stencilView = stencilReadOnly ? + ds.createView({ aspect: 'stencil-only' }) : + fakeStencil.createView(); + const depthView = depthReadOnly ? + ds.createView({ aspect: 'depth-only' }) : + fakeDepth.createView(); + const testBindGroup = t.device.createBindGroup({ + layout: testPipeline.getBindGroupLayout(0), + entries: [ + { binding: 0, resource: depthView }, + { binding: 1, resource: stencilView }] + + }); + + // Run the test. + const testPass = encoder.beginRenderPass({ + colorAttachments: [], + depthStencilAttachment: { + view: ds.createView(), + ...(hasDepth && ( + depthReadOnly ? + { depthReadOnly: true } : + { + depthStoreOp: 'store', + depthLoadOp: 'load' + })), + ...(hasStencil && ( + stencilReadOnly ? + { stencilReadOnly: true } : + { + stencilStoreOp: 'store', + stencilLoadOp: 'load' + })) + } + }); + testPass.setPipeline(testPipeline); + testPass.setStencilReference(kStencilRef); + testPass.setBindGroup(0, testBindGroup); + testPass.draw(3); + testPass.end(); + + // Check that the contents of the textures are what we expect. See the shader module for the + // computation of what's expected, it writes a 1 on success, 0 otherwise. + const checkPipeline = t.device.createRenderPipeline({ + label: 'checkPipeline', + layout: 'auto', + vertex: { module: testAndCheckModule }, + fragment: { + module: testAndCheckModule, + entryPoint: 'check_texture', + targets: [{ format: 'r32uint' }] + }, + primitive: { topology: 'triangle-list' } + }); + const checkBindGroup = t.device.createBindGroup({ + layout: checkPipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: hasDepth ? ds.createView({ aspect: 'depth-only' }) : fakeDepth.createView() + }, + { + binding: 1, + resource: hasStencil ? + ds.createView({ aspect: 'stencil-only' }) : + fakeStencil.createView() + }] + + }); + + const resultTexture = t.device.createTexture({ + label: 'resultTexture', + format: 'r32uint', + usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC, + size: [3, 3] + }); + const checkPass = encoder.beginRenderPass({ + colorAttachments: [ + { + view: resultTexture.createView(), + loadOp: 'clear', + clearValue: [0, 0, 0, 0], + storeOp: 'store' + }] + + }); + checkPass.setPipeline(checkPipeline); + checkPass.setBindGroup(0, checkBindGroup); + checkPass.draw(3); + checkPass.end(); + + t.queue.submit([encoder.finish()]); + + // The check texture should be full of success (a.k.a. 1)! + t.expectSingleColor(resultTexture, resultTexture.format, { size: [3, 3, 1], exp: { R: 1 } }); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/reflection.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/reflection.spec.js index da9d90b819..3fd7746ebe 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/reflection.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/reflection.spec.js @@ -8,26 +8,38 @@ import { GPUTest } from '../../gpu_test.js'; export const g = makeTestGroup(GPUTest); -g.test('buffer_reflection_attributes'). -desc(`For every buffer attribute, the corresponding descriptor value is carried over.`). -paramsSubcasesOnly((u) => -u.combine('descriptor', [ +function* extractValuePropertyKeys(obj) { + for (const key in obj) { + if (typeof obj[key] !== 'function') { + yield key; + } + } +} + +const kBufferSubcases = + + + + +[ { size: 4, usage: GPUConst.BufferUsage.VERTEX }, { size: 16, usage: - GPUConst.BufferUsage.STORAGE | - GPUConst.BufferUsage.COPY_SRC | - GPUConst.BufferUsage.UNIFORM + GPUConst.BufferUsage.STORAGE | GPUConst.BufferUsage.COPY_SRC | GPUConst.BufferUsage.UNIFORM }, { size: 32, usage: GPUConst.BufferUsage.MAP_READ | GPUConst.BufferUsage.COPY_DST }, +{ size: 40, usage: GPUConst.BufferUsage.INDEX, label: 'some label' }, { size: 32, usage: GPUConst.BufferUsage.MAP_READ | GPUConst.BufferUsage.MAP_WRITE, invalid: true -}] -) -). +}]; + + +g.test('buffer_reflection_attributes'). +desc(`For every buffer attribute, the corresponding descriptor value is carried over.`). +paramsSubcasesOnly((u) => u.combine('descriptor', kBufferSubcases)). fn((t) => { const { descriptor } = t.params; @@ -39,15 +51,61 @@ fn((t) => { }, descriptor.invalid === true); }); -g.test('texture_reflection_attributes'). -desc(`For every texture attribute, the corresponding descriptor value is carried over.`). +g.test('buffer_creation_from_reflection'). +desc( + ` + Check that you can create a buffer from a buffer's reflection. + This check is to insure that as WebGPU develops this path doesn't + suddenly break because of new reflection. + ` +). paramsSubcasesOnly((u) => -u.combine('descriptor', [ +u.combine('descriptor', kBufferSubcases).filter((p) => !p.descriptor.invalid) +). + +fn((t) => { + const { descriptor } = t.params; + + const buffer = t.device.createBuffer(descriptor); + t.trackForCleanup(buffer); + const buffer2 = t.device.createBuffer(buffer); + t.trackForCleanup(buffer2); + + const bufferAsObject = buffer; + const buffer2AsObject = buffer2; + const keys = [...extractValuePropertyKeys(bufferAsObject)]; + + // Sanity check + t.expect(keys.includes('size')); + t.expect(keys.includes('usage')); + t.expect(keys.includes('label')); + + for (const key of keys) { + t.expect(bufferAsObject[key] === buffer2AsObject[key], key); + } +}); + +const kTextureSubcases = + + + + + + + + +[ { size: { width: 4, height: 4 }, format: 'rgba8unorm', usage: GPUConst.TextureUsage.TEXTURE_BINDING }, +{ + size: { width: 4, height: 4 }, + format: 'rgba8unorm', + usage: GPUConst.TextureUsage.TEXTURE_BINDING, + label: 'some label' +}, { size: { width: 8, height: 8, depthOrArrayLayers: 8 }, format: 'bgra8unorm', @@ -83,9 +141,12 @@ u.combine('descriptor', [ usage: GPUConst.TextureUsage.TEXTURE_BINDING, sampleCount: 4, invalid: true -}] -) -). +}]; + + +g.test('texture_reflection_attributes'). +desc(`For every texture attribute, the corresponding descriptor value is carried over.`). +paramsSubcasesOnly((u) => u.combine('descriptor', kTextureSubcases)). fn((t) => { const { descriptor } = t.params; @@ -116,15 +177,74 @@ fn((t) => { }, descriptor.invalid === true); }); -g.test('query_set_reflection_attributes'). -desc(`For every queue attribute, the corresponding descriptor value is carried over.`). + + + + +g.test('texture_creation_from_reflection'). +desc( + ` + Check that you can create a texture from a texture's reflection. + This check is to insure that as WebGPU develops this path doesn't + suddenly break because of new reflection. + ` +). paramsSubcasesOnly((u) => -u.combine('descriptor', [ +u.combine('descriptor', kTextureSubcases).filter((p) => !p.descriptor.invalid) +). +fn((t) => { + const { descriptor } = t.params; + + const texture = t.device.createTexture(descriptor); + t.trackForCleanup(texture); + const textureWithSize = texture; + textureWithSize.size = [texture.width, texture.height, texture.depthOrArrayLayers]; + const texture2 = t.device.createTexture(textureWithSize); + t.trackForCleanup(texture2); + + const textureAsObject = texture; + const texture2AsObject = texture2; + const keys = [...extractValuePropertyKeys(textureAsObject)].filter((k) => k !== 'size'); + + // Sanity check + t.expect(keys.includes('format')); + t.expect(keys.includes('usage')); + t.expect(keys.includes('label')); + + for (const key of keys) { + t.expect(textureAsObject[key] === texture2AsObject[key], key); + } + + // MAINTENANCE_TODO: Check this if it is made possible by a spec change. + // + // texture3 = t.device.createTexture({ + // ...texture, + // size: [texture.width, texture.height, texture.depthOrArrayLayers], + // }); + // + // and this + // + // texture3 = t.device.createTexture({ + // size: [texture.width, texture.height, texture.depthOrArrayLayers], + // ...texture, + // }); +}); + +const kQuerySetSubcases = + + + + +[ { type: 'occlusion', count: 4 }, { type: 'occlusion', count: 16 }, -{ type: 'occlusion', count: 8193, invalid: true }] -) -). +{ type: 'occlusion', count: 32, label: 'some label' }, +{ type: 'occlusion', count: 8193, invalid: true }]; + + +g.test('query_set_reflection_attributes'). +desc(`For every queue attribute, the corresponding descriptor value is carried over.`). +paramsSubcasesOnly((u) => u.combine('descriptor', kQuerySetSubcases)). fn((t) => { const { descriptor } = t.params; @@ -134,4 +254,37 @@ fn((t) => { t.expect(querySet.type === descriptor.type); t.expect(querySet.count === descriptor.count); }, descriptor.invalid === true); +}); + +g.test('query_set_creation_from_reflection'). +desc( + ` + Check that you can create a queryset from a queryset's reflection. + This check is to insure that as WebGPU develops this path doesn't + suddenly break because of new reflection. + ` +). +paramsSubcasesOnly((u) => +u.combine('descriptor', kQuerySetSubcases).filter((p) => !p.descriptor.invalid) +). +fn((t) => { + const { descriptor } = t.params; + + const querySet = t.device.createQuerySet(descriptor); + t.trackForCleanup(querySet); + const querySet2 = t.device.createQuerySet(querySet); + t.trackForCleanup(querySet2); + + const querySetAsObject = querySet; + const querySet2AsObject = querySet2; + const keys = [...extractValuePropertyKeys(querySetAsObject)]; + + // Sanity check + t.expect(keys.includes('type')); + t.expect(keys.includes('count')); + t.expect(keys.includes('label')); + + for (const key of keys) { + t.expect(querySetAsObject[key] === querySet2AsObject[key], key); + } }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/sample_mask.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/sample_mask.spec.js index 60487998df..0afa98e254 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/sample_mask.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/sample_mask.spec.js @@ -8,6 +8,8 @@ Also tested: - The positions of samples in the standard sample patterns. - Per-sample interpolation sampling: @interpolate(perspective, sample). +TODO: Test sample_mask as an input. + TODO: add a test without a 0th color attachment (sparse color attachment), with different color attachments and alpha value output. The cross-platform behavior is unknown. could be any of: - coverage is always 100% @@ -19,7 +21,7 @@ Details could be found at: https://github.com/gpuweb/cts/issues/2201 import { assert, range } from '../../../../common/util/util.js'; import { GPUTest, TextureTestMixin } from '../../../gpu_test.js'; import { checkElementsPassPredicate, checkElementsEqual } from '../../../util/check_contents.js'; -import { TypeF32, TypeU32 } from '../../../util/conversion.js'; +import { Type } from '../../../util/conversion.js'; import { TexelView } from '../../../util/texture/texel_view.js'; const kColors = [ @@ -435,8 +437,8 @@ class F extends TextureTestMixin(GPUTest) { sampleMask, fragmentShaderOutputMask) { - const buffer = this.copySinglePixelTextureToBufferUsingComputePass( - TypeF32, // correspond to 'rgba8unorm' format + const buffer = this.copy2DTextureToBufferUsingComputePass( + Type.f32, // correspond to 'rgba8unorm' format 4, texture.createView(), sampleCount @@ -459,10 +461,10 @@ class F extends TextureTestMixin(GPUTest) { sampleMask, fragmentShaderOutputMask) { - const buffer = this.copySinglePixelTextureToBufferUsingComputePass( + const buffer = this.copy2DTextureToBufferUsingComputePass( // Use f32 as the scalar type for depth (depth24plus, depth32float) // Use u32 as the scalar type for stencil (stencil8) - aspect === 'depth-only' ? TypeF32 : TypeU32, + aspect === 'depth-only' ? Type.f32 : Type.u32, 1, depthStencilTexture.createView({ aspect }), sampleCount @@ -702,8 +704,8 @@ fn(async (t) => { 2 ); - const colorBuffer = t.copySinglePixelTextureToBufferUsingComputePass( - TypeF32, // correspond to 'rgba8unorm' format + const colorBuffer = t.copy2DTextureToBufferUsingComputePass( + Type.f32, // correspond to 'rgba8unorm' format 4, color.createView(), sampleCount @@ -714,8 +716,8 @@ fn(async (t) => { }); colorResultPromises.push(colorResult); - const depthBuffer = t.copySinglePixelTextureToBufferUsingComputePass( - TypeF32, // correspond to 'depth24plus-stencil8' format + const depthBuffer = t.copy2DTextureToBufferUsingComputePass( + Type.f32, // correspond to 'depth24plus-stencil8' format 1, depthStencil.createView({ aspect: 'depth-only' }), sampleCount @@ -726,8 +728,8 @@ fn(async (t) => { }); depthResultPromises.push(depthResult); - const stencilBuffer = t.copySinglePixelTextureToBufferUsingComputePass( - TypeU32, // correspond to 'depth24plus-stencil8' format + const stencilBuffer = t.copy2DTextureToBufferUsingComputePass( + Type.u32, // correspond to 'depth24plus-stencil8' format 1, depthStencil.createView({ aspect: 'stencil-only' }), sampleCount diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/3d_texture_slices.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/3d_texture_slices.spec.js new file mode 100644 index 0000000000..9146505064 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/3d_texture_slices.spec.js @@ -0,0 +1,363 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Test rendering to 3d texture slices. +- Render to same slice on different render pass, different textures, or texture [1, 1, N]'s different mip levels +- Render to different slices at mip levels on same texture in render pass +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { kTextureFormatInfo } from '../../../format_info.js'; +import { GPUTest } from '../../../gpu_test.js'; +import { kBytesPerRowAlignment } from '../../../util/texture/layout.js'; + +const kSize = 4; +const kFormat = 'rgba8unorm'; + +class F extends GPUTest { + createShaderModule(attachmentCount = 1) { + let locations = ''; + let outputs = ''; + for (let i = 0; i < attachmentCount; i++) { + locations = locations + `@location(${i}) color${i} : vec4f, \n`; + outputs = outputs + `output.color${i} = vec4f(0.0, 1.0, 0.0, 1.0);\n`; + } + + return this.device.createShaderModule({ + code: ` + struct Output { + ${locations} + } + + @vertex + fn main_vs(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4 { + var pos : array, 3> = array, 3>( + // Triangle is slightly extended so its edge doesn't cut through pixel centers. + vec2(-1.0, 1.01), + vec2(1.01, -1.0), + vec2(-1.0, -1.0)); + return vec4(pos[VertexIndex], 0.0, 1.0); + } + + @fragment + fn main_fs() -> Output { + var output : Output; + ${outputs} + return output; + } + ` + }); + } + + getBufferSizeAndOffset( + attachmentWidth, + attachmentHeight, + attachmentCount) + { + const bufferSize = + (attachmentCount * attachmentHeight - 1) * kBytesPerRowAlignment + attachmentWidth * 4; + const bufferOffset = attachmentCount > 1 ? attachmentHeight * kBytesPerRowAlignment : 0; + return { bufferSize, bufferOffset }; + } + + checkAttachmentResult( + attachmentWidth, + attachmentHeight, + attachmentCount, + buffer) + { + const { bufferSize, bufferOffset } = this.getBufferSizeAndOffset( + attachmentWidth, + attachmentHeight, + attachmentCount + ); + const expectedData = new Uint8Array(bufferSize); + for (let i = 0; i < attachmentCount; i++) { + for (let j = 0; j < attachmentHeight; j++) { + for (let k = 0; k < attachmentWidth; k++) { + expectedData[i * bufferOffset + j * 256 + k * 4] = k <= j ? 0x00 : 0xff; + expectedData[i * bufferOffset + j * 256 + k * 4 + 1] = k <= j ? 0xff : 0x00; + expectedData[i * bufferOffset + j * 256 + k * 4 + 2] = 0x00; + expectedData[i * bufferOffset + j * 256 + k * 4 + 3] = 0xff; + } + } + } + + this.expectGPUBufferValuesEqual(buffer, expectedData); + } +} + +export const g = makeTestGroup(F); + +g.test('one_color_attachment,mip_levels'). +desc( + ` + Render to a 3d texture slice with mip levels. + ` +). +params((u) => u.combine('mipLevel', [0, 1, 2]).combine('depthSlice', [0, 1])). +fn((t) => { + const { mipLevel, depthSlice } = t.params; + + const texture = t.device.createTexture({ + size: [kSize << mipLevel, kSize << mipLevel, 2 << mipLevel], + dimension: '3d', + format: kFormat, + mipLevelCount: mipLevel + 1, + usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC + }); + + const { bufferSize } = t.getBufferSizeAndOffset(kSize, kSize, 1); + + const buffer = t.device.createBuffer({ + size: bufferSize, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + }); + + const module = t.createShaderModule(); + + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { module }, + fragment: { + module, + targets: [{ format: kFormat }] + }, + primitive: { topology: 'triangle-list' } + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ + colorAttachments: [ + { + view: texture.createView({ + baseMipLevel: mipLevel, + mipLevelCount: 1 + }), + depthSlice, + clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 }, + loadOp: 'clear', + storeOp: 'store' + }] + + }); + pass.setPipeline(pipeline); + pass.draw(3); + pass.end(); + encoder.copyTextureToBuffer( + { texture, mipLevel, origin: { x: 0, y: 0, z: depthSlice } }, + { buffer, bytesPerRow: 256 }, + { width: kSize, height: kSize, depthOrArrayLayers: 1 } + ); + t.device.queue.submit([encoder.finish()]); + + t.checkAttachmentResult(kSize, kSize, 1, buffer); +}); + +g.test('multiple_color_attachments,same_mip_level'). +desc( + ` + Render to the different slices of 3d texture in multiple color attachments. + - Same 3d texture with different slices at same mip level + - Different 3d textures with same slice at same mip level + ` +). +params((u) => +u. +combine('sameTexture', [true, false]). +beginSubcases(). +combine('samePass', [true, false]). +combine('mipLevel', [0, 1]) +). +fn((t) => { + const { sameTexture, samePass, mipLevel } = t.params; + + const formatByteCost = kTextureFormatInfo[kFormat].colorRender.byteCost; + const maxAttachmentCountPerSample = Math.trunc( + t.device.limits.maxColorAttachmentBytesPerSample / formatByteCost + ); + const attachmentCount = Math.min( + maxAttachmentCountPerSample, + t.device.limits.maxColorAttachments + ); + + const descriptor = { + size: [kSize << mipLevel, kSize << mipLevel, 1 << attachmentCount << mipLevel], + dimension: '3d', + format: kFormat, + mipLevelCount: mipLevel + 1, + usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC + }; + + const texture = t.device.createTexture(descriptor); + + const textures = []; + const colorAttachments = []; + for (let i = 0; i < attachmentCount; i++) { + if (sameTexture) { + textures.push(texture); + } else { + const diffTexture = t.device.createTexture(descriptor); + textures.push(diffTexture); + } + + const colorAttachment = { + view: textures[i].createView({ + baseMipLevel: mipLevel, + mipLevelCount: 1 + }), + depthSlice: sameTexture ? i : 0, + clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 }, + loadOp: 'clear', + storeOp: 'store' + }; + + colorAttachments.push(colorAttachment); + } + + const encoder = t.device.createCommandEncoder(); + + if (samePass) { + const module = t.createShaderModule(attachmentCount); + + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { module }, + fragment: { + module, + targets: new Array(attachmentCount).fill({ format: kFormat }) + }, + primitive: { topology: 'triangle-list' } + }); + + const pass = encoder.beginRenderPass({ colorAttachments }); + pass.setPipeline(pipeline); + pass.draw(3); + pass.end(); + } else { + const module = t.createShaderModule(); + + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { module }, + fragment: { + module, + targets: [{ format: kFormat }] + }, + primitive: { topology: 'triangle-list' } + }); + + for (let i = 0; i < attachmentCount; i++) { + const pass = encoder.beginRenderPass({ colorAttachments: [colorAttachments[i]] }); + pass.setPipeline(pipeline); + pass.draw(3); + pass.end(); + } + } + + const { bufferSize, bufferOffset } = t.getBufferSizeAndOffset(kSize, kSize, attachmentCount); + const buffer = t.device.createBuffer({ + size: bufferSize, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + }); + for (let i = 0; i < attachmentCount; i++) { + encoder.copyTextureToBuffer( + { + texture: textures[i], + mipLevel, + origin: { x: 0, y: 0, z: sameTexture ? i : 0 } + }, + { buffer, bytesPerRow: 256, offset: bufferOffset * i }, + { width: kSize, height: kSize, depthOrArrayLayers: 1 } + ); + } + + t.device.queue.submit([encoder.finish()]); + + t.checkAttachmentResult(kSize, kSize, attachmentCount, buffer); +}); + +g.test('multiple_color_attachments,same_slice_with_diff_mip_levels'). +desc( + ` + Render to the same slice of a 3d texture at different mip levels in multiple color attachments. + - For texture size with 1x1xN, the same depth slice of different mip levels can be rendered. + ` +). +params((u) => u.combine('depthSlice', [0, 1])). +fn((t) => { + const { depthSlice } = t.params; + + const kBaseSize = 1; + + const formatByteCost = kTextureFormatInfo[kFormat].colorRender.byteCost; + const maxAttachmentCountPerSample = Math.trunc( + t.device.limits.maxColorAttachmentBytesPerSample / formatByteCost + ); + const attachmentCount = Math.min( + maxAttachmentCountPerSample, + t.device.limits.maxColorAttachments + ); + + const module = t.createShaderModule(attachmentCount); + + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { module }, + fragment: { + module, + targets: new Array(attachmentCount).fill({ format: kFormat }) + }, + primitive: { topology: 'triangle-list' } + }); + + const texture = t.device.createTexture({ + size: [kBaseSize, kBaseSize, depthSlice + 1 << attachmentCount], + dimension: '3d', + format: kFormat, + mipLevelCount: attachmentCount, + usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC + }); + + const colorAttachments = []; + for (let i = 0; i < attachmentCount; i++) { + const colorAttachment = { + view: texture.createView({ + baseMipLevel: i, + mipLevelCount: 1 + }), + depthSlice, + clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 }, + loadOp: 'clear', + storeOp: 'store' + }; + + colorAttachments.push(colorAttachment); + } + + const encoder = t.device.createCommandEncoder(); + + const pass = encoder.beginRenderPass({ colorAttachments }); + pass.setPipeline(pipeline); + pass.draw(3); + pass.end(); + + const { bufferSize, bufferOffset } = t.getBufferSizeAndOffset( + kBaseSize, + kBaseSize, + attachmentCount + ); + const buffer = t.device.createBuffer({ + size: bufferSize, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + }); + for (let i = 0; i < attachmentCount; i++) { + encoder.copyTextureToBuffer( + { texture, mipLevel: i, origin: { x: 0, y: 0, z: depthSlice } }, + { buffer, bytesPerRow: 256, offset: bufferOffset * i }, + { width: kBaseSize, height: kBaseSize, depthOrArrayLayers: 1 } + ); + } + + t.device.queue.submit([encoder.finish()]); + + t.checkAttachmentResult(kBaseSize, kBaseSize, attachmentCount, buffer); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/color_target_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/color_target_state.spec.js index 4e0a49f507..f23ea3ed62 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/color_target_state.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/color_target_state.spec.js @@ -11,7 +11,7 @@ TODO: import { assert, unreachable } from '../../../../common/util/util.js'; import { kBlendFactors, kBlendOperations } from '../../../capability_info.js'; import { GPUConst } from '../../../constants.js'; -import { kEncodableTextureFormats, kTextureFormatInfo } from '../../../format_info.js'; +import { kRegularTextureFormats, kTextureFormatInfo } from '../../../format_info.js'; import { GPUTest, TextureTestMixin } from '../../../gpu_test.js'; import { clamp } from '../../../util/math.js'; import { TexelView } from '../../../util/texture/texel_view.js'; @@ -165,6 +165,7 @@ u // .combine('component', ['color', 'alpha']). combine('srcFactor', kBlendFactors). combine('dstFactor', kBlendFactors). +beginSubcases(). combine('operation', kBlendOperations). filter((t) => { if (t.operation === 'min' || t.operation === 'max') { @@ -172,7 +173,6 @@ filter((t) => { } return true; }). -beginSubcases(). combine('srcColor', [{ r: 0.11, g: 0.61, b: 0.81, a: 0.44 }]). combine('dstColor', [ { r: 0.51, g: 0.22, b: 0.71, a: 0.33 }, @@ -318,9 +318,9 @@ struct Uniform { ); }); -const kBlendableFormats = kEncodableTextureFormats.filter((f) => { +const kBlendableFormats = kRegularTextureFormats.filter((f) => { const info = kTextureFormatInfo[f]; - return info.renderable && info.sampleType === 'float'; + return info.colorRender && info.color.type === 'float'; }); g.test('blending,formats'). diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth.spec.js index 12c88f8dcd..19008f0850 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth.spec.js @@ -467,13 +467,8 @@ fn((t) => { @vertex fn main( @builtin(vertex_index) VertexIndex : u32, @builtin(instance_index) InstanceIndex : u32) -> Output { - // TODO: remove workaround for Tint unary array access broke - var zv : array, 4> = array, 4>( - vec2(0.2, 0.2), - vec2(0.3, 0.3), - vec2(-0.1, -0.1), - vec2(1.1, 1.1)); - let z : f32 = zv[InstanceIndex].x; + let zv = array(0.2, 0.3, -0.1, 1.1); + let z = zv[InstanceIndex]; var output : Output; output.Position = vec4(0.5, 0.5, z, 1.0); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_bias.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_bias.spec.js index 4cae7f53eb..59e5f83bef 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_bias.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_bias.spec.js @@ -304,6 +304,12 @@ u // }] ) ). +beforeAllSubcases((t) => { + t.skipIf( + t.isCompatibility && t.params.biasClamp !== 0, + 'non zero depthBiasClamp is not supported in compatibility mode' + ); +}). fn((t) => { t.runDepthBiasTest('depth32float', t.params); }); @@ -346,6 +352,12 @@ combineWithParams([ }] ) ). +beforeAllSubcases((t) => { + t.skipIf( + t.isCompatibility && t.params.biasClamp !== 0, + 'non zero depthBiasClamp is not supported in compatibility mode' + ); +}). fn((t) => { const { format } = t.params; t.runDepthBiasTestFor24BitFormat(format, t.params); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_clip_clamp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_clip_clamp.spec.js index 28d639990d..4dc6b2d116 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_clip_clamp.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_clip_clamp.spec.js @@ -4,6 +4,7 @@ Tests for depth clipping, depth clamping (at various points in the pipeline), and maybe extended depth ranges as well. `;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { assert } from '../../../../common/util/util.js'; import { kDepthStencilFormats, kTextureFormatInfo } from '../../../format_info.js'; import { GPUTest } from '../../../gpu_test.js'; import { @@ -52,6 +53,7 @@ beforeAllSubcases((t) => { fn(async (t) => { const { format, unclippedDepth, writeDepth, multisampled } = t.params; const info = kTextureFormatInfo[format]; + assert(!!info.depth); /** Number of depth values to test for both vertex output and frag_depth output. */ const kNumDepthValues = 8; @@ -222,16 +224,16 @@ fn(async (t) => { undefined; const dsActual = - !multisampled && info.bytesPerBlock ? + !multisampled && info.depth.bytes ? t.device.createBuffer({ - size: kNumTestPoints * info.bytesPerBlock, + size: kNumTestPoints * info.depth.bytes, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ }) : undefined; const dsExpected = - !multisampled && info.bytesPerBlock ? + !multisampled && info.depth.bytes ? t.device.createBuffer({ - size: kNumTestPoints * info.bytesPerBlock, + size: kNumTestPoints * info.depth.bytes, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ }) : undefined; @@ -270,7 +272,9 @@ fn(async (t) => { pass.end(); } if (dsActual) { - enc.copyTextureToBuffer({ texture: dsTexture }, { buffer: dsActual }, [kNumTestPoints]); + enc.copyTextureToBuffer({ texture: dsTexture, aspect: 'depth-only' }, { buffer: dsActual }, [ + kNumTestPoints] + ); } { const clearValue = [0, 0, 0, 0]; // Will see this color if the check passed. @@ -302,7 +306,11 @@ fn(async (t) => { } enc.copyTextureToBuffer({ texture: checkTexture }, { buffer: checkBuffer }, [kNumTestPoints]); if (dsExpected) { - enc.copyTextureToBuffer({ texture: dsTexture }, { buffer: dsExpected }, [kNumTestPoints]); + enc.copyTextureToBuffer( + { texture: dsTexture, aspect: 'depth-only' }, + { buffer: dsExpected }, + [kNumTestPoints] + ); } t.device.queue.submit([enc.finish()]); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_copy.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_copy.js index 4025467306..08e878b458 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_copy.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_copy.js @@ -3,6 +3,7 @@ **/import { assert } from '../../../../../common/util/util.js';import { kTextureFormatInfo } from '../../../../format_info.js';import { virtualMipSize } from '../../../../util/texture/base.js'; + export const checkContentsByBufferCopy = ( t, params, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_ds_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_ds_test.js index 3a88f02a6a..a88c38e60e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_ds_test.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_ds_test.js @@ -4,6 +4,7 @@ import { virtualMipSize } from '../../../../util/texture/base.js'; + function makeFullscreenVertexModule(device) { return device.createShaderModule({ code: ` diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_sampling.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_sampling.js index 89a4a79e32..d55628a5bb 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_sampling.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_sampling.js @@ -8,6 +8,7 @@ import { '../../../../util/texture/texel_data.js'; + export const checkContentsBySampling = ( t, params, @@ -41,14 +42,20 @@ subresourceRange) => componentOrder[0].toLowerCase() : componentOrder.map((c) => c.toLowerCase()).join('') + '[i]'; - const _xd = '_' + params.dimension; + const viewDimension = + t.isCompatibility && params.dimension === '2d' && texture.depthOrArrayLayers > 1 ? + '2d-array' : + params.dimension; + const _xd = `_${viewDimension.replace('-', '_')}`; const _multisampled = params.sampleCount > 1 ? '_multisampled' : ''; const texelIndexExpression = - params.dimension === '2d' ? + viewDimension === '2d' ? 'vec2(GlobalInvocationID.xy)' : - params.dimension === '3d' ? + viewDimension === '2d-array' ? + 'vec2(GlobalInvocationID.xy), constants.layer' : + viewDimension === '3d' ? 'vec3(GlobalInvocationID.xyz)' : - params.dimension === '1d' ? + viewDimension === '1d' ? 'i32(GlobalInvocationID.x)' : unreachable(); const computePipeline = t.device.createComputePipeline({ @@ -58,7 +65,8 @@ subresourceRange) => module: t.device.createShaderModule({ code: ` struct Constants { - level : i32 + level : i32, + layer : i32, }; @group(0) @binding(0) var constants : Constants; @@ -90,10 +98,10 @@ subresourceRange) => for (const layer of layers) { const ubo = t.device.createBuffer({ mappedAtCreation: true, - size: 4, + size: 8, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }); - new Int32Array(ubo.getMappedRange(), 0, 1)[0] = level; + new Int32Array(ubo.getMappedRange()).set([level, layer]); ubo.unmap(); const byteLength = @@ -104,6 +112,14 @@ subresourceRange) => }); t.trackForCleanup(resultBuffer); + const viewDescriptor = { + ...(!t.isCompatibility && { + baseArrayLayer: layer, + arrayLayerCount: 1 + }), + dimension: viewDimension + }; + const bindGroup = t.device.createBindGroup({ layout: computePipeline.getBindGroupLayout(0), entries: [ @@ -113,11 +129,7 @@ subresourceRange) => }, { binding: 1, - resource: texture.createView({ - baseArrayLayer: layer, - arrayLayerCount: 1, - dimension: params.dimension - }) + resource: texture.createView(viewDescriptor) }, { binding: 3, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/texture_zero_init_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/texture_zero_init_test.js new file mode 100644 index 0000000000..7e2c1f1cff --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/texture_zero_init_test.js @@ -0,0 +1,538 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kUnitCaseParamsBuilder } from + +'../../../../../common/framework/params_builder.js'; +import { assert, unreachable } from '../../../../../common/util/util.js'; +import { kTextureAspects, kTextureDimensions } from '../../../../capability_info.js'; +import { GPUConst } from '../../../../constants.js'; +import { + kTextureFormatInfo, + kUncompressedTextureFormats, + textureDimensionAndFormatCompatible } from + + +'../../../../format_info.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { virtualMipSize } from '../../../../util/texture/base.js'; +import { createTextureUploadBuffer } from '../../../../util/texture/layout.js'; +import { SubresourceRange } from '../../../../util/texture/subresource.js'; +import { + + kTexelRepresentationInfo } from +'../../../../util/texture/texel_data.js'; + +export let UninitializeMethod = /*#__PURE__*/function (UninitializeMethod) {UninitializeMethod["Creation"] = "Creation";UninitializeMethod["StoreOpClear"] = "StoreOpClear";return UninitializeMethod;}({}); + +// The texture was rendered to with GPUStoreOp "clear" + +const kUninitializeMethods = Object.keys(UninitializeMethod); + +export let ReadMethod = /*#__PURE__*/function (ReadMethod) {ReadMethod["Sample"] = "Sample";ReadMethod["CopyToBuffer"] = "CopyToBuffer";ReadMethod["CopyToTexture"] = "CopyToTexture";ReadMethod["DepthTest"] = "DepthTest";ReadMethod["StencilTest"] = "StencilTest";ReadMethod["ColorBlending"] = "ColorBlending";ReadMethod["Storage"] = "Storage";return ReadMethod;}({}); + + + + + + +// Read the texture as a storage texture + + +// Test with these mip level counts + +const kMipLevelCounts = [1, 5]; + +// For each mip level count, define the mip ranges to leave uninitialized. +const kUninitializedMipRangesToTest = { + 1: [{ begin: 0, end: 1 }], // Test the only mip + 5: [ + { begin: 0, end: 2 }, + { begin: 3, end: 4 }] + // Test a range and a single mip +}; + +// Test with these sample counts. +const kSampleCounts = [1, 4]; + +// Test with these layer counts. + + +// For each layer count, define the layers to leave uninitialized. +const kUninitializedLayerRangesToTest = { + 1: [{ begin: 0, end: 1 }], // Test the only layer + 7: [ + { begin: 2, end: 4 }, + { begin: 6, end: 7 }] + // Test a range and a single layer +}; + +// Enums to abstract over color / depth / stencil values in textures. Depending on the texture format, +// the data for each value may have a different representation. These enums are converted to a +// representation such that their values can be compared. ex.) An integer is needed to upload to an +// unsigned normalized format, but its value is read as a float in the shader. +export let InitializedState = /*#__PURE__*/function (InitializedState) {InitializedState[InitializedState["Canary"] = 0] = "Canary";InitializedState[InitializedState["Zero"] = 1] = "Zero";return InitializedState;}({}); + +// We check that uninitialized subresources are in this state when read back. + + +const initializedStateAsFloat = { + [InitializedState.Zero]: 0, + [InitializedState.Canary]: 1 +}; + +const initializedStateAsUint = { + [InitializedState.Zero]: 0, + [InitializedState.Canary]: 1 +}; + +const initializedStateAsSint = { + [InitializedState.Zero]: 0, + [InitializedState.Canary]: -1 +}; + +function initializedStateAsColor( +state, +format) +{ + let value; + if (format.indexOf('uint') !== -1) { + value = initializedStateAsUint[state]; + } else if (format.indexOf('sint') !== -1) { + value = initializedStateAsSint[state]; + } else { + value = initializedStateAsFloat[state]; + } + return [value, value, value, value]; +} + +const initializedStateAsDepth = { + [InitializedState.Zero]: 0, + [InitializedState.Canary]: 0.8 +}; + +const initializedStateAsStencil = { + [InitializedState.Zero]: 0, + [InitializedState.Canary]: 42 +}; + +function allAspectsCopyDst(info) { + return ( + (!info.color || info.color.copyDst) && ( + !info.depth || info.depth.copyDst) && ( + !info.stencil || info.stencil.copyDst)); + +} + +export function getRequiredTextureUsage( +format, +sampleCount, +uninitializeMethod, +readMethod) +{ + let usage = GPUConst.TextureUsage.COPY_DST; + + switch (uninitializeMethod) { + case UninitializeMethod.Creation: + break; + case UninitializeMethod.StoreOpClear: + usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT; + break; + default: + unreachable(); + } + + switch (readMethod) { + case ReadMethod.CopyToBuffer: + case ReadMethod.CopyToTexture: + usage |= GPUConst.TextureUsage.COPY_SRC; + break; + case ReadMethod.Sample: + usage |= GPUConst.TextureUsage.TEXTURE_BINDING; + break; + case ReadMethod.Storage: + usage |= GPUConst.TextureUsage.STORAGE_BINDING; + break; + case ReadMethod.DepthTest: + case ReadMethod.StencilTest: + case ReadMethod.ColorBlending: + usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT; + break; + default: + unreachable(); + } + + if (sampleCount > 1) { + // Copies to multisampled textures are not allowed. We need OutputAttachment to initialize + // canary data in multisampled textures. + usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT; + } + + const info = kTextureFormatInfo[format]; + if (!allAspectsCopyDst(info)) { + // Copies are not possible. We need OutputAttachment to initialize + // canary data. + if (info.color) assert(!!info.colorRender, 'not implemented for non-renderable color'); + usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT; + } + + return usage; +} + +export class TextureZeroInitTest extends GPUTest { + + + + constructor(sharedState, rec, params) { + super(sharedState, rec, params); + this.p = params; + + const stateToTexelComponents = (state) => { + const [R, G, B, A] = initializedStateAsColor(state, this.p.format); + return { + R, + G, + B, + A, + Depth: initializedStateAsDepth[state], + Stencil: initializedStateAsStencil[state] + }; + }; + + this.stateToTexelComponents = { + [InitializedState.Zero]: stateToTexelComponents(InitializedState.Zero), + [InitializedState.Canary]: stateToTexelComponents(InitializedState.Canary) + }; + } + + get textureWidth() { + let width = 1 << this.p.mipLevelCount; + if (this.p.nonPowerOfTwo) { + width = 2 * width - 1; + } + return width; + } + + get textureHeight() { + if (this.p.dimension === '1d') { + return 1; + } + + let height = 1 << this.p.mipLevelCount; + if (this.p.nonPowerOfTwo) { + height = 2 * height - 1; + } + return height; + } + + get textureDepth() { + return this.p.dimension === '3d' ? 11 : 1; + } + + get textureDepthOrArrayLayers() { + return this.p.dimension === '2d' ? this.p.layerCount : this.textureDepth; + } + + // Used to iterate subresources and check that their uninitialized contents are zero when accessed + *iterateUninitializedSubresources() { + for (const mipRange of kUninitializedMipRangesToTest[this.p.mipLevelCount]) { + for (const layerRange of kUninitializedLayerRangesToTest[this.p.layerCount]) { + yield new SubresourceRange({ mipRange, layerRange }); + } + } + } + + // Used to iterate and initialize other subresources not checked for zero-initialization. + // Zero-initialization of uninitialized subresources should not have side effects on already + // initialized subresources. + *iterateInitializedSubresources() { + const uninitialized = new Array(this.p.mipLevelCount); + for (let level = 0; level < uninitialized.length; ++level) { + uninitialized[level] = new Array(this.p.layerCount); + } + for (const subresources of this.iterateUninitializedSubresources()) { + for (const { level, layer } of subresources.each()) { + uninitialized[level][layer] = true; + } + } + for (let level = 0; level < uninitialized.length; ++level) { + for (let layer = 0; layer < uninitialized[level].length; ++layer) { + if (!uninitialized[level][layer]) { + yield new SubresourceRange({ + mipRange: { begin: level, count: 1 }, + layerRange: { begin: layer, count: 1 } + }); + } + } + } + } + + *generateTextureViewDescriptorsForRendering( + aspect, + subresourceRange) + { + const viewDescriptor = { + dimension: '2d', + aspect + }; + + if (subresourceRange === undefined) { + return viewDescriptor; + } + + for (const { level, layer } of subresourceRange.each()) { + yield { + ...viewDescriptor, + baseMipLevel: level, + mipLevelCount: 1, + baseArrayLayer: layer, + arrayLayerCount: 1 + }; + } + } + + initializeWithStoreOp( + state, + texture, + subresourceRange) + { + const commandEncoder = this.device.createCommandEncoder(); + commandEncoder.pushDebugGroup('initializeWithStoreOp'); + + for (const viewDescriptor of this.generateTextureViewDescriptorsForRendering( + 'all', + subresourceRange + )) { + if (kTextureFormatInfo[this.p.format].color) { + commandEncoder. + beginRenderPass({ + colorAttachments: [ + { + view: texture.createView(viewDescriptor), + storeOp: 'store', + clearValue: initializedStateAsColor(state, this.p.format), + loadOp: 'clear' + }] + + }). + end(); + } else { + const depthStencilAttachment = { + view: texture.createView(viewDescriptor) + }; + if (kTextureFormatInfo[this.p.format].depth) { + depthStencilAttachment.depthClearValue = initializedStateAsDepth[state]; + depthStencilAttachment.depthLoadOp = 'clear'; + depthStencilAttachment.depthStoreOp = 'store'; + } + if (kTextureFormatInfo[this.p.format].stencil) { + depthStencilAttachment.stencilClearValue = initializedStateAsStencil[state]; + depthStencilAttachment.stencilLoadOp = 'clear'; + depthStencilAttachment.stencilStoreOp = 'store'; + } + commandEncoder. + beginRenderPass({ + colorAttachments: [], + depthStencilAttachment + }). + end(); + } + } + + commandEncoder.popDebugGroup(); + this.queue.submit([commandEncoder.finish()]); + } + + initializeWithCopy( + texture, + state, + subresourceRange) + { + assert(this.p.format in kTextureFormatInfo); + const format = this.p.format; + + const firstSubresource = subresourceRange.each().next().value; + assert(typeof firstSubresource !== 'undefined'); + + const [largestWidth, largestHeight, largestDepth] = virtualMipSize( + this.p.dimension, + [this.textureWidth, this.textureHeight, this.textureDepth], + firstSubresource.level + ); + + const rep = kTexelRepresentationInfo[format]; + const texelData = new Uint8Array(rep.pack(rep.encode(this.stateToTexelComponents[state]))); + const { buffer, bytesPerRow, rowsPerImage } = createTextureUploadBuffer( + texelData, + this.device, + format, + this.p.dimension, + [largestWidth, largestHeight, largestDepth] + ); + + const commandEncoder = this.device.createCommandEncoder(); + + for (const { level, layer } of subresourceRange.each()) { + const [width, height, depth] = virtualMipSize( + this.p.dimension, + [this.textureWidth, this.textureHeight, this.textureDepth], + level + ); + + commandEncoder.copyBufferToTexture( + { + buffer, + bytesPerRow, + rowsPerImage + }, + { texture, mipLevel: level, origin: { x: 0, y: 0, z: layer } }, + { width, height, depthOrArrayLayers: depth } + ); + } + this.queue.submit([commandEncoder.finish()]); + buffer.destroy(); + } + + initializeTexture( + texture, + state, + subresourceRange) + { + const info = kTextureFormatInfo[this.p.format]; + if (this.p.sampleCount > 1 || !allAspectsCopyDst(info)) { + // Copies to multisampled textures not yet specified. + // Use a storeOp for now. + if (info.color) assert(!!info.colorRender, 'not implemented for non-renderable color'); + this.initializeWithStoreOp(state, texture, subresourceRange); + } else { + this.initializeWithCopy(texture, state, subresourceRange); + } + } + + discardTexture(texture, subresourceRange) { + const commandEncoder = this.device.createCommandEncoder(); + commandEncoder.pushDebugGroup('discardTexture'); + + for (const desc of this.generateTextureViewDescriptorsForRendering('all', subresourceRange)) { + if (kTextureFormatInfo[this.p.format].color) { + commandEncoder. + beginRenderPass({ + colorAttachments: [ + { + view: texture.createView(desc), + storeOp: 'discard', + loadOp: 'load' + }] + + }). + end(); + } else { + const depthStencilAttachment = { + view: texture.createView(desc) + }; + if (kTextureFormatInfo[this.p.format].depth) { + depthStencilAttachment.depthLoadOp = 'load'; + depthStencilAttachment.depthStoreOp = 'discard'; + } + if (kTextureFormatInfo[this.p.format].stencil) { + depthStencilAttachment.stencilLoadOp = 'load'; + depthStencilAttachment.stencilStoreOp = 'discard'; + } + commandEncoder. + beginRenderPass({ + colorAttachments: [], + depthStencilAttachment + }). + end(); + } + } + + commandEncoder.popDebugGroup(); + this.queue.submit([commandEncoder.finish()]); + } +} + +export const kTestParams = kUnitCaseParamsBuilder. +combine('dimension', kTextureDimensions). +combine('readMethod', [ +ReadMethod.CopyToBuffer, +ReadMethod.CopyToTexture, +ReadMethod.Sample, +ReadMethod.DepthTest, +ReadMethod.StencilTest] +) +// [3] compressed formats +.combine('format', kUncompressedTextureFormats). +filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format)). +beginSubcases(). +combine('aspect', kTextureAspects). +unless(({ readMethod, format, aspect }) => { + const info = kTextureFormatInfo[format]; + return ( + readMethod === ReadMethod.DepthTest && (!info.depth || aspect === 'stencil-only') || + readMethod === ReadMethod.StencilTest && (!info.stencil || aspect === 'depth-only') || + readMethod === ReadMethod.ColorBlending && !info.color || + // [1]: Test with depth/stencil sampling + readMethod === ReadMethod.Sample && (!!info.depth || !!info.stencil) || + aspect === 'depth-only' && !info.depth || + aspect === 'stencil-only' && !info.stencil || + aspect === 'all' && !!info.depth && !!info.stencil || + // Cannot copy from a packed depth format. + // [2]: Test copying out of the stencil aspect. + (readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture) && ( + format === 'depth24plus' || format === 'depth24plus-stencil8')); + +}). +combine('mipLevelCount', kMipLevelCounts) +// 1D texture can only have a single mip level +.unless((p) => p.dimension === '1d' && p.mipLevelCount !== 1). +combine('sampleCount', kSampleCounts). +unless( + ({ readMethod, sampleCount }) => + // We can only read from multisampled textures by sampling. + sampleCount > 1 && ( + readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture) +) +// Multisampled textures may only have one mip +.unless(({ sampleCount, mipLevelCount }) => sampleCount > 1 && mipLevelCount > 1). +combine('uninitializeMethod', kUninitializeMethods). +unless(({ dimension, readMethod, uninitializeMethod, format, sampleCount }) => { + const formatInfo = kTextureFormatInfo[format]; + return ( + dimension !== '2d' && ( + sampleCount > 1 || + !!formatInfo.depth || + !!formatInfo.stencil || + readMethod === ReadMethod.DepthTest || + readMethod === ReadMethod.StencilTest || + readMethod === ReadMethod.ColorBlending || + uninitializeMethod === UninitializeMethod.StoreOpClear)); + +}). +expandWithParams(function* ({ dimension }) { + switch (dimension) { + case '2d': + yield { layerCount: 1 }; + yield { layerCount: 7 }; + break; + case '1d': + case '3d': + yield { layerCount: 1 }; + break; + } +}) +// Multisampled 3D / 2D array textures not supported. +.unless(({ sampleCount, layerCount }) => sampleCount > 1 && layerCount > 1). +unless(({ format, sampleCount, uninitializeMethod, readMethod }) => { + const usage = getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMethod); + const info = kTextureFormatInfo[format]; + + return ( + (usage & GPUConst.TextureUsage.RENDER_ATTACHMENT) !== 0 && + info.color && + !info.colorRender || + (usage & GPUConst.TextureUsage.STORAGE_BINDING) !== 0 && !info.color?.storage || + sampleCount > 1 && !info.multisample); + +}). +combine('nonPowerOfTwo', [false, true]). +combine('canaryOnCreation', [false, true]); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/texture_zero.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/texture_zero.spec.js index d7e83601c1..574a997516 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/texture_zero.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/texture_zero.spec.js @@ -7,550 +7,9 @@ TODO: - test by sampling depth/stencil [1] - test by copying out of stencil [2] - test compressed texture formats [3] -`; // MAINTENANCE_TODO: This is a test file, it probably shouldn't export anything. -// Everything that's exported should be moved to another file. - - -import { - kUnitCaseParamsBuilder } from - -'../../../../common/framework/params_builder.js'; -import { makeTestGroup } from '../../../../common/framework/test_group.js'; -import { assert, unreachable } from '../../../../common/util/util.js'; -import { kTextureAspects, kTextureDimensions } from '../../../capability_info.js'; -import { GPUConst } from '../../../constants.js'; -import { - kTextureFormatInfo, - kUncompressedTextureFormats, - textureDimensionAndFormatCompatible } from - - -'../../../format_info.js'; -import { GPUTest } from '../../../gpu_test.js'; -import { virtualMipSize } from '../../../util/texture/base.js'; -import { createTextureUploadBuffer } from '../../../util/texture/layout.js'; -import { SubresourceRange } from '../../../util/texture/subresource.js'; -import { kTexelRepresentationInfo } from '../../../util/texture/texel_data.js'; - -export let UninitializeMethod = /*#__PURE__*/function (UninitializeMethod) {UninitializeMethod["Creation"] = "Creation";UninitializeMethod["StoreOpClear"] = "StoreOpClear";return UninitializeMethod;}({}); - -// The texture was rendered to with GPUStoreOp "clear" - -const kUninitializeMethods = Object.keys(UninitializeMethod); - -export let ReadMethod = /*#__PURE__*/function (ReadMethod) {ReadMethod["Sample"] = "Sample";ReadMethod["CopyToBuffer"] = "CopyToBuffer";ReadMethod["CopyToTexture"] = "CopyToTexture";ReadMethod["DepthTest"] = "DepthTest";ReadMethod["StencilTest"] = "StencilTest";ReadMethod["ColorBlending"] = "ColorBlending";ReadMethod["Storage"] = "Storage";return ReadMethod;}({}); - - - - - - -// Read the texture as a storage texture - - -// Test with these mip level counts - -const kMipLevelCounts = [1, 5]; - -// For each mip level count, define the mip ranges to leave uninitialized. -const kUninitializedMipRangesToTest = { - 1: [{ begin: 0, end: 1 }], // Test the only mip - 5: [ - { begin: 0, end: 2 }, - { begin: 3, end: 4 }] - // Test a range and a single mip -}; - -// Test with these sample counts. -const kSampleCounts = [1, 4]; - -// Test with these layer counts. - - -// For each layer count, define the layers to leave uninitialized. -const kUninitializedLayerRangesToTest = { - 1: [{ begin: 0, end: 1 }], // Test the only layer - 7: [ - { begin: 2, end: 4 }, - { begin: 6, end: 7 }] - // Test a range and a single layer -}; - -// Enums to abstract over color / depth / stencil values in textures. Depending on the texture format, -// the data for each value may have a different representation. These enums are converted to a -// representation such that their values can be compared. ex.) An integer is needed to upload to an -// unsigned normalized format, but its value is read as a float in the shader. -export let InitializedState = /*#__PURE__*/function (InitializedState) {InitializedState[InitializedState["Canary"] = 0] = "Canary";InitializedState[InitializedState["Zero"] = 1] = "Zero";return InitializedState;}({}); - -// We check that uninitialized subresources are in this state when read back. - - -const initializedStateAsFloat = { - [InitializedState.Zero]: 0, - [InitializedState.Canary]: 1 -}; - -const initializedStateAsUint = { - [InitializedState.Zero]: 0, - [InitializedState.Canary]: 1 -}; - -const initializedStateAsSint = { - [InitializedState.Zero]: 0, - [InitializedState.Canary]: -1 -}; - -function initializedStateAsColor( -state, -format) -{ - let value; - if (format.indexOf('uint') !== -1) { - value = initializedStateAsUint[state]; - } else if (format.indexOf('sint') !== -1) { - value = initializedStateAsSint[state]; - } else { - value = initializedStateAsFloat[state]; - } - return [value, value, value, value]; -} - -const initializedStateAsDepth = { - [InitializedState.Zero]: 0, - [InitializedState.Canary]: 0.8 -}; - -const initializedStateAsStencil = { - [InitializedState.Zero]: 0, - [InitializedState.Canary]: 42 -}; - -function getRequiredTextureUsage( -format, -sampleCount, -uninitializeMethod, -readMethod) -{ - let usage = GPUConst.TextureUsage.COPY_DST; - - switch (uninitializeMethod) { - case UninitializeMethod.Creation: - break; - case UninitializeMethod.StoreOpClear: - usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT; - break; - default: - unreachable(); - } - - switch (readMethod) { - case ReadMethod.CopyToBuffer: - case ReadMethod.CopyToTexture: - usage |= GPUConst.TextureUsage.COPY_SRC; - break; - case ReadMethod.Sample: - usage |= GPUConst.TextureUsage.TEXTURE_BINDING; - break; - case ReadMethod.Storage: - usage |= GPUConst.TextureUsage.STORAGE_BINDING; - break; - case ReadMethod.DepthTest: - case ReadMethod.StencilTest: - case ReadMethod.ColorBlending: - usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT; - break; - default: - unreachable(); - } - - if (sampleCount > 1) { - // Copies to multisampled textures are not allowed. We need OutputAttachment to initialize - // canary data in multisampled textures. - usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT; - } - - if (!kTextureFormatInfo[format].copyDst) { - // Copies are not possible. We need OutputAttachment to initialize - // canary data. - assert(kTextureFormatInfo[format].renderable); - usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT; - } - - return usage; -} - -export class TextureZeroInitTest extends GPUTest { - - - - constructor(sharedState, rec, params) { - super(sharedState, rec, params); - this.p = params; - - const stateToTexelComponents = (state) => { - const [R, G, B, A] = initializedStateAsColor(state, this.p.format); - return { - R, - G, - B, - A, - Depth: initializedStateAsDepth[state], - Stencil: initializedStateAsStencil[state] - }; - }; - - this.stateToTexelComponents = { - [InitializedState.Zero]: stateToTexelComponents(InitializedState.Zero), - [InitializedState.Canary]: stateToTexelComponents(InitializedState.Canary) - }; - } - - get textureWidth() { - let width = 1 << this.p.mipLevelCount; - if (this.p.nonPowerOfTwo) { - width = 2 * width - 1; - } - return width; - } - - get textureHeight() { - if (this.p.dimension === '1d') { - return 1; - } - - let height = 1 << this.p.mipLevelCount; - if (this.p.nonPowerOfTwo) { - height = 2 * height - 1; - } - return height; - } - - get textureDepth() { - return this.p.dimension === '3d' ? 11 : 1; - } - - get textureDepthOrArrayLayers() { - return this.p.dimension === '2d' ? this.p.layerCount : this.textureDepth; - } - - // Used to iterate subresources and check that their uninitialized contents are zero when accessed - *iterateUninitializedSubresources() { - for (const mipRange of kUninitializedMipRangesToTest[this.p.mipLevelCount]) { - for (const layerRange of kUninitializedLayerRangesToTest[this.p.layerCount]) { - yield new SubresourceRange({ mipRange, layerRange }); - } - } - } - - // Used to iterate and initialize other subresources not checked for zero-initialization. - // Zero-initialization of uninitialized subresources should not have side effects on already - // initialized subresources. - *iterateInitializedSubresources() { - const uninitialized = new Array(this.p.mipLevelCount); - for (let level = 0; level < uninitialized.length; ++level) { - uninitialized[level] = new Array(this.p.layerCount); - } - for (const subresources of this.iterateUninitializedSubresources()) { - for (const { level, layer } of subresources.each()) { - uninitialized[level][layer] = true; - } - } - for (let level = 0; level < uninitialized.length; ++level) { - for (let layer = 0; layer < uninitialized[level].length; ++layer) { - if (!uninitialized[level][layer]) { - yield new SubresourceRange({ - mipRange: { begin: level, count: 1 }, - layerRange: { begin: layer, count: 1 } - }); - } - } - } - } - - *generateTextureViewDescriptorsForRendering( - aspect, - subresourceRange) - { - const viewDescriptor = { - dimension: '2d', - aspect - }; - - if (subresourceRange === undefined) { - return viewDescriptor; - } - - for (const { level, layer } of subresourceRange.each()) { - yield { - ...viewDescriptor, - baseMipLevel: level, - mipLevelCount: 1, - baseArrayLayer: layer, - arrayLayerCount: 1 - }; - } - } - - initializeWithStoreOp( - state, - texture, - subresourceRange) - { - const commandEncoder = this.device.createCommandEncoder(); - commandEncoder.pushDebugGroup('initializeWithStoreOp'); - - for (const viewDescriptor of this.generateTextureViewDescriptorsForRendering( - 'all', - subresourceRange - )) { - if (kTextureFormatInfo[this.p.format].color) { - commandEncoder. - beginRenderPass({ - colorAttachments: [ - { - view: texture.createView(viewDescriptor), - storeOp: 'store', - clearValue: initializedStateAsColor(state, this.p.format), - loadOp: 'clear' - }] - - }). - end(); - } else { - const depthStencilAttachment = { - view: texture.createView(viewDescriptor) - }; - if (kTextureFormatInfo[this.p.format].depth) { - depthStencilAttachment.depthClearValue = initializedStateAsDepth[state]; - depthStencilAttachment.depthLoadOp = 'clear'; - depthStencilAttachment.depthStoreOp = 'store'; - } - if (kTextureFormatInfo[this.p.format].stencil) { - depthStencilAttachment.stencilClearValue = initializedStateAsStencil[state]; - depthStencilAttachment.stencilLoadOp = 'clear'; - depthStencilAttachment.stencilStoreOp = 'store'; - } - commandEncoder. - beginRenderPass({ - colorAttachments: [], - depthStencilAttachment - }). - end(); - } - } - - commandEncoder.popDebugGroup(); - this.queue.submit([commandEncoder.finish()]); - } - - initializeWithCopy( - texture, - state, - subresourceRange) - { - assert(this.p.format in kTextureFormatInfo); - const format = this.p.format; - - const firstSubresource = subresourceRange.each().next().value; - assert(typeof firstSubresource !== 'undefined'); - - const [largestWidth, largestHeight, largestDepth] = virtualMipSize( - this.p.dimension, - [this.textureWidth, this.textureHeight, this.textureDepth], - firstSubresource.level - ); - - const rep = kTexelRepresentationInfo[format]; - const texelData = new Uint8Array(rep.pack(rep.encode(this.stateToTexelComponents[state]))); - const { buffer, bytesPerRow, rowsPerImage } = createTextureUploadBuffer( - texelData, - this.device, - format, - this.p.dimension, - [largestWidth, largestHeight, largestDepth] - ); - - const commandEncoder = this.device.createCommandEncoder(); - - for (const { level, layer } of subresourceRange.each()) { - const [width, height, depth] = virtualMipSize( - this.p.dimension, - [this.textureWidth, this.textureHeight, this.textureDepth], - level - ); - - commandEncoder.copyBufferToTexture( - { - buffer, - bytesPerRow, - rowsPerImage - }, - { texture, mipLevel: level, origin: { x: 0, y: 0, z: layer } }, - { width, height, depthOrArrayLayers: depth } - ); - } - this.queue.submit([commandEncoder.finish()]); - buffer.destroy(); - } - - initializeTexture( - texture, - state, - subresourceRange) - { - if (this.p.sampleCount > 1 || !kTextureFormatInfo[this.p.format].copyDst) { - // Copies to multisampled textures not yet specified. - // Use a storeOp for now. - assert(kTextureFormatInfo[this.p.format].renderable); - this.initializeWithStoreOp(state, texture, subresourceRange); - } else { - this.initializeWithCopy(texture, state, subresourceRange); - } - } - - discardTexture(texture, subresourceRange) { - const commandEncoder = this.device.createCommandEncoder(); - commandEncoder.pushDebugGroup('discardTexture'); - - for (const desc of this.generateTextureViewDescriptorsForRendering('all', subresourceRange)) { - if (kTextureFormatInfo[this.p.format].color) { - commandEncoder. - beginRenderPass({ - colorAttachments: [ - { - view: texture.createView(desc), - storeOp: 'discard', - loadOp: 'load' - }] - - }). - end(); - } else { - const depthStencilAttachment = { - view: texture.createView(desc) - }; - if (kTextureFormatInfo[this.p.format].depth) { - depthStencilAttachment.depthLoadOp = 'load'; - depthStencilAttachment.depthStoreOp = 'discard'; - } - if (kTextureFormatInfo[this.p.format].stencil) { - depthStencilAttachment.stencilLoadOp = 'load'; - depthStencilAttachment.stencilStoreOp = 'discard'; - } - commandEncoder. - beginRenderPass({ - colorAttachments: [], - depthStencilAttachment - }). - end(); - } - } - - commandEncoder.popDebugGroup(); - this.queue.submit([commandEncoder.finish()]); - } -} - -const kTestParams = kUnitCaseParamsBuilder. -combine('dimension', kTextureDimensions). -combine('readMethod', [ -ReadMethod.CopyToBuffer, -ReadMethod.CopyToTexture, -ReadMethod.Sample, -ReadMethod.DepthTest, -ReadMethod.StencilTest] -) -// [3] compressed formats -.combine('format', kUncompressedTextureFormats). -filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format)). -beginSubcases(). -combine('aspect', kTextureAspects). -unless(({ readMethod, format, aspect }) => { - const info = kTextureFormatInfo[format]; - return ( - readMethod === ReadMethod.DepthTest && (!info.depth || aspect === 'stencil-only') || - readMethod === ReadMethod.StencilTest && (!info.stencil || aspect === 'depth-only') || - readMethod === ReadMethod.ColorBlending && !info.color || - // [1]: Test with depth/stencil sampling - readMethod === ReadMethod.Sample && (!!info.depth || !!info.stencil) || - aspect === 'depth-only' && !info.depth || - aspect === 'stencil-only' && !info.stencil || - aspect === 'all' && !!info.depth && !!info.stencil || - // Cannot copy from a packed depth format. - // [2]: Test copying out of the stencil aspect. - (readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture) && ( - format === 'depth24plus' || format === 'depth24plus-stencil8')); - -}). -combine('mipLevelCount', kMipLevelCounts) -// 1D texture can only have a single mip level -.unless((p) => p.dimension === '1d' && p.mipLevelCount !== 1). -combine('sampleCount', kSampleCounts). -unless( - ({ readMethod, sampleCount }) => - // We can only read from multisampled textures by sampling. - sampleCount > 1 && ( - readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture) -) -// Multisampled textures may only have one mip -.unless(({ sampleCount, mipLevelCount }) => sampleCount > 1 && mipLevelCount > 1). -combine('uninitializeMethod', kUninitializeMethods). -unless(({ dimension, readMethod, uninitializeMethod, format, sampleCount }) => { - const formatInfo = kTextureFormatInfo[format]; - return ( - dimension !== '2d' && ( - sampleCount > 1 || - !!formatInfo.depth || - !!formatInfo.stencil || - readMethod === ReadMethod.DepthTest || - readMethod === ReadMethod.StencilTest || - readMethod === ReadMethod.ColorBlending || - uninitializeMethod === UninitializeMethod.StoreOpClear)); - -}). -expandWithParams(function* ({ dimension }) { - switch (dimension) { - case '2d': - yield { layerCount: 1 }; - yield { layerCount: 7 }; - break; - case '1d': - case '3d': - yield { layerCount: 1 }; - break; - } -}) -// Multisampled 3D / 2D array textures not supported. -.unless(({ sampleCount, layerCount }) => sampleCount > 1 && layerCount > 1). -unless(({ format, sampleCount, uninitializeMethod, readMethod }) => { - const usage = getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMethod); - const info = kTextureFormatInfo[format]; - - return ( - (usage & GPUConst.TextureUsage.RENDER_ATTACHMENT) !== 0 && !info.renderable || - (usage & GPUConst.TextureUsage.STORAGE_BINDING) !== 0 && !info.color?.storage || - sampleCount > 1 && !info.multisample); - -}). -combine('nonPowerOfTwo', [false, true]). -combine('canaryOnCreation', [false, true]). -filter(({ canaryOnCreation, format }) => { - // We can only initialize the texture if it's encodable or renderable. - const canInitialize = format in kTextureFormatInfo || kTextureFormatInfo[format].renderable; - - // Filter out cases where we want canary values but can't initialize. - return !canaryOnCreation || canInitialize; -}); - - - - - - - - - - +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { unreachable } from '../../../../common/util/util.js'; +import { kTextureFormatInfo } from '../../../format_info.js'; import { checkContentsByBufferCopy, checkContentsByTextureCopy } from './check_texture/by_copy.js'; import { @@ -558,6 +17,15 @@ import { checkContentsByStencilTest } from './check_texture/by_ds_test.js'; import { checkContentsBySampling } from './check_texture/by_sampling.js'; +import { + getRequiredTextureUsage, + + + TextureZeroInitTest, + kTestParams, + UninitializeMethod, + InitializedState } from +'./check_texture/texture_zero_init_test.js'; const checkContentsImpl = { Sample: checkContentsBySampling, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/shader_module/compilation_info.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/shader_module/compilation_info.spec.js index 9f9a1fcba0..ee64ed6065 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/shader_module/compilation_info.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/shader_module/compilation_info.spec.js @@ -63,6 +63,17 @@ const kInvalidShaderSources = [ // Expected Error: unknown function 'unknown' return unknown(0.0, 0.0, 0.0, 1.0); }` +}, +{ + valid: false, + name: 'unicode-multi-byte-characters', + _errorLine: 1, + // This shader is simplistic enough to always result in the same error position. + // Generally, various backends may choose to report the error at different positions within the + // line, so it's difficult to meaningfully validate them. + _errorLinePos: 19, + _code: `/*🐈🐈🐈🐈🐈🐈🐈*/? +// Expected Error: invalid character found` }]; @@ -174,7 +185,7 @@ beginSubcases(). combine('sourceMapName', kSourceMapsKeys) ). fn(async (t) => { - const { _code, _errorLine, sourceMapName } = t.params; + const { _code, _errorLine, _errorLinePos, sourceMapName } = t.params; const shaderModule = t.expectGPUError('validation', () => { const sourceMap = kSourceMaps[sourceMapName]; @@ -191,14 +202,22 @@ fn(async (t) => { // If a line is reported, it should point at the correct line (1-based). t.expect( message.lineNum === 0 === (message.linePos === 0), - "GPUCompilationMessages that don't report a line number should not report a line position." + `Got message.lineNum ${message.lineNum}, .linePos ${message.linePos}, but GPUCompilationMessage should specify both or neither` ); - if (message.lineNum === 0 || message.lineNum === _errorLine) { + if (message.lineNum === 0) { foundAppropriateError = true; + break; + } - // Various backends may choose to report the error at different positions within the line, - // so it's difficult to meaningfully validate them. + if (message.lineNum === _errorLine) { + foundAppropriateError = true; + if (_errorLinePos !== undefined) { + t.expect( + message.linePos === _errorLinePos, + `Got message.linePos ${message.linePos}, expected ${_errorLinePos}` + ); + } break; } } @@ -239,10 +258,9 @@ fn(async (t) => { for (const message of info.messages) { // Any offsets and lengths should reference valid spans of the shader code. - t.expect(message.offset <= _code.length, 'Message offset should be within the shader source'); t.expect( - message.offset + message.length <= _code.length, - 'Message offset and length should be within the shader source' + message.offset <= _code.length && message.offset + message.length <= _code.length, + 'message.offset and .length should be within the shader source' ); // If a valid line number and position are given, the offset should point the the same @@ -255,9 +273,10 @@ fn(async (t) => { lineOffset += 1; } + const expectedOffset = lineOffset + message.linePos - 1; t.expect( - message.offset === lineOffset + message.linePos - 1, - 'lineNum and linePos should point to the same location as offset' + message.offset === expectedOffset, + `message.lineNum (${message.lineNum}) and .linePos (${message.linePos}) point to a different offset (${lineOffset} + ${message.linePos} - 1 = ${expectedOffset}) than .offset (${message.offset})` ); } } diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/storage_texture/read_only.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/storage_texture/read_only.spec.js new file mode 100644 index 0000000000..ebf33cca31 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/storage_texture/read_only.spec.js @@ -0,0 +1,626 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Tests for the behavior of read-only storage textures. + +TODO: +- Test mipmap level > 0 +- Test resource usage transitions with read-only storage textures +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { unreachable, assert } from '../../../../common/util/util.js'; +import { Float16Array } from '../../../../external/petamoriken/float16/float16.js'; +import { kTextureDimensions } from '../../../capability_info.js'; +import { + + kColorTextureFormats, + kTextureFormatInfo } from +'../../../format_info.js'; +import { GPUTest } from '../../../gpu_test.js'; +import { kValidShaderStages } from '../../../util/shader.js'; + +function ComponentCount(format) { + switch (format) { + case 'r32float': + case 'r32sint': + case 'r32uint': + return 1; + case 'rg32float': + case 'rg32sint': + case 'rg32uint': + return 2; + case 'rgba32float': + case 'rgba32sint': + case 'rgba32uint': + case 'rgba8sint': + case 'rgba8uint': + case 'rgba8snorm': + case 'rgba8unorm': + case 'rgba16float': + case 'rgba16sint': + case 'rgba16uint': + case 'bgra8unorm': + return 4; + default: + unreachable(); + return 0; + } +} + +class F extends GPUTest { + InitTextureAndGetExpectedOutputBufferData( + storageTexture, + format) + { + const bytesPerBlock = kTextureFormatInfo[format].color.bytes; + assert(bytesPerBlock !== undefined); + + const width = storageTexture.width; + const height = storageTexture.height; + const depthOrArrayLayers = storageTexture.depthOrArrayLayers; + + const texelData = new ArrayBuffer(bytesPerBlock * width * height * depthOrArrayLayers); + const texelTypedDataView = this.GetTypedArrayBufferViewForTexelData(texelData, format); + const componentCount = ComponentCount(format); + const outputBufferData = new ArrayBuffer(4 * 4 * width * height * depthOrArrayLayers); + const outputBufferTypedData = this.GetTypedArrayBufferForOutputBufferData( + outputBufferData, + format + ); + + const SetData = ( + texelValue, + outputValue, + texelDataIndex, + component, + outputComponent = component) => + { + const texelComponentIndex = texelDataIndex * componentCount + component; + texelTypedDataView[texelComponentIndex] = texelValue; + const outputTexelComponentIndex = texelDataIndex * 4 + outputComponent; + outputBufferTypedData[outputTexelComponentIndex] = outputValue; + }; + for (let z = 0; z < depthOrArrayLayers; ++z) { + for (let y = 0; y < height; ++y) { + for (let x = 0; x < width; ++x) { + const texelDataIndex = z * width * height + y * width + x; + outputBufferTypedData[4 * texelDataIndex] = 0; + outputBufferTypedData[4 * texelDataIndex + 1] = 0; + outputBufferTypedData[4 * texelDataIndex + 2] = 0; + outputBufferTypedData[4 * texelDataIndex + 3] = 1; + for (let component = 0; component < componentCount; ++component) { + switch (format) { + case 'r32uint': + case 'rg32uint': + case 'rgba16uint': + case 'rgba32uint':{ + const texelValue = 4 * texelDataIndex + component + 1; + SetData(texelValue, texelValue, texelDataIndex, component); + break; + } + case 'rgba8uint':{ + const texelValue = (4 * texelDataIndex + component + 1) % 256; + SetData(texelValue, texelValue, texelDataIndex, component); + break; + } + case 'rgba8unorm':{ + const texelValue = (4 * texelDataIndex + component + 1) % 256; + const outputValue = texelValue / 255.0; + SetData(texelValue, outputValue, texelDataIndex, component); + break; + } + case 'bgra8unorm':{ + const texelValue = (4 * texelDataIndex + component + 1) % 256; + const outputValue = texelValue / 255.0; + // BGRA -> RGBA + assert(component < 4); + const outputComponent = [2, 1, 0, 3][component]; + SetData(texelValue, outputValue, texelDataIndex, component, outputComponent); + break; + } + case 'r32sint': + case 'rg32sint': + case 'rgba16sint': + case 'rgba32sint':{ + const texelValue = + (texelDataIndex & 1 ? 1 : -1) * (4 * texelDataIndex + component + 1); + SetData(texelValue, texelValue, texelDataIndex, component); + break; + } + case 'rgba8sint':{ + const texelValue = (4 * texelDataIndex + component + 1) % 256 - 128; + SetData(texelValue, texelValue, texelDataIndex, component); + break; + } + case 'rgba8snorm':{ + const texelValue = (4 * texelDataIndex + component + 1) % 256 - 128; + const outputValue = Math.max(texelValue / 127.0, -1.0); + SetData(texelValue, outputValue, texelDataIndex, component); + break; + } + case 'r32float': + case 'rg32float': + case 'rgba32float':{ + const texelValue = (4 * texelDataIndex + component + 1) / 10.0; + SetData(texelValue, texelValue, texelDataIndex, component); + break; + } + case 'rgba16float':{ + const texelValue = (4 * texelDataIndex + component + 1) / 10.0; + const f16Array = new Float16Array(1); + f16Array[0] = texelValue; + SetData(texelValue, f16Array[0], texelDataIndex, component); + break; + } + default: + unreachable(); + break; + } + } + } + } + } + this.queue.writeTexture( + { + texture: storageTexture + }, + texelData, + { + bytesPerRow: bytesPerBlock * width, + rowsPerImage: height + }, + [width, height, depthOrArrayLayers] + ); + + return outputBufferData; + } + + GetTypedArrayBufferForOutputBufferData(arrayBuffer, format) { + switch (kTextureFormatInfo[format].color.type) { + case 'uint': + return new Uint32Array(arrayBuffer); + case 'sint': + return new Int32Array(arrayBuffer); + case 'float': + case 'unfilterable-float': + return new Float32Array(arrayBuffer); + } + } + + GetTypedArrayBufferViewForTexelData(arrayBuffer, format) { + switch (format) { + case 'r32uint': + case 'rg32uint': + case 'rgba32uint': + return new Uint32Array(arrayBuffer); + case 'rgba8uint': + case 'rgba8unorm': + case 'bgra8unorm': + return new Uint8Array(arrayBuffer); + case 'rgba16uint': + return new Uint16Array(arrayBuffer); + case 'r32sint': + case 'rg32sint': + case 'rgba32sint': + return new Int32Array(arrayBuffer); + case 'rgba8sint': + case 'rgba8snorm': + return new Int8Array(arrayBuffer); + case 'rgba16sint': + return new Int16Array(arrayBuffer); + case 'r32float': + case 'rg32float': + case 'rgba32float': + return new Float32Array(arrayBuffer); + case 'rgba16float': + return new Float16Array(arrayBuffer); + default: + unreachable(); + return new Uint8Array(arrayBuffer); + } + } + + GetOutputBufferWGSLType(format) { + switch (kTextureFormatInfo[format].color.type) { + case 'uint': + return 'vec4u'; + case 'sint': + return 'vec4i'; + case 'float': + case 'unfilterable-float': + return 'vec4f'; + default: + unreachable(); + return ''; + } + } + + DoTransform( + storageTexture, + shaderStage, + format, + outputBuffer) + { + let declaration = ''; + switch (storageTexture.dimension) { + case '1d': + declaration = 'texture_storage_1d'; + break; + case '2d': + declaration = + storageTexture.depthOrArrayLayers > 1 ? 'texture_storage_2d_array' : 'texture_storage_2d'; + break; + case '3d': + declaration = 'texture_storage_3d'; + break; + } + const textureDeclaration = ` + @group(0) @binding(0) var readOnlyTexture: ${declaration}<${format}, read>; + `; + const bindingResourceDeclaration = ` + ${textureDeclaration} + @group(0) @binding(1) + var outputBuffer : array<${this.GetOutputBufferWGSLType(format)}>; + `; + + const bindGroupEntries = [ + { + binding: 0, + resource: storageTexture.createView() + }, + { + binding: 1, + resource: { + buffer: outputBuffer + } + }]; + + + const commandEncoder = this.device.createCommandEncoder(); + + switch (shaderStage) { + case 'compute':{ + let textureLoadCoord = ''; + switch (storageTexture.dimension) { + case '1d': + textureLoadCoord = 'invocationID.x'; + break; + case '2d': + textureLoadCoord = + storageTexture.depthOrArrayLayers > 1 ? + `vec2u(invocationID.x, invocationID.y), invocationID.z` : + `vec2u(invocationID.x, invocationID.y)`; + break; + case '3d': + textureLoadCoord = 'invocationID'; + break; + } + + const computeShader = ` + ${bindingResourceDeclaration} + @compute + @workgroup_size( + ${storageTexture.width}, ${storageTexture.height}, ${storageTexture.depthOrArrayLayers}) + fn main( + @builtin(local_invocation_id) invocationID: vec3u, + @builtin(local_invocation_index) invocationIndex: u32) { + let initialValue = textureLoad(readOnlyTexture, ${textureLoadCoord}); + outputBuffer[invocationIndex] = initialValue; + }`; + const computePipeline = this.device.createComputePipeline({ + compute: { + module: this.device.createShaderModule({ + code: computeShader + }) + }, + layout: 'auto' + }); + const bindGroup = this.device.createBindGroup({ + layout: computePipeline.getBindGroupLayout(0), + entries: bindGroupEntries + }); + + const computePassEncoder = commandEncoder.beginComputePass(); + computePassEncoder.setPipeline(computePipeline); + computePassEncoder.setBindGroup(0, bindGroup); + computePassEncoder.dispatchWorkgroups(1); + computePassEncoder.end(); + break; + } + case 'fragment':{ + let textureLoadCoord = ''; + switch (storageTexture.dimension) { + case '1d': + textureLoadCoord = 'textureCoord.x'; + break; + case '2d': + textureLoadCoord = + storageTexture.depthOrArrayLayers > 1 ? 'textureCoord, z' : 'textureCoord'; + break; + case '3d': + textureLoadCoord = 'vec3u(textureCoord, z)'; + break; + } + + const fragmentShader = ` + ${bindingResourceDeclaration} + @fragment + fn main(@builtin(position) fragCoord: vec4f) -> @location(0) vec4f { + let textureCoord = vec2u(fragCoord.xy); + let storageTextureTexelCountPerImage = ${storageTexture.width * storageTexture.height}u; + for (var z = 0u; z < ${storageTexture.depthOrArrayLayers}; z++) { + let initialValue = textureLoad(readOnlyTexture, ${textureLoadCoord}); + let outputIndex = + storageTextureTexelCountPerImage * z + textureCoord.y * ${storageTexture.width} + + textureCoord.x; + outputBuffer[outputIndex] = initialValue; + } + return vec4f(0.0, 1.0, 0.0, 1.0); + }`; + const vertexShader = ` + @vertex + fn main(@builtin(vertex_index) vertexIndex : u32) -> @builtin(position) vec4f { + var pos = array( + vec2f(-1.0, -1.0), + vec2f(-1.0, 1.0), + vec2f( 1.0, -1.0), + vec2f(-1.0, 1.0), + vec2f( 1.0, -1.0), + vec2f( 1.0, 1.0)); + return vec4f(pos[vertexIndex], 0.0, 1.0); + } + `; + const renderPipeline = this.device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: this.device.createShaderModule({ + code: vertexShader + }) + }, + fragment: { + module: this.device.createShaderModule({ + code: fragmentShader + }), + targets: [ + { + format: 'rgba8unorm' + }] + + }, + primitive: { + topology: 'triangle-list' + } + }); + + const bindGroup = this.device.createBindGroup({ + layout: renderPipeline.getBindGroupLayout(0), + entries: bindGroupEntries + }); + + const placeholderColorTexture = this.device.createTexture({ + size: [storageTexture.width, storageTexture.height, 1], + usage: GPUTextureUsage.RENDER_ATTACHMENT, + format: 'rgba8unorm' + }); + this.trackForCleanup(placeholderColorTexture); + + const renderPassEncoder = commandEncoder.beginRenderPass({ + colorAttachments: [ + { + view: placeholderColorTexture.createView(), + loadOp: 'clear', + clearValue: { r: 0, g: 0, b: 0, a: 0 }, + storeOp: 'store' + }] + + }); + renderPassEncoder.setPipeline(renderPipeline); + renderPassEncoder.setBindGroup(0, bindGroup); + renderPassEncoder.draw(6); + renderPassEncoder.end(); + break; + } + case 'vertex':{ + // For each texel location (coordX, coordY), draw one point at (coordX + 0.5, coordY + 0.5) + // in the storageTexture.width * storageTexture.height grid, and save all the texel values + // at (coordX, coordY, z) (z >= 0 && z < storageTexture.depthOrArrayLayers) into the + // corresponding vertex shader outputs. + let vertexOutputs = ''; + for (let layer = 0; layer < storageTexture.depthOrArrayLayers; ++layer) { + vertexOutputs = vertexOutputs.concat( + ` + @location(${layer + 1}) @interpolate(flat) + vertex_out${layer}: ${this.GetOutputBufferWGSLType(format)},` + ); + } + + let loadFromTextureWGSL = ''; + switch (storageTexture.dimension) { + case '1d': + loadFromTextureWGSL = ` + output.vertex_out0 = textureLoad(readOnlyTexture, coordX);`; + break; + case '2d': + if (storageTexture.depthOrArrayLayers === 1) { + loadFromTextureWGSL = ` + output.vertex_out0 = textureLoad(readOnlyTexture, vec2u(coordX, coordY));`; + } else { + for (let z = 0; z < storageTexture.depthOrArrayLayers; ++z) { + loadFromTextureWGSL = loadFromTextureWGSL.concat(` + output.vertex_out${z} = + textureLoad(readOnlyTexture, vec2u(coordX, coordY), ${z});`); + } + } + break; + case '3d': + for (let z = 0; z < storageTexture.depthOrArrayLayers; ++z) { + loadFromTextureWGSL = loadFromTextureWGSL.concat(` + output.vertex_out${z} = textureLoad(readOnlyTexture, vec3u(coordX, coordY, ${z}));`); + } + break; + } + + let outputToBufferWGSL = ''; + for (let layer = 0; layer < storageTexture.depthOrArrayLayers; ++layer) { + outputToBufferWGSL = outputToBufferWGSL.concat( + ` + let outputIndex${layer} = + storageTextureTexelCountPerImage * ${layer}u + + fragmentInput.tex_coord.y * ${storageTexture.width}u + fragmentInput.tex_coord.x; + outputBuffer[outputIndex${layer}] = fragmentInput.vertex_out${layer};` + ); + } + + const shader = ` + ${bindingResourceDeclaration} + struct VertexOutput { + @builtin(position) my_pos: vec4f, + @location(0) @interpolate(flat) tex_coord: vec2u, + ${vertexOutputs} + } + @vertex + fn vs_main(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput { + var output : VertexOutput; + let coordX = vertexIndex % ${storageTexture.width}u; + let coordY = vertexIndex / ${storageTexture.width}u; + // Each vertex in the mesh take an even step along X axis from -1.0 to 1.0. + let posXStep = f32(${2.0 / storageTexture.width}); + // As well as along Y axis. + let posYStep = f32(${2.0 / storageTexture.height}); + // And the vertex located in the middle of the step, i.e. with a bias of 0.5 step. + let outputPosX = -1.0 + posXStep * 0.5 + posXStep * f32(coordX); + let outputPosY = -1.0 + posYStep * 0.5 + posYStep * f32(coordY); + output.my_pos = vec4f(outputPosX, outputPosY, 0.0, 1.0); + output.tex_coord = vec2u(coordX, coordY); + ${loadFromTextureWGSL} + return output; + } + @fragment + fn fs_main(fragmentInput : VertexOutput) -> @location(0) vec4f { + let storageTextureTexelCountPerImage = ${storageTexture.width * storageTexture.height}u; + ${outputToBufferWGSL} + return vec4f(0.0, 1.0, 0.0, 1.0); + } + `; + + const renderPipeline = this.device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: this.device.createShaderModule({ + code: shader + }) + }, + fragment: { + module: this.device.createShaderModule({ + code: shader + }), + targets: [ + { + format: 'rgba8unorm' + }] + + }, + primitive: { + topology: 'point-list' + } + }); + + const bindGroup = this.device.createBindGroup({ + layout: renderPipeline.getBindGroupLayout(0), + entries: bindGroupEntries + }); + + const placeholderColorTexture = this.device.createTexture({ + size: [storageTexture.width, storageTexture.height, 1], + usage: GPUTextureUsage.RENDER_ATTACHMENT, + format: 'rgba8unorm' + }); + this.trackForCleanup(placeholderColorTexture); + + const renderPassEncoder = commandEncoder.beginRenderPass({ + colorAttachments: [ + { + view: placeholderColorTexture.createView(), + loadOp: 'clear', + clearValue: { r: 0, g: 0, b: 0, a: 0 }, + storeOp: 'store' + }] + + }); + renderPassEncoder.setPipeline(renderPipeline); + renderPassEncoder.setBindGroup(0, bindGroup); + renderPassEncoder.draw(storageTexture.width * storageTexture.height); + renderPassEncoder.end(); + break; + } + } + + this.queue.submit([commandEncoder.finish()]); + } +} + +export const g = makeTestGroup(F); + +g.test('basic'). +desc( + `The basic functionality tests for read-only storage textures. In the test we read data from + the read-only storage texture, write the data into an output storage buffer, and check if the + data in the output storage buffer is exactly what we expect.` +). +params((u) => +u. +combine('format', kColorTextureFormats). +filter( + (p) => p.format === 'bgra8unorm' || kTextureFormatInfo[p.format].color?.storage === true +). +combine('shaderStage', kValidShaderStages). +combine('dimension', kTextureDimensions). +combine('depthOrArrayLayers', [1, 2]). +unless((p) => p.dimension === '1d' && p.depthOrArrayLayers > 1) +). +beforeAllSubcases((t) => { + if (t.params.format === 'bgra8unorm') { + t.selectDeviceOrSkipTestCase('bgra8unorm-storage'); + } + if (t.isCompatibility) { + t.skipIfTextureFormatNotUsableAsStorageTexture(t.params.format); + } +}). +fn((t) => { + const { format, shaderStage, dimension, depthOrArrayLayers } = t.params; + + const kWidth = 8; + const height = dimension === '1d' ? 1 : 8; + const storageTexture = t.device.createTexture({ + format, + dimension, + size: [kWidth, height, depthOrArrayLayers], + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST | GPUTextureUsage.STORAGE_BINDING + }); + t.trackForCleanup(storageTexture); + + const expectedData = t.InitTextureAndGetExpectedOutputBufferData(storageTexture, format); + + const outputBuffer = t.device.createBuffer({ + size: 4 * 4 * kWidth * height * depthOrArrayLayers, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE + }); + t.trackForCleanup(outputBuffer); + + t.DoTransform(storageTexture, shaderStage, format, outputBuffer); + + switch (kTextureFormatInfo[format].color.type) { + case 'uint': + t.expectGPUBufferValuesEqual(outputBuffer, new Uint32Array(expectedData)); + break; + case 'sint': + t.expectGPUBufferValuesEqual(outputBuffer, new Int32Array(expectedData)); + break; + case 'float': + case 'unfilterable-float': + t.expectGPUBufferValuesEqual(outputBuffer, new Float32Array(expectedData)); + break; + default: + unreachable(); + break; + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/storage_texture/read_write.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/storage_texture/read_write.spec.js new file mode 100644 index 0000000000..ecc27c47ff --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/storage_texture/read_write.spec.js @@ -0,0 +1,385 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Tests for the behavior of read-write storage textures. + +TODO: +- Test resource usage transitions with read-write storage textures +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { assert, unreachable } from '../../../../common/util/util.js'; +import { kTextureDimensions } from '../../../capability_info.js'; +import { kColorTextureFormats, kTextureFormatInfo } from '../../../format_info.js'; +import { GPUTest } from '../../../gpu_test.js'; +import { align } from '../../../util/math.js'; + +const kShaderStagesForReadWriteStorageTexture = ['fragment', 'compute']; + + + +class F extends GPUTest { + GetInitialData(storageTexture) { + const format = storageTexture.format; + const bytesPerBlock = kTextureFormatInfo[format].bytesPerBlock; + assert(bytesPerBlock !== undefined); + + const width = storageTexture.width; + const height = storageTexture.height; + const depthOrArrayLayers = storageTexture.depthOrArrayLayers; + const initialData = new ArrayBuffer(bytesPerBlock * width * height * depthOrArrayLayers); + const initialTypedData = this.GetTypedArrayBuffer(initialData, format); + for (let z = 0; z < depthOrArrayLayers; ++z) { + for (let y = 0; y < height; ++y) { + for (let x = 0; x < width; ++x) { + const index = z * width * height + y * width + x; + switch (format) { + case 'r32sint': + initialTypedData[index] = (index & 1 ? 1 : -1) * (2 * index + 1); + break; + case 'r32uint': + initialTypedData[index] = 2 * index + 1; + break; + case 'r32float': + initialTypedData[index] = (2 * index + 1) / 10.0; + break; + } + } + } + } + return initialData; + } + + GetTypedArrayBuffer(arrayBuffer, format) { + switch (format) { + case 'r32sint': + return new Int32Array(arrayBuffer); + case 'r32uint': + return new Uint32Array(arrayBuffer); + case 'r32float': + return new Float32Array(arrayBuffer); + default: + unreachable(); + return new Uint8Array(arrayBuffer); + } + } + + GetExpectedData( + shaderStage, + storageTexture, + initialData) + { + const format = storageTexture.format; + const bytesPerBlock = kTextureFormatInfo[format].bytesPerBlock; + assert(bytesPerBlock !== undefined); + + const width = storageTexture.width; + const height = storageTexture.height; + const depthOrArrayLayers = storageTexture.depthOrArrayLayers; + const bytesPerRowAlignment = align(bytesPerBlock * width, 256); + const itemsPerRow = bytesPerRowAlignment / bytesPerBlock; + + const expectedData = new ArrayBuffer( + bytesPerRowAlignment * (height * depthOrArrayLayers - 1) + bytesPerBlock * width + ); + const expectedTypedData = this.GetTypedArrayBuffer(expectedData, format); + const initialTypedData = this.GetTypedArrayBuffer(initialData, format); + for (let z = 0; z < depthOrArrayLayers; ++z) { + for (let y = 0; y < height; ++y) { + for (let x = 0; x < width; ++x) { + const expectedIndex = z * itemsPerRow * height + y * itemsPerRow + x; + switch (shaderStage) { + case 'compute':{ + // In the compute shader we flip the texture along the diagonal. + const initialIndex = + (depthOrArrayLayers - 1 - z) * width * height + + (height - 1 - y) * width + ( + width - 1 - x); + expectedTypedData[expectedIndex] = initialTypedData[initialIndex]; + break; + } + case 'fragment':{ + // In the fragment shader we double the original texel value of the read-write storage + // texture. + const initialIndex = z * width * height + y * width + x; + expectedTypedData[expectedIndex] = initialTypedData[initialIndex] * 2; + break; + } + } + } + } + } + return expectedData; + } + + RecordCommandsToTransform( + device, + shaderStage, + commandEncoder, + rwTexture) + { + let declaration = ''; + switch (rwTexture.dimension) { + case '1d': + declaration = 'texture_storage_1d'; + break; + case '2d': + declaration = + rwTexture.depthOrArrayLayers > 1 ? 'texture_storage_2d_array' : 'texture_storage_2d'; + break; + case '3d': + declaration = 'texture_storage_3d'; + break; + } + const textureDeclaration = ` + @group(0) @binding(0) var rwTexture: ${declaration}<${rwTexture.format}, read_write>; + `; + + switch (shaderStage) { + case 'fragment':{ + const vertexShader = ` + @vertex + fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f { + var pos = array( + vec2f(-1.0, -1.0), + vec2f(-1.0, 1.0), + vec2f( 1.0, -1.0), + vec2f(-1.0, 1.0), + vec2f( 1.0, -1.0), + vec2f( 1.0, 1.0)); + return vec4f(pos[VertexIndex], 0.0, 1.0); + } + `; + let textureLoadStoreCoord = ''; + switch (rwTexture.dimension) { + case '1d': + textureLoadStoreCoord = 'textureCoord.x'; + break; + case '2d': + textureLoadStoreCoord = + rwTexture.depthOrArrayLayers > 1 ? 'textureCoord, z' : 'textureCoord'; + break; + case '3d': + textureLoadStoreCoord = 'vec3u(textureCoord, z)'; + break; + } + const fragmentShader = ` + ${textureDeclaration} + @fragment + fn main(@builtin(position) fragCoord: vec4f) -> @location(0) vec4f { + let textureCoord = vec2u(fragCoord.xy); + + for (var z = 0u; z < ${rwTexture.depthOrArrayLayers}; z++) { + let initialValue = textureLoad(rwTexture, ${textureLoadStoreCoord}); + let outputValue = initialValue * 2; + textureStore(rwTexture, ${textureLoadStoreCoord}, outputValue); + } + + return vec4f(0.0, 1.0, 0.0, 1.0); + } + `; + const renderPipeline = device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: device.createShaderModule({ + code: vertexShader + }) + }, + fragment: { + module: device.createShaderModule({ + code: fragmentShader + }), + targets: [ + { + format: 'rgba8unorm' + }] + + }, + primitive: { + topology: 'triangle-list' + } + }); + + const bindGroup = device.createBindGroup({ + layout: renderPipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: rwTexture.createView() + }] + + }); + + const placeholderColorTexture = device.createTexture({ + size: [rwTexture.width, rwTexture.height, 1], + usage: GPUTextureUsage.RENDER_ATTACHMENT, + format: 'rgba8unorm' + }); + this.trackForCleanup(placeholderColorTexture); + + const renderPassEncoder = commandEncoder.beginRenderPass({ + colorAttachments: [ + { + view: placeholderColorTexture.createView(), + loadOp: 'clear', + clearValue: { r: 0, g: 0, b: 0, a: 0 }, + storeOp: 'store' + }] + + }); + renderPassEncoder.setPipeline(renderPipeline); + renderPassEncoder.setBindGroup(0, bindGroup); + renderPassEncoder.draw(6); + renderPassEncoder.end(); + break; + } + case 'compute':{ + let textureLoadCoord = ''; + let textureStoreCoord = ''; + switch (rwTexture.dimension) { + case '1d': + textureLoadCoord = 'dimension - 1u - invocationID.x'; + textureStoreCoord = 'invocationID.x'; + break; + case '2d': + textureLoadCoord = + rwTexture.depthOrArrayLayers > 1 ? + `vec2u(dimension.x - 1u - invocationID.x, dimension.y - 1u - invocationID.y), + textureNumLayers(rwTexture) - 1u - invocationID.z` : + `vec2u(dimension.x - 1u - invocationID.x, dimension.y - 1u - invocationID.y)`; + textureStoreCoord = + rwTexture.depthOrArrayLayers > 1 ? + 'invocationID.xy, invocationID.z' : + 'invocationID.xy'; + break; + case '3d': + textureLoadCoord = ` + vec3u(dimension.x - 1u - invocationID.x, dimension.y - 1u - invocationID.y, + dimension.z - 1u - invocationID.z)`; + textureStoreCoord = 'invocationID'; + break; + } + + const computeShader = ` + ${textureDeclaration} + @compute + @workgroup_size(${rwTexture.width}, ${rwTexture.height}, ${rwTexture.depthOrArrayLayers}) + fn main(@builtin(local_invocation_id) invocationID: vec3u) { + let dimension = textureDimensions(rwTexture); + + let initialValue = textureLoad(rwTexture, ${textureLoadCoord}); + textureBarrier(); + + textureStore(rwTexture, ${textureStoreCoord}, initialValue); + }`; + + const computePipeline = device.createComputePipeline({ + compute: { + module: device.createShaderModule({ + code: computeShader + }) + }, + layout: 'auto' + }); + const bindGroup = device.createBindGroup({ + layout: computePipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: rwTexture.createView() + }] + + }); + const computePassEncoder = commandEncoder.beginComputePass(); + computePassEncoder.setPipeline(computePipeline); + computePassEncoder.setBindGroup(0, bindGroup); + computePassEncoder.dispatchWorkgroups(1); + computePassEncoder.end(); + break; + } + } + } +} + +export const g = makeTestGroup(F); + +g.test('basic'). +desc( + `The basic functionality tests for read-write storage textures. In the test we read data from + the read-write storage texture, do transforms and write the data back to the read-write storage + texture. textureBarrier() is also called in the tests using compute pipelines.` +). +params((u) => +u. +combine('format', kColorTextureFormats). +filter((p) => kTextureFormatInfo[p.format].color?.readWriteStorage === true). +combine('shaderStage', kShaderStagesForReadWriteStorageTexture). +combine('textureDimension', kTextureDimensions). +combine('depthOrArrayLayers', [1, 2]). +unless((p) => p.textureDimension === '1d' && p.depthOrArrayLayers > 1) +). +beforeAllSubcases((t) => { + t.skipIfTextureFormatNotUsableAsStorageTexture(t.params.format); +}). +fn((t) => { + const { format, shaderStage, textureDimension, depthOrArrayLayers } = t.params; + + // In compatibility mode the lowest maxComputeInvocationsPerWorkgroup is 128 vs non-compat which is 256 + // So in non-compat we get 16 * 8 * 2, vs compat where we get 8 * 8 * 2 + const kWidth = t.isCompatibility ? 8 : 16; + const height = textureDimension === '1d' ? 1 : 8; + const textureSize = [kWidth, height, depthOrArrayLayers]; + const storageTexture = t.device.createTexture({ + format, + dimension: textureDimension, + size: textureSize, + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST | GPUTextureUsage.STORAGE_BINDING + }); + t.trackForCleanup(storageTexture); + + const bytesPerBlock = kTextureFormatInfo[format].bytesPerBlock; + const initialData = t.GetInitialData(storageTexture); + t.queue.writeTexture( + { texture: storageTexture }, + initialData, + { + bytesPerRow: bytesPerBlock * kWidth, + rowsPerImage: height + }, + textureSize + ); + + const commandEncoder = t.device.createCommandEncoder(); + + t.RecordCommandsToTransform(t.device, shaderStage, commandEncoder, storageTexture); + + const expectedData = t.GetExpectedData(shaderStage, storageTexture, initialData); + const readbackBuffer = t.device.createBuffer({ + size: expectedData.byteLength, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + }); + t.trackForCleanup(readbackBuffer); + const bytesPerRow = align(bytesPerBlock * kWidth, 256); + commandEncoder.copyTextureToBuffer( + { + texture: storageTexture + }, + { + buffer: readbackBuffer, + bytesPerRow, + rowsPerImage: height + }, + textureSize + ); + t.queue.submit([commandEncoder.finish()]); + + switch (format) { + case 'r32sint': + t.expectGPUBufferValuesEqual(readbackBuffer, new Int32Array(expectedData)); + break; + case 'r32uint': + t.expectGPUBufferValuesEqual(readbackBuffer, new Uint32Array(expectedData)); + break; + case 'r32float': + t.expectGPUBufferValuesEqual(readbackBuffer, new Float32Array(expectedData)); + break; + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/format_reinterpretation.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/format_reinterpretation.spec.js index efe3cf3265..f942724585 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/format_reinterpretation.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/format_reinterpretation.spec.js @@ -100,12 +100,15 @@ u // .combine('format', kRegularTextureFormats). combine('viewFormat', kRegularTextureFormats). filter( - ({ format, viewFormat }) => format !== viewFormat && viewCompatible(format, viewFormat) + ({ format, viewFormat }) => + format !== viewFormat && viewCompatible(false, format, viewFormat) ) ). beforeAllSubcases((t) => { const { format, viewFormat } = t.params; t.skipIfTextureFormatNotSupported(format, viewFormat); + // Compatibility mode does not support format reinterpretation. + t.skipIf(t.isCompatibility); }). fn((t) => { const { format, viewFormat } = t.params; @@ -200,13 +203,16 @@ u // .combine('format', kRenderableColorTextureFormats). combine('viewFormat', kRenderableColorTextureFormats). filter( - ({ format, viewFormat }) => format !== viewFormat && viewCompatible(format, viewFormat) + ({ format, viewFormat }) => + format !== viewFormat && viewCompatible(false, format, viewFormat) ). combine('sampleCount', [1, 4]) ). beforeAllSubcases((t) => { const { format, viewFormat } = t.params; t.skipIfTextureFormatNotSupported(format, viewFormat); + // Compatibility mode does not support format reinterpretation. + t.skipIf(t.isCompatibility); }). fn((t) => { const { format, viewFormat, sampleCount } = t.params; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/write.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/write.spec.js index 5b52d9d0b2..185407105c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/write.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/write.spec.js @@ -3,6 +3,9 @@ **/export const description = ` Test the result of writing textures through texture views with various options. +Reads value from a shader array, writes the value via various write methods. +Check the texture result with the expected texel view. + All x= every possible view write method: { - storage write {fragment, compute} - render pass store @@ -13,20 +16,358 @@ Format reinterpretation is not tested here. It is in format_reinterpretation.spe TODO: Write helper for this if not already available (see resource_init, buffer_sync_test for related code). `;import { makeTestGroup } from '../../../../common/framework/test_group.js'; -import { GPUTest } from '../../../gpu_test.js'; +import { unreachable } from '../../../../common/util/util.js'; +import { + kRegularTextureFormats, + kTextureFormatInfo } from + +'../../../format_info.js'; +import { GPUTest, TextureTestMixin } from '../../../gpu_test.js'; +import { kFullscreenQuadVertexShaderCode } from '../../../util/shader.js'; +import { TexelView } from '../../../util/texture/texel_view.js'; + +export const g = makeTestGroup(TextureTestMixin(GPUTest)); + +const kTextureViewWriteMethods = [ +'storage-write-fragment', +'storage-write-compute', +'render-pass-store', +'render-pass-resolve']; + + + +// Src color values to read from a shader array. +const kColorsFloat = [ +{ R: 1.0, G: 0.0, B: 0.0, A: 0.8 }, +{ R: 0.0, G: 1.0, B: 0.0, A: 0.7 }, +{ R: 0.0, G: 0.0, B: 0.0, A: 0.6 }, +{ R: 0.0, G: 0.0, B: 0.0, A: 0.5 }, +{ R: 1.0, G: 1.0, B: 1.0, A: 0.4 }, +{ R: 0.7, G: 0.0, B: 0.0, A: 0.3 }, +{ R: 0.0, G: 0.8, B: 0.0, A: 0.2 }, +{ R: 0.0, G: 0.0, B: 0.9, A: 0.1 }, +{ R: 0.1, G: 0.2, B: 0.0, A: 0.3 }, +{ R: 0.4, G: 0.3, B: 0.6, A: 0.8 }]; + + +function FloatToIntColor(c) { + return Math.floor(c * 100); +} + +const kColorsInt = kColorsFloat.map((c) => { + return { + R: FloatToIntColor(c.R), + G: FloatToIntColor(c.G), + B: FloatToIntColor(c.B), + A: FloatToIntColor(c.A) + }; +}); + +const kTextureSize = 16; + +function writeTextureAndGetExpectedTexelView( +t, +method, +view, +format, +sampleCount) +{ + const info = kTextureFormatInfo[format]; + const isFloatType = info.color.type === 'float' || info.color.type === 'unfilterable-float'; + const kColors = isFloatType ? kColorsFloat : kColorsInt; + const expectedTexelView = TexelView.fromTexelsAsColors( + format, + (coords) => { + const pixelPos = coords.y * kTextureSize + coords.x; + return kColors[pixelPos % kColors.length]; + }, + { clampToFormatRange: true } + ); + const vecType = isFloatType ? 'vec4f' : info.color.type === 'sint' ? 'vec4i' : 'vec4u'; + const kColorArrayShaderString = `array<${vecType}, ${kColors.length}>( + ${kColors.map((t) => `${vecType}(${t.R}, ${t.G}, ${t.B}, ${t.A}) `).join(',')} + )`; + + switch (method) { + case 'storage-write-compute': + { + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ + code: ` + @group(0) @binding(0) var dst: texture_storage_2d<${format}, write>; + @compute @workgroup_size(1, 1) fn main( + @builtin(global_invocation_id) global_id: vec3, + ) { + const src = ${kColorArrayShaderString}; + let coord = vec2u(global_id.xy); + let idx = coord.x + coord.y * ${kTextureSize}; + textureStore(dst, coord, src[idx % ${kColors.length}]); + }` + }), + entryPoint: 'main' + } + }); + const commandEncoder = t.device.createCommandEncoder(); + const pass = commandEncoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup( + 0, + t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: view + }] + + }) + ); + pass.dispatchWorkgroups(kTextureSize, kTextureSize); + pass.end(); + t.device.queue.submit([commandEncoder.finish()]); + } + break; + + case 'storage-write-fragment': + { + // Create a placeholder color attachment texture, + // The size of which equals that of format texture we are testing, + // so that we have the same number of fragments and texels. + const kPlaceholderTextureFormat = 'rgba8unorm'; + const placeholderTexture = t.trackForCleanup( + t.device.createTexture({ + format: kPlaceholderTextureFormat, + size: [kTextureSize, kTextureSize], + usage: GPUTextureUsage.RENDER_ATTACHMENT + }) + ); + + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: t.device.createShaderModule({ + code: kFullscreenQuadVertexShaderCode + }) + }, + fragment: { + module: t.device.createShaderModule({ + code: ` + @group(0) @binding(0) var dst: texture_storage_2d<${format}, write>; + @fragment fn main( + @builtin(position) fragCoord: vec4, + ) { + const src = ${kColorArrayShaderString}; + let coord = vec2u(fragCoord.xy); + let idx = coord.x + coord.y * ${kTextureSize}; + textureStore(dst, coord, src[idx % ${kColors.length}]); + }` + }), + // Set writeMask to 0 as the fragment shader has no output. + targets: [ + { + format: kPlaceholderTextureFormat, + writeMask: 0 + }] + + } + }); + const commandEncoder = t.device.createCommandEncoder(); + const pass = commandEncoder.beginRenderPass({ + colorAttachments: [ + { + view: placeholderTexture.createView(), + loadOp: 'clear', + storeOp: 'discard' + }] + + }); + pass.setPipeline(pipeline); + pass.setBindGroup( + 0, + t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: view + }] -export const g = makeTestGroup(GPUTest); + }) + ); + pass.draw(6); + pass.end(); + t.device.queue.submit([commandEncoder.finish()]); + } + break; + + case 'render-pass-store': + case 'render-pass-resolve': + { + // Create a placeholder color attachment texture for the store target when tesing texture is used as resolve target. + const targetView = + method === 'render-pass-store' ? + view : + t. + trackForCleanup( + t.device.createTexture({ + format, + size: [kTextureSize, kTextureSize], + usage: GPUTextureUsage.RENDER_ATTACHMENT, + sampleCount: 4 + }) + ). + createView(); + const resolveView = method === 'render-pass-store' ? undefined : view; + const multisampleCount = method === 'render-pass-store' ? sampleCount : 4; + + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: t.device.createShaderModule({ + code: kFullscreenQuadVertexShaderCode + }) + }, + fragment: { + module: t.device.createShaderModule({ + code: ` + @fragment fn main( + @builtin(position) fragCoord: vec4, + ) -> @location(0) ${vecType} { + const src = ${kColorArrayShaderString}; + let coord = vec2u(fragCoord.xy); + let idx = coord.x + coord.y * ${kTextureSize}; + return src[idx % ${kColors.length}]; + }` + }), + targets: [ + { + format + }] + + }, + multisample: { + count: multisampleCount + } + }); + const commandEncoder = t.device.createCommandEncoder(); + const pass = commandEncoder.beginRenderPass({ + colorAttachments: [ + { + view: targetView, + resolveTarget: resolveView, + loadOp: 'clear', + storeOp: 'store' + }] + + }); + pass.setPipeline(pipeline); + pass.draw(6); + pass.end(); + t.device.queue.submit([commandEncoder.finish()]); + } + break; + default: + unreachable(); + } + + return expectedTexelView; +} g.test('format'). desc( `Views of every allowed format. +Read values from color array in the shader, and write it to the texture view via different write methods. + - x= every texture format - x= sampleCount {1, 4} if valid - x= every possible view write method (see above) + +TODO: Test sampleCount > 1 for 'render-pass-store' after extending copySinglePixelTextureToBufferUsingComputePass + to read multiple pixels from multisampled textures. [1] +TODO: Test rgb10a2uint when TexelRepresentation.numericRange is made per-component. [2] ` ). -unimplemented(); +params((u) => +u // +.combine('method', kTextureViewWriteMethods). +combine('format', kRegularTextureFormats). +combine('sampleCount', [1, 4]). +filter(({ format, method, sampleCount }) => { + const info = kTextureFormatInfo[format]; + + if (sampleCount > 1 && !info.multisample) { + return false; + } + + // [2] + if (format === 'rgb10a2uint') { + return false; + } + + switch (method) { + case 'storage-write-compute': + case 'storage-write-fragment': + return info.color?.storage && sampleCount === 1; + case 'render-pass-store': + // [1] + if (sampleCount > 1) { + return false; + } + return !!info.colorRender; + case 'render-pass-resolve': + return !!info.colorRender?.resolve && sampleCount === 1; + } + return true; +}) +). +beforeAllSubcases((t) => { + const { format, method } = t.params; + t.skipIfTextureFormatNotSupported(format); + + switch (method) { + case 'storage-write-compute': + case 'storage-write-fragment': + // Still need to filter again for compat mode. + t.skipIfTextureFormatNotUsableAsStorageTexture(format); + break; + } +}). +fn((t) => { + const { format, method, sampleCount } = t.params; + + const usage = + GPUTextureUsage.COPY_SRC | ( + method.includes('storage') ? + GPUTextureUsage.STORAGE_BINDING : + GPUTextureUsage.RENDER_ATTACHMENT); + + const texture = t.trackForCleanup( + t.device.createTexture({ + format, + usage, + size: [kTextureSize, kTextureSize], + sampleCount + }) + ); + + const view = texture.createView(); + const expectedTexelView = writeTextureAndGetExpectedTexelView( + t, + method, + view, + format, + sampleCount + ); + + // [1] Use copySinglePixelTextureToBufferUsingComputePass to check multisampled texture. + t.expectTexelViewComparisonIsOkInTexture({ texture }, expectedTexelView, [ + kTextureSize, + kTextureSize] + ); +}); g.test('dimension'). desc( diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/mapping.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/mapping.spec.js index 3d27f02567..89766884d3 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/mapping.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/mapping.spec.js @@ -27,8 +27,10 @@ class F extends ValidationTest { this.expectValidationError(() => { p = buffer.mapAsync(mode, offset, size); }, expectation.validationError); + let caught = false; let rejectedEarly = false; + let microtaskBRan = false; // If mapAsync rejected early, microtask A will run before B. // If not, B will run before A. p.catch(() => { @@ -38,20 +40,31 @@ class F extends ValidationTest { queueMicrotask(() => { // Microtask B rejectedEarly = caught; + microtaskBRan = true; }); - try { - // This await will always complete after microtasks A and B are both done. - await p; - assert(expectation.rejectName === null, 'mapAsync unexpectedly passed'); - } catch (ex) { - assert(ex instanceof Error, 'mapAsync rejected with non-error'); - assert(typeof ex.stack === 'string', 'mapAsync rejected without a stack'); - assert(expectation.rejectName === ex.name, `mapAsync rejected unexpectedly with: ${ex}`); - assert( - expectation.earlyRejection === rejectedEarly, - 'mapAsync rejected at an unexpected timing' - ); - } + + // These handlers should always run after microtasks A and B are both done. + await p.then( + () => { + unreachable('mapAsync unexpectedly passed'); + }, + (ex) => { + const suffix = `\n Rejection: ${ex}`; + + this.expect(microtaskBRan, 'scheduling problem?: microtaskB has not run yet' + suffix); + assert(ex instanceof Error, 'mapAsync rejected with non-error' + suffix); + this.expect(typeof ex.stack === 'string', 'mapAsync rejected without a stack' + suffix); + this.expect( + expectation.rejectName === ex.name, + 'mapAsync rejected with wrong exception name' + suffix + ); + if (expectation.earlyRejection) { + this.expect(rejectedEarly, 'expected early mapAsync rejection, got deferred' + suffix); + } else { + this.expect(!rejectedEarly, 'expected deferred mapAsync rejection, got early' + suffix); + } + } + ); } } diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/query_types.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/query_types.spec.js index 02bfb09b64..44097d184c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/query_types.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/query_types.spec.js @@ -43,11 +43,13 @@ fn((t) => { }); }); -g.test('writeTimestamp'). +g.test('timestamp'). desc( ` Tests that writing a timestamp throws a type error exception if the features don't contain 'timestamp-query'. + + TODO: writeTimestamp test is disabled since it's removed from the spec for now. ` ). params((u) => u.combine('featureContainsTimestampQuery', [false, true])). @@ -66,11 +68,53 @@ fn((t) => { const querySet = t.device.createQuerySet({ type: featureContainsTimestampQuery ? 'timestamp' : 'occlusion', - count: 1 + count: 2 }); - const encoder = t.createEncoder('non-pass'); - t.shouldThrow(featureContainsTimestampQuery ? false : 'TypeError', () => { - encoder.encoder.writeTimestamp(querySet, 0); - }); + { + let expected = featureContainsTimestampQuery ? false : 'TypeError'; + // writeTimestamp no longer exists and this should always TypeError. + expected = 'TypeError'; + + const encoder = t.createEncoder('non-pass'); + t.shouldThrow(expected, () => { + + encoder.encoder.writeTimestamp(querySet, 0); + }); + encoder.finish(); + } + + { + const encoder = t.createEncoder('non-pass'); + encoder.encoder. + beginComputePass({ + timestampWrites: { querySet, beginningOfPassWriteIndex: 0, endOfPassWriteIndex: 1 } + }). + end(); + t.expectValidationError(() => { + encoder.finish(); + }, !featureContainsTimestampQuery); + } + + { + const encoder = t.createEncoder('non-pass'); + const view = t. + trackForCleanup( + t.device.createTexture({ + size: [16, 16, 1], + format: 'rgba8unorm', + usage: GPUTextureUsage.RENDER_ATTACHMENT + }) + ). + createView(); + encoder.encoder. + beginRenderPass({ + colorAttachments: [{ view, loadOp: 'clear', storeOp: 'discard' }], + timestampWrites: { querySet, beginningOfPassWriteIndex: 0, endOfPassWriteIndex: 1 } + }). + end(); + t.expectValidationError(() => { + encoder.finish(); + }, !featureContainsTimestampQuery); + } }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/limit_utils.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/limit_utils.js index 10cfffdcef..442af6ac74 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/limit_utils.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/limit_utils.js @@ -45,32 +45,47 @@ export function getPipelineTypeForBindingCombination(bindingCombination) { } } -function getBindGroupIndex(bindGroupTest, i) { +function getBindGroupIndex(bindGroupTest, numBindGroups, i) { switch (bindGroupTest) { case 'sameGroup': return 0; case 'differentGroups': - return i % 3; + return i % numBindGroups; + } +} + +function getBindingIndex(bindGroupTest, numBindGroups, i) { + switch (bindGroupTest) { + case 'sameGroup': + return i; + case 'differentGroups': + return i / numBindGroups | 0; } } function getWGSLBindings( -order, -bindGroupTest, -storageDefinitionWGSLSnippetFn, +{ + order, + bindGroupTest, + storageDefinitionWGSLSnippetFn, + numBindGroups + + + + + +}, numBindings, id) { return reorder( order, - range( - numBindings, - (i) => - `@group(${getBindGroupIndex( - bindGroupTest, - i - )}) @binding(${i}) ${storageDefinitionWGSLSnippetFn(i, id)};` - ) + range(numBindings, (i) => { + const groupNdx = getBindGroupIndex(bindGroupTest, numBindGroups, i); + const bindingNdx = getBindingIndex(bindGroupTest, numBindGroups, i); + const storageWGSL = storageDefinitionWGSLSnippetFn(i, id); + return `@group(${groupNdx}) @binding(${bindingNdx}) ${storageWGSL};`; + }) ).join('\n '); } @@ -80,15 +95,22 @@ order, bindGroupTest, storageDefinitionWGSLSnippetFn, bodyFn, +numBindGroups, numBindings, extraWGSL = '') { + const bindingParams = { + order, + bindGroupTest, + storageDefinitionWGSLSnippetFn, + numBindGroups + }; switch (bindingCombination) { case 'vertex': return ` ${extraWGSL} - ${getWGSLBindings(order, bindGroupTest, storageDefinitionWGSLSnippetFn, numBindings, 0)} + ${getWGSLBindings(bindingParams, numBindings, 0)} @vertex fn mainVS() -> @builtin(position) vec4f { ${bodyFn(numBindings, 0)} @@ -99,7 +121,7 @@ extraWGSL = '') return ` ${extraWGSL} - ${getWGSLBindings(order, bindGroupTest, storageDefinitionWGSLSnippetFn, numBindings, 0)} + ${getWGSLBindings(bindingParams, numBindings, 0)} @vertex fn mainVS() -> @builtin(position) vec4f { return vec4f(0); @@ -113,9 +135,9 @@ extraWGSL = '') return ` ${extraWGSL} - ${getWGSLBindings(order, bindGroupTest, storageDefinitionWGSLSnippetFn, numBindings, 0)} + ${getWGSLBindings(bindingParams, numBindings, 0)} - ${getWGSLBindings(order, bindGroupTest, storageDefinitionWGSLSnippetFn, numBindings - 1, 1)} + ${getWGSLBindings(bindingParams, numBindings - 1, 1)} @vertex fn mainVS() -> @builtin(position) vec4f { ${bodyFn(numBindings, 0)} @@ -131,9 +153,9 @@ extraWGSL = '') return ` ${extraWGSL} - ${getWGSLBindings(order, bindGroupTest, storageDefinitionWGSLSnippetFn, numBindings - 1, 0)} + ${getWGSLBindings(bindingParams, numBindings - 1, 0)} - ${getWGSLBindings(order, bindGroupTest, storageDefinitionWGSLSnippetFn, numBindings, 1)} + ${getWGSLBindings(bindingParams, numBindings, 1)} @vertex fn mainVS() -> @builtin(position) vec4f { ${bodyFn(numBindings - 1, 0)} @@ -148,8 +170,7 @@ extraWGSL = '') case 'compute': return ` ${extraWGSL} - ${getWGSLBindings(order, bindGroupTest, storageDefinitionWGSLSnippetFn, numBindings, 0)} - @group(3) @binding(0) var d: f32; + ${getWGSLBindings(bindingParams, numBindings, 0)} @compute @workgroup_size(1) fn main() { ${bodyFn(numBindings, 0)} } @@ -164,6 +185,7 @@ order, bindGroupTest, storageDefinitionWGSLSnippetFn, usageWGSLSnippetFn, +maxBindGroups, numBindings, extraWGSL = '') { @@ -174,6 +196,7 @@ extraWGSL = '') storageDefinitionWGSLSnippetFn, (numBindings, set) => `${range(numBindings, (i) => usageWGSLSnippetFn(i, set)).join('\n ')}`, + maxBindGroups, numBindings, extraWGSL ); @@ -185,6 +208,7 @@ order, bindGroupTest, storageDefinitionWGSLSnippetFn, usageWGSLSnippetFn, +numBindGroups, numBindings, extraWGSL = '') { @@ -195,6 +219,7 @@ extraWGSL = '') storageDefinitionWGSLSnippetFn, (numBindings, set) => `${range(numBindings, (i) => usageWGSLSnippetFn(i, set)).join('\n ')}`, + numBindGroups, numBindings, extraWGSL ); @@ -854,7 +879,7 @@ export class LimitTestsImpl extends GPUTestBase { /** * Creates an GPURenderCommandsMixin setup with some initial state. */ - _getGPURenderCommandsMixin(encoderType) { + #getGPURenderCommandsMixin(encoderType) { const { device } = this; switch (encoderType) { @@ -895,7 +920,7 @@ export class LimitTestsImpl extends GPUTestBase { }); const encoder = device.createCommandEncoder(); - const mixin = encoder.beginRenderPass({ + const passEncoder = encoder.beginRenderPass({ colorAttachments: [ { view: texture.createView(), @@ -906,10 +931,10 @@ export class LimitTestsImpl extends GPUTestBase { }); return { - mixin, + passEncoder, bindGroup, prep() { - mixin.end(); + passEncoder.end(); }, test() { encoder.finish(); @@ -946,16 +971,16 @@ export class LimitTestsImpl extends GPUTestBase { }); - const mixin = device.createRenderBundleEncoder({ + const passEncoder = device.createRenderBundleEncoder({ colorFormats: ['rgba8unorm'] }); return { - mixin, + passEncoder, bindGroup, prep() {}, test() { - mixin.finish(); + passEncoder.finish(); } }; break; @@ -964,17 +989,23 @@ export class LimitTestsImpl extends GPUTestBase { } /** - * Tests a method on GPURenderCommandsMixin - * The function will be called with the mixin. + * Test a method on GPURenderCommandsMixin or GPUBindingCommandsMixin + * The function will be called with the passEncoder. */ - async testGPURenderCommandsMixin( + async testGPURenderAndBindingCommandsMixin( encoderType, fn, + + + + + + shouldError, msg = '') { - const { mixin, prep, test } = this._getGPURenderCommandsMixin(encoderType); - fn({ mixin }); + const { passEncoder, prep, test, bindGroup } = this.#getGPURenderCommandsMixin(encoderType); + fn({ passEncoder, bindGroup }); prep(); await this.expectValidationError(test, shouldError, msg); @@ -983,7 +1014,7 @@ export class LimitTestsImpl extends GPUTestBase { /** * Creates GPUBindingCommandsMixin setup with some initial state. */ - _getGPUBindingCommandsMixin(encoderType) { + #getGPUBindingCommandsMixin(encoderType) { const { device } = this; switch (encoderType) { @@ -1016,12 +1047,12 @@ export class LimitTestsImpl extends GPUTestBase { }); const encoder = device.createCommandEncoder(); - const mixin = encoder.beginComputePass(); + const passEncoder = encoder.beginComputePass(); return { - mixin, + passEncoder, bindGroup, prep() { - mixin.end(); + passEncoder.end(); }, test() { encoder.finish(); @@ -1030,15 +1061,15 @@ export class LimitTestsImpl extends GPUTestBase { break; } case 'render': - return this._getGPURenderCommandsMixin('render'); + return this.#getGPURenderCommandsMixin('render'); case 'renderBundle': - return this._getGPURenderCommandsMixin('renderBundle'); + return this.#getGPURenderCommandsMixin('renderBundle'); } } /** * Tests a method on GPUBindingCommandsMixin - * The function pass will be called with the mixin and a bindGroup + * The function pass will be called with the passEncoder and a bindGroup */ async testGPUBindingCommandsMixin( encoderType, @@ -1046,8 +1077,8 @@ export class LimitTestsImpl extends GPUTestBase { shouldError, msg = '') { - const { mixin, bindGroup, prep, test } = this._getGPUBindingCommandsMixin(encoderType); - fn({ mixin, bindGroup }); + const { passEncoder, bindGroup, prep, test } = this.#getGPUBindingCommandsMixin(encoderType); + fn({ passEncoder, bindGroup }); prep(); await this.expectValidationError(test, shouldError, msg); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxBindGroups.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxBindGroups.spec.js index ab0eaa3e4b..f239b560fa 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxBindGroups.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxBindGroups.spec.js @@ -1,6 +1,6 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { range } from '../../../../../common/util/util.js';import { +**/import { assert } from '../../../../../common/util/util.js';import { kCreatePipelineTypes, kEncoderTypes, kMaximumLimitBaseParams, @@ -10,30 +10,152 @@ const limit = 'maxBindGroups'; export const { g, description } = makeLimitTestGroup(limit); + + + + + + + + + + + + + +const kLimitToBindingLayout = [ +{ + name: 'maxSampledTexturesPerShaderStage', + entry: { + texture: {} + } +}, +{ + name: 'maxSamplersPerShaderStage', + entry: { + sampler: {} + } +}, +{ + name: 'maxUniformBuffersPerShaderStage', + entry: { + buffer: {} + } +}, +{ + name: 'maxStorageBuffersPerShaderStage', + entry: { + buffer: { + type: 'read-only-storage' + } + } +}, +{ + name: 'maxStorageTexturesPerShaderStage', + entry: { + storageTexture: { + access: 'write-only', + format: 'rgba8unorm', + viewDimension: '2d' + } + } +}]; + + +/** + * Yields all possible binding layout entries for a stage. + */ +function* getBindingLayoutEntriesForStage(device) { + for (const { name, entry } of kLimitToBindingLayout) { + const limit = device.limits[name]; + for (let i = 0; i < limit; ++i) { + yield entry; + } + } +} + +/** + * Yields all of the possible BindingLayoutEntryAndVisibility entries for a render pipeline + */ +function* getBindingLayoutEntriesForRenderPipeline( +device) +{ + const visibilities = [GPUShaderStage.VERTEX, GPUShaderStage.FRAGMENT]; + for (const visibility of visibilities) { + for (const bindEntryResourceType of getBindingLayoutEntriesForStage(device)) { + const entry = { + binding: 0, + visibility, + ...bindEntryResourceType + }; + yield entry; + } + } +} + +/** + * Returns the total possible bindings per render pipeline + */ +function getTotalPossibleBindingsPerRenderPipeline(device) { + const totalPossibleBindingsPerStage = + device.limits.maxSampledTexturesPerShaderStage + + device.limits.maxSamplersPerShaderStage + + device.limits.maxUniformBuffersPerShaderStage + + device.limits.maxStorageBuffersPerShaderStage + + device.limits.maxStorageTexturesPerShaderStage; + return totalPossibleBindingsPerStage * 2; +} + +/** + * Yields count GPUBindGroupLayoutEntries + */ +function* getBindingLayoutEntries( +device, +count) +{ + assert(count < getTotalPossibleBindingsPerRenderPipeline(device)); + const iter = getBindingLayoutEntriesForRenderPipeline(device); + for (; count > 0; --count) { + yield iter.next().value; + } +} + g.test('createPipelineLayout,at_over'). desc(`Test using createPipelineLayout at and over ${limit} limit`). params(kMaximumLimitBaseParams). fn(async (t) => { const { limitTest, testValueName } = t.params; + await t.testDeviceWithRequestedMaximumLimits( limitTest, testValueName, - async ({ device, testValue, shouldError }) => { - const bindGroupLayouts = range(testValue, (_i) => - device.createBindGroupLayout({ - entries: [ - { - binding: 0, - visibility: GPUShaderStage.VERTEX, - buffer: {} - }] - - }) + async ({ device, testValue, shouldError, actualLimit }) => { + const totalPossibleBindingsPerPipeline = getTotalPossibleBindingsPerRenderPipeline(device); + // Not sure what to do if we ever hit this but I think it's better to assert than silently skip. + assert( + testValue < totalPossibleBindingsPerPipeline, + `not enough possible bindings(${totalPossibleBindingsPerPipeline}) to test ${testValue} bindGroups` ); - await t.expectValidationError(() => { - device.createPipelineLayout({ bindGroupLayouts }); - }, shouldError); + const bindingDescriptions = []; + const bindGroupLayouts = [...getBindingLayoutEntries(device, testValue)].map((entry) => { + bindingDescriptions.push( + `${JSON.stringify(entry)} // group(${bindingDescriptions.length})` + ); + return device.createBindGroupLayout({ + entries: [entry] + }); + }); + + await t.expectValidationError( + () => { + device.createPipelineLayout({ bindGroupLayouts }); + }, + shouldError, + `testing ${testValue} bindGroups on maxBindGroups = ${actualLimit} with \n${bindingDescriptions.join( + '\n' + )}` + ); } ); }); @@ -76,8 +198,8 @@ fn(async (t) => { const lastIndex = testValue - 1; await t.testGPUBindingCommandsMixin( encoderType, - ({ mixin, bindGroup }) => { - mixin.setBindGroup(lastIndex, bindGroup); + ({ passEncoder, bindGroup }) => { + passEncoder.setBindGroup(lastIndex, bindGroup); }, shouldError, `shouldError: ${shouldError}, actualLimit: ${actualLimit}, testValue: ${lastIndex}` diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers.spec.js new file mode 100644 index 0000000000..7e4b0ccda1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers.spec.js @@ -0,0 +1,301 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kRenderEncoderTypes, kMaximumLimitBaseParams, + makeLimitTestGroup } from + +'./limit_utils.js'; + +const kVertexBufferBindGroupPreferences = ['vertexBuffers', 'bindGroups']; + + +const kLayoutTypes = ['auto', 'explicit']; + + +/** + * Given testValue, choose more vertex buffers or more bind groups based on preference + */ +function getNumBindGroupsAndNumVertexBuffers( +device, +preference, +testValue) +{ + switch (preference) { + case 'bindGroups':{ + const numBindGroups = Math.min(testValue, device.limits.maxBindGroups); + const numVertexBuffers = Math.max(0, testValue - numBindGroups); + return { numVertexBuffers, numBindGroups }; + } + case 'vertexBuffers':{ + const numVertexBuffers = Math.min(testValue, device.limits.maxVertexBuffers); + const numBindGroups = Math.max(0, testValue - numVertexBuffers); + return { numVertexBuffers, numBindGroups }; + } + } +} + +function createLayout(device, layoutType, numBindGroups) { + switch (layoutType) { + case 'auto': + return 'auto'; + case 'explicit':{ + const bindGroupLayouts = new Array(numBindGroups); + if (numBindGroups > 0) { + bindGroupLayouts.fill(device.createBindGroupLayout({ entries: [] })); + bindGroupLayouts[numBindGroups - 1] = device.createBindGroupLayout({ + entries: [ + { + binding: 0, + visibility: GPUShaderStage.VERTEX, + buffer: {} + }] + + }); + } + return device.createPipelineLayout({ bindGroupLayouts }); + } + } +} + +/** + * Generate a render pipeline that can be used to test maxBindGroupsPlusVertexBuffers + */ +function getPipelineDescriptor( +device, +preference, +testValue, +layoutType) +{ + // Get the numVertexBuffers and numBindGroups we could use given testValue as a total. + // We will only use 1 of each but we'll use the last index. + const { numVertexBuffers, numBindGroups } = getNumBindGroupsAndNumVertexBuffers( + device, + preference, + testValue + ); + + const layout = createLayout(device, layoutType, numBindGroups); + + const [bindGroupDecl, bindGroupUsage] = + numBindGroups === 0 ? + ['', ''] : + [`@group(${numBindGroups - 1}) @binding(0) var u: f32;`, `_ = u;`]; + + const [attribDecl, attribUsage] = + numVertexBuffers === 0 ? + ['', ''] : + ['@location(0) v: vec4f', `_ = v; // will use vertex buffer ${numVertexBuffers - 1}`]; + + const code = ` + ${bindGroupDecl} + + @vertex fn vs(${attribDecl}) -> @builtin(position) vec4f { + ${bindGroupUsage} + ${attribUsage} + return vec4f(0); + } + + @fragment fn fs() -> @location(0) vec4f { + return vec4f(0); + } + `; + + const module = device.createShaderModule({ code }); + const buffers = new Array(numVertexBuffers); + if (numVertexBuffers > 0) { + buffers[numVertexBuffers - 1] = { + arrayStride: 16, + attributes: [{ shaderLocation: 0, offset: 0, format: 'float32' }] + }; + } + + return { + code, + descriptor: { + layout, + vertex: { + module, + buffers + }, + fragment: { + module, + targets: [{ format: 'rgba8unorm' }] + } + } + }; +} + +const kExtraLimits = { + maxBindGroups: 'adapterLimit', + maxVertexBuffers: 'adapterLimit' +}; + +const limit = 'maxBindGroupsPlusVertexBuffers'; +export const { g, description } = makeLimitTestGroup(limit); + +g.test('createRenderPipeline,at_over'). +desc(`Test using at and over ${limit} limit in createRenderPipeline(Async).`). +params( + kMaximumLimitBaseParams. + combine('async', [false, true]). + beginSubcases(). + combine('preference', kVertexBufferBindGroupPreferences). + combine('layoutType', kLayoutTypes) +). +fn(async (t) => { + const { limitTest, testValueName, async, preference, layoutType } = t.params; + await t.testDeviceWithRequestedMaximumLimits( + limitTest, + testValueName, + async ({ device, testValue, shouldError, actualLimit }) => { + const maxUsableBindGroupsPlusVertexBuffers = + device.limits.maxBindGroups + device.limits.maxVertexBuffers; + t.skipIf( + maxUsableBindGroupsPlusVertexBuffers < actualLimit, + `can not test because the max usable bindGroups + vertexBuffers (${maxUsableBindGroupsPlusVertexBuffers}) is < maxBindGroupsAndVertexBuffers (${actualLimit})` + ); + t.skipIf( + maxUsableBindGroupsPlusVertexBuffers === actualLimit && testValue > actualLimit, + `can not test because the max usable bindGroups + vertexBuffers (${maxUsableBindGroupsPlusVertexBuffers}) === maxBindGroupsAndVertexBuffers (${actualLimit}) + but the testValue (${testValue}) > maxBindGroupsAndVertexBuffers (${actualLimit})` + ); + + const { code, descriptor } = getPipelineDescriptor( + device, + preference, + testValue, + layoutType + ); + + await t.testCreateRenderPipeline( + descriptor, + async, + shouldError, + `testValue: ${testValue}, actualLimit: ${actualLimit}, shouldError: ${shouldError}\n${code}` + ); + }, + kExtraLimits + ); +}); + +g.test('draw,at_over'). +desc(`Test using at and over ${limit} limit draw/drawIndexed/drawIndirect/drawIndexedIndirect`). +params( + kMaximumLimitBaseParams. + combine('encoderType', kRenderEncoderTypes). + beginSubcases(). + combine('preference', kVertexBufferBindGroupPreferences). + combine('drawType', ['draw', 'drawIndexed', 'drawIndirect', 'drawIndexedIndirect']) +). +fn(async (t) => { + const { limitTest, testValueName, encoderType, drawType, preference } = t.params; + await t.testDeviceWithRequestedMaximumLimits( + limitTest, + testValueName, + async ({ device, testValue, shouldError, actualLimit }) => { + const maxUsableVertexBuffers = Math.min( + device.limits.maxVertexBuffers, + device.limits.maxVertexAttributes + ); + const maxUsableBindGroupsPlusVertexBuffers = + device.limits.maxBindGroups + maxUsableVertexBuffers; + t.skipIf( + maxUsableBindGroupsPlusVertexBuffers < actualLimit, + `can not test because the max usable bindGroups + vertexBuffers (${maxUsableBindGroupsPlusVertexBuffers}) is < maxBindGroupsAndVertexBuffers (${actualLimit})` + ); + t.skipIf( + maxUsableBindGroupsPlusVertexBuffers === actualLimit && testValue > actualLimit, + `can not test because the max usable bindGroups + vertexBuffers (${maxUsableBindGroupsPlusVertexBuffers}) === maxBindGroupsAndVertexBuffers (${actualLimit}) + but the testValue (${testValue}) > maxBindGroupsAndVertexBuffers (${actualLimit})` + ); + + // Get the numVertexBuffers and numBindGroups we could use given testValue as a total. + // We will only use 1 of each but we'll use the last index. + const { numVertexBuffers, numBindGroups } = getNumBindGroupsAndNumVertexBuffers( + device, + preference, + testValue + ); + + const module = device.createShaderModule({ + code: ` + @vertex fn vs() -> @builtin(position) vec4f { + return vec4f(0); + } + @fragment fn fs() -> @location(0) vec4f { + return vec4f(0); + } + ` + }); + const pipeline = device.createRenderPipeline({ + layout: 'auto', + vertex: { module }, + fragment: { module, targets: [{ format: 'rgba8unorm' }] } + }); + + const vertexBuffer = device.createBuffer({ + size: 16, + usage: GPUBufferUsage.VERTEX + }); + t.trackForCleanup(vertexBuffer); + + await t.testGPURenderAndBindingCommandsMixin( + encoderType, + ({ bindGroup, passEncoder }) => { + // Set the last vertex buffer and clear it. This should have no effect + // unless there is a bug in bookkeeping in the implementation. + passEncoder.setVertexBuffer(device.limits.maxVertexBuffers - 1, vertexBuffer); + passEncoder.setVertexBuffer(device.limits.maxVertexBuffers - 1, null); + + // Set the last bindGroup and clear it. This should have no effect + // unless there is a bug in bookkeeping in the implementation. + passEncoder.setBindGroup(device.limits.maxBindGroups - 1, bindGroup); + passEncoder.setBindGroup(device.limits.maxBindGroups - 1, null); + + if (numVertexBuffers) { + passEncoder.setVertexBuffer(numVertexBuffers - 1, vertexBuffer); + } + + if (numBindGroups) { + passEncoder.setBindGroup(numBindGroups - 1, bindGroup); + } + + passEncoder.setPipeline(pipeline); + + const indirectBuffer = device.createBuffer({ + size: 20, + usage: GPUBufferUsage.INDIRECT + }); + t.trackForCleanup(indirectBuffer); + + const indexBuffer = device.createBuffer({ + size: 4, + usage: GPUBufferUsage.INDEX + }); + t.trackForCleanup(indexBuffer); + + switch (drawType) { + case 'draw': + passEncoder.draw(0); + break; + case 'drawIndexed': + passEncoder.setIndexBuffer(indexBuffer, 'uint16'); + passEncoder.drawIndexed(0); + break; + case 'drawIndirect': + passEncoder.drawIndirect(indirectBuffer, 0); + break; + case 'drawIndexedIndirect': + passEncoder.setIndexBuffer(indexBuffer, 'uint16'); + passEncoder.drawIndexedIndirect(indirectBuffer, 0); + break; + } + }, + shouldError, + `testValue: ${testValue}, actualLimit: ${actualLimit}, shouldError: ${shouldError}` + ); + + vertexBuffer.destroy(); + }, + kExtraLimits + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.spec.js index 2034364a5f..4eb76c7d38 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.spec.js @@ -12,7 +12,8 @@ import { const limit = 'maxComputeWorkgroupStorageSize'; export const { g, description } = makeLimitTestGroup(limit); -const kSmallestWorkgroupVarSize = 4; +// Each var is roundUp(16, SizeOf(T)) +const kSmallestWorkgroupVarSize = 16; const wgslF16Types = { f16: { alignOf: 2, sizeOf: 2, requireF16: true }, @@ -71,7 +72,9 @@ function getModuleForWorkgroupStorageSize(device, wgslType, size) { const { sizeOf, alignOf, requireF16 } = wgslTypes[wgslType]; const unitSize = align(sizeOf, alignOf); const units = Math.floor(size / unitSize); - const extra = (size - units * unitSize) / kSmallestWorkgroupVarSize; + const sizeUsed = align(units * unitSize, 16); + const sizeLeft = size - sizeUsed; + const extra = Math.floor(sizeLeft / kSmallestWorkgroupVarSize); const code = (requireF16 ? 'enable f16;\n' : '') + @@ -89,7 +92,7 @@ function getModuleForWorkgroupStorageSize(device, wgslType, size) { b: vec2f, }; var d0: array<${wgslType}, ${units}>; - ${extra ? `var d1: array;` : ''} + ${extra ? `var d1: array, ${extra}>;` : ''} @compute @workgroup_size(1) fn main() { _ = d0; ${extra ? '_ = d1;' : ''} diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxInterStageShaderComponents.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxInterStageShaderComponents.spec.js index 472630a7bf..8da125b1df 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxInterStageShaderComponents.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxInterStageShaderComponents.spec.js @@ -111,8 +111,12 @@ params( combine('sampleMaskOut', [false, true]) ). beforeAllSubcases((t) => { - if (t.isCompatibility && (t.params.sampleMaskIn || t.params.sampleMaskOut)) { - t.skip('sample_mask not supported in compatibility mode'); + if (t.isCompatibility) { + t.skipIf( + t.params.sampleMaskIn || t.params.sampleMaskOut, + 'sample_mask not supported in compatibility mode' + ); + t.skipIf(t.params.sampleIndex, 'sample_index not supported in compatibility mode'); } }). fn(async (t) => { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxSampledTexturesPerShaderStage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxSampledTexturesPerShaderStage.spec.js index 07d19ad596..36bc191474 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxSampledTexturesPerShaderStage.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxSampledTexturesPerShaderStage.spec.js @@ -1,8 +1,9 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { range, reorder, - kReorderOrderKeys } from + kReorderOrderKeys, + assert } from '../../../../../common/util/util.js'; import { kShaderStageCombinationsWithStage } from '../../../../capability_info.js'; @@ -13,8 +14,14 @@ import { kBindingCombinations, getPipelineTypeForBindingCombination, getPerStageWGSLForBindingCombination } from + './limit_utils.js'; +const kExtraLimits = { + maxBindingsPerBindGroup: 'adapterLimit', + maxBindGroups: 'adapterLimit' +}; + const limit = 'maxSampledTexturesPerShaderStage'; export const { g, description } = makeLimitTestGroup(limit); @@ -43,6 +50,9 @@ desc( Note: We also test order to make sure the implementation isn't just looking at just the last entry. + + Note: It's also possible the maxBindingsPerBindGroup is lower than + ${limit} in which case skip the test since we can not hit the limit. ` ). params( @@ -56,11 +66,17 @@ fn(async (t) => { limitTest, testValueName, async ({ device, testValue, shouldError }) => { + t.skipIf( + t.adapter.limits.maxBindingsPerBindGroup < testValue, + `maxBindingsPerBindGroup = ${t.adapter.limits.maxBindingsPerBindGroup} which is less than ${testValue}` + ); + await t.expectValidationError( () => createBindGroupLayout(device, visibility, order, testValue), shouldError ); - } + }, + kExtraLimits ); }); @@ -83,18 +99,30 @@ fn(async (t) => { await t.testDeviceWithRequestedMaximumLimits( limitTest, testValueName, - async ({ device, testValue, shouldError }) => { - const kNumGroups = 3; + async ({ device, testValue, shouldError, actualLimit }) => { + const maxBindingsPerBindGroup = Math.min( + t.device.limits.maxBindingsPerBindGroup, + actualLimit + ); + const kNumGroups = Math.ceil(testValue / maxBindingsPerBindGroup); + + // Not sure what to do in this case but best we get notified if it happens. + assert(kNumGroups <= t.device.limits.maxBindGroups); + const bindGroupLayouts = range(kNumGroups, (i) => { - const minInGroup = Math.floor(testValue / kNumGroups); - const numInGroup = i ? minInGroup : testValue - minInGroup * (kNumGroups - 1); + const numInGroup = Math.min( + testValue - i * maxBindingsPerBindGroup, + maxBindingsPerBindGroup + ); return createBindGroupLayout(device, visibility, order, numInGroup); }); + await t.expectValidationError( () => device.createPipelineLayout({ bindGroupLayouts }), shouldError ); - } + }, + kExtraLimits ); }); @@ -122,16 +150,21 @@ fn(async (t) => { limitTest, testValueName, async ({ device, testValue, actualLimit, shouldError }) => { + t.skipIf( + bindGroupTest === 'sameGroup' && testValue > device.limits.maxBindingsPerBindGroup, + `can not test ${testValue} bindings in same group because maxBindingsPerBindGroup = ${device.limits.maxBindingsPerBindGroup}` + ); + const code = getPerStageWGSLForBindingCombination( bindingCombination, order, bindGroupTest, (i, j) => `var u${j}_${i}: texture_2d`, (i, j) => `_ = textureLoad(u${j}_${i}, vec2u(0), 0);`, + device.limits.maxBindGroups, testValue ); const module = device.createShaderModule({ code }); - await t.testCreatePipeline( pipelineType, async, @@ -139,6 +172,7 @@ fn(async (t) => { shouldError, `actualLimit: ${actualLimit}, testValue: ${testValue}\n:${code}` ); - } + }, + kExtraLimits ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxSamplersPerShaderStage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxSamplersPerShaderStage.spec.js index c3bd3428ce..9c4dd735f1 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxSamplersPerShaderStage.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxSamplersPerShaderStage.spec.js @@ -1,8 +1,9 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { range, reorder, - kReorderOrderKeys } from + kReorderOrderKeys, + assert } from '../../../../../common/util/util.js'; import { kShaderStageCombinationsWithStage } from '../../../../capability_info.js'; @@ -13,8 +14,14 @@ import { kBindingCombinations, getPipelineTypeForBindingCombination, getPerStageWGSLForBindingCombination } from + './limit_utils.js'; +const kExtraLimits = { + maxBindingsPerBindGroup: 'adapterLimit', + maxBindGroups: 'adapterLimit' +}; + const limit = 'maxSamplersPerShaderStage'; export const { g, description } = makeLimitTestGroup(limit); @@ -56,11 +63,17 @@ fn(async (t) => { limitTest, testValueName, async ({ device, testValue, shouldError }) => { + t.skipIf( + t.adapter.limits.maxBindingsPerBindGroup < testValue, + `maxBindingsPerBindGroup = ${t.adapter.limits.maxBindingsPerBindGroup} which is less than ${testValue}` + ); + await t.expectValidationError( () => createBindGroupLayout(device, visibility, order, testValue), shouldError ); - } + }, + kExtraLimits ); }); @@ -83,18 +96,29 @@ fn(async (t) => { await t.testDeviceWithRequestedMaximumLimits( limitTest, testValueName, - async ({ device, testValue, shouldError }) => { - const kNumGroups = 3; + async ({ device, testValue, shouldError, actualLimit }) => { + const maxBindingsPerBindGroup = Math.min( + t.device.limits.maxBindingsPerBindGroup, + actualLimit + ); + const kNumGroups = Math.ceil(testValue / maxBindingsPerBindGroup); + + // Not sure what to do in this case but best we get notified if it happens. + assert(kNumGroups <= t.device.limits.maxBindGroups); + const bindGroupLayouts = range(kNumGroups, (i) => { - const minInGroup = Math.floor(testValue / kNumGroups); - const numInGroup = i ? minInGroup : testValue - minInGroup * (kNumGroups - 1); + const numInGroup = Math.min( + testValue - i * maxBindingsPerBindGroup, + maxBindingsPerBindGroup + ); return createBindGroupLayout(device, visibility, order, numInGroup); }); await t.expectValidationError( () => device.createPipelineLayout({ bindGroupLayouts }), shouldError ); - } + }, + kExtraLimits ); }); @@ -122,14 +146,27 @@ fn(async (t) => { limitTest, testValueName, async ({ device, testValue, actualLimit, shouldError }) => { + t.skipIf( + bindGroupTest === 'sameGroup' && testValue > device.limits.maxBindingsPerBindGroup, + `can not test ${testValue} bindings in same group because maxBindingsPerBindGroup = ${device.limits.maxBindingsPerBindGroup}` + ); + + // If this was false the texture binding would overlap the sampler bindings. + assert(testValue < device.limits.maxBindGroups * device.limits.maxBindingsPerBindGroup); + + // Put the texture on the last possible binding. + const groupNdx = device.limits.maxBindGroups - 1; + const bindingNdx = device.limits.maxBindingsPerBindGroup - 1; + const code = getPerStageWGSLForBindingCombination( bindingCombination, order, bindGroupTest, (i, j) => `var u${j}_${i}: sampler`, (i, j) => `_ = textureGather(0, tex, u${j}_${i}, vec2f(0));`, + device.limits.maxBindGroups, testValue, - '@group(3) @binding(1) var tex: texture_2d;' + `@group(${groupNdx}) @binding(${bindingNdx}) var tex: texture_2d;` ); const module = device.createShaderModule({ code }); @@ -140,6 +177,7 @@ fn(async (t) => { shouldError, `actualLimit: ${actualLimit}, testValue: ${testValue}\n:${code}` ); - } + }, + kExtraLimits ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxStorageBuffersPerShaderStage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxStorageBuffersPerShaderStage.spec.js index 1c09dcfcfd..14601e20a1 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxStorageBuffersPerShaderStage.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxStorageBuffersPerShaderStage.spec.js @@ -1,9 +1,11 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { range, reorder, - kReorderOrderKeys } from + kReorderOrderKeys, + assert } from '../../../../../common/util/util.js'; +import { kShaderStageCombinationsWithStage } from '../../../../capability_info.js'; import { GPUConst } from '../../../../constants.js'; import { @@ -13,8 +15,14 @@ import { kBindingCombinations, getPipelineTypeForBindingCombination, getPerStageWGSLForBindingCombination } from + './limit_utils.js'; +const kExtraLimits = { + maxBindingsPerBindGroup: 'adapterLimit', + maxBindGroups: 'adapterLimit' +}; + const limit = 'maxStorageBuffersPerShaderStage'; export const { g, description } = makeLimitTestGroup(limit); @@ -48,34 +56,31 @@ desc( ). params( kMaximumLimitBaseParams. - combine('visibility', [ - GPUConst.ShaderStage.VERTEX, - GPUConst.ShaderStage.FRAGMENT, - GPUConst.ShaderStage.VERTEX | GPUConst.ShaderStage.FRAGMENT, - GPUConst.ShaderStage.COMPUTE, - GPUConst.ShaderStage.VERTEX | GPUConst.ShaderStage.COMPUTE, - GPUConst.ShaderStage.FRAGMENT | GPUConst.ShaderStage.COMPUTE, - GPUConst.ShaderStage.VERTEX | GPUConst.ShaderStage.FRAGMENT | GPUConst.ShaderStage.COMPUTE] - ). + combine('visibility', kShaderStageCombinationsWithStage). combine('type', ['storage', 'read-only-storage']). - combine('order', kReorderOrderKeys) + combine('order', kReorderOrderKeys). + filter( + ({ visibility, type }) => + (visibility & GPUConst.ShaderStage.VERTEX) === 0 || type !== 'storage' + ) ). fn(async (t) => { const { limitTest, testValueName, visibility, order, type } = t.params; - if (visibility & GPUConst.ShaderStage.VERTEX && type === 'storage') { - // vertex stage does not support storage buffers - return; - } - await t.testDeviceWithRequestedMaximumLimits( limitTest, testValueName, async ({ device, testValue, shouldError }) => { + t.skipIf( + t.adapter.limits.maxBindingsPerBindGroup < testValue, + `maxBindingsPerBindGroup = ${t.adapter.limits.maxBindingsPerBindGroup} which is less than ${testValue}` + ); + await t.expectValidationError(() => { createBindGroupLayout(device, visibility, type, order, testValue); }, shouldError); - } + }, + kExtraLimits ); }); @@ -90,41 +95,44 @@ desc( ). params( kMaximumLimitBaseParams. - combine('visibility', [ - GPUConst.ShaderStage.VERTEX, - GPUConst.ShaderStage.FRAGMENT, - GPUConst.ShaderStage.VERTEX | GPUConst.ShaderStage.FRAGMENT, - GPUConst.ShaderStage.COMPUTE, - GPUConst.ShaderStage.VERTEX | GPUConst.ShaderStage.COMPUTE, - GPUConst.ShaderStage.FRAGMENT | GPUConst.ShaderStage.COMPUTE, - GPUConst.ShaderStage.VERTEX | GPUConst.ShaderStage.FRAGMENT | GPUConst.ShaderStage.COMPUTE] - ). + combine('visibility', kShaderStageCombinationsWithStage). combine('type', ['storage', 'read-only-storage']). - combine('order', kReorderOrderKeys) + combine('order', kReorderOrderKeys). + filter( + ({ visibility, type }) => + (visibility & GPUConst.ShaderStage.VERTEX) === 0 || type !== 'storage' + ) ). fn(async (t) => { const { limitTest, testValueName, visibility, order, type } = t.params; - if (visibility & GPUConst.ShaderStage.VERTEX && type === 'storage') { - // vertex stage does not support storage buffers - return; - } - await t.testDeviceWithRequestedMaximumLimits( limitTest, testValueName, - async ({ device, testValue, shouldError }) => { - const kNumGroups = 3; + async ({ device, testValue, shouldError, actualLimit }) => { + const maxBindingsPerBindGroup = Math.min( + t.device.limits.maxBindingsPerBindGroup, + actualLimit + ); + const kNumGroups = Math.ceil(testValue / maxBindingsPerBindGroup); + + // Not sure what to do in this case but best we get notified if it happens. + assert(kNumGroups <= t.device.limits.maxBindGroups); + const bindGroupLayouts = range(kNumGroups, (i) => { - const minInGroup = Math.floor(testValue / kNumGroups); - const numInGroup = i ? minInGroup : testValue - minInGroup * (kNumGroups - 1); + const numInGroup = Math.min( + testValue - i * maxBindingsPerBindGroup, + maxBindingsPerBindGroup + ); return createBindGroupLayout(device, visibility, type, order, numInGroup); }); + await t.expectValidationError( () => device.createPipelineLayout({ bindGroupLayouts }), shouldError ); - } + }, + kExtraLimits ); }); @@ -152,12 +160,18 @@ fn(async (t) => { limitTest, testValueName, async ({ device, testValue, actualLimit, shouldError }) => { + t.skipIf( + bindGroupTest === 'sameGroup' && testValue > device.limits.maxBindingsPerBindGroup, + `can not test ${testValue} bindings in same group because maxBindingsPerBindGroup = ${device.limits.maxBindingsPerBindGroup}` + ); + const code = getPerStageWGSLForBindingCombination( bindingCombination, order, bindGroupTest, (i, j) => `var u${j}_${i}: f32`, (i, j) => `_ = u${j}_${i};`, + device.limits.maxBindGroups, testValue ); const module = device.createShaderModule({ code }); @@ -169,6 +183,7 @@ fn(async (t) => { shouldError, `actualLimit: ${actualLimit}, testValue: ${testValue}\n:${code}` ); - } + }, + kExtraLimits ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxStorageTexturesPerShaderStage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxStorageTexturesPerShaderStage.spec.js index 5005ae35fe..a9eea3196a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxStorageTexturesPerShaderStage.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxStorageTexturesPerShaderStage.spec.js @@ -2,7 +2,8 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { range, reorder, - kReorderOrderKeys } from + kReorderOrderKeys, + assert } from '../../../../../common/util/util.js'; import { GPUConst } from '../../../../constants.js'; @@ -13,8 +14,14 @@ import { getPerStageWGSLForBindingCombinationStorageTextures, getPipelineTypeForBindingCombination } from + './limit_utils.js'; +const kExtraLimits = { + maxBindingsPerBindGroup: 'adapterLimit', + maxBindGroups: 'adapterLimit' +}; + const limit = 'maxStorageTexturesPerShaderStage'; export const { g, description } = makeLimitTestGroup(limit); @@ -60,11 +67,17 @@ fn(async (t) => { limitTest, testValueName, async ({ device, testValue, shouldError }) => { + t.skipIf( + t.adapter.limits.maxBindingsPerBindGroup < testValue, + `maxBindingsPerBindGroup = ${t.adapter.limits.maxBindingsPerBindGroup} which is less than ${testValue}` + ); + await t.expectValidationError( () => createBindGroupLayout(device, visibility, order, testValue), shouldError ); - } + }, + kExtraLimits ); }); @@ -91,18 +104,30 @@ fn(async (t) => { await t.testDeviceWithRequestedMaximumLimits( limitTest, testValueName, - async ({ device, testValue, shouldError }) => { - const kNumGroups = 3; + async ({ device, testValue, shouldError, actualLimit }) => { + const maxBindingsPerBindGroup = Math.min( + t.device.limits.maxBindingsPerBindGroup, + actualLimit + ); + const kNumGroups = Math.ceil(testValue / maxBindingsPerBindGroup); + + // Not sure what to do in this case but best we get notified if it happens. + assert(kNumGroups <= t.device.limits.maxBindGroups); + const bindGroupLayouts = range(kNumGroups, (i) => { - const minInGroup = Math.floor(testValue / kNumGroups); - const numInGroup = i ? minInGroup : testValue - minInGroup * (kNumGroups - 1); + const numInGroup = Math.min( + testValue - i * maxBindingsPerBindGroup, + maxBindingsPerBindGroup + ); return createBindGroupLayout(device, visibility, order, numInGroup); }); + await t.expectValidationError( () => device.createPipelineLayout({ bindGroupLayouts }), shouldError ); - } + }, + kExtraLimits ); }); @@ -130,6 +155,11 @@ fn(async (t) => { limitTest, testValueName, async ({ device, testValue, actualLimit, shouldError }) => { + t.skipIf( + bindGroupTest === 'sameGroup' && testValue > device.limits.maxBindingsPerBindGroup, + `can not test ${testValue} bindings in same group because maxBindingsPerBindGroup = ${device.limits.maxBindingsPerBindGroup}` + ); + if (bindingCombination === 'fragment') { return; } @@ -140,6 +170,7 @@ fn(async (t) => { bindGroupTest, (i, j) => `var u${j}_${i}: texture_storage_2d`, (i, j) => `textureStore(u${j}_${i}, vec2u(0), vec4f(1));`, + device.limits.maxBindGroups, testValue ); const module = device.createShaderModule({ code }); @@ -151,6 +182,7 @@ fn(async (t) => { shouldError, `actualLimit: ${actualLimit}, testValue: ${testValue}\n:${code}` ); - } + }, + kExtraLimits ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxUniformBuffersPerShaderStage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxUniformBuffersPerShaderStage.spec.js index 191493046a..eb2330547d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxUniformBuffersPerShaderStage.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxUniformBuffersPerShaderStage.spec.js @@ -1,8 +1,9 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { range, reorder, - kReorderOrderKeys } from + kReorderOrderKeys, + assert } from '../../../../../common/util/util.js'; import { kShaderStageCombinationsWithStage } from '../../../../capability_info.js'; @@ -13,8 +14,14 @@ import { kBindingCombinations, getPipelineTypeForBindingCombination, getPerStageWGSLForBindingCombination } from + './limit_utils.js'; +const kExtraLimits = { + maxBindingsPerBindGroup: 'adapterLimit', + maxBindGroups: 'adapterLimit' +}; + const limit = 'maxUniformBuffersPerShaderStage'; export const { g, description } = makeLimitTestGroup(limit); @@ -56,11 +63,17 @@ fn(async (t) => { limitTest, testValueName, async ({ device, testValue, shouldError }) => { + t.skipIf( + t.adapter.limits.maxBindingsPerBindGroup < testValue, + `maxBindingsPerBindGroup = ${t.adapter.limits.maxBindingsPerBindGroup} which is less than ${testValue}` + ); + await t.expectValidationError( () => createBindGroupLayout(device, visibility, order, testValue), shouldError ); - } + }, + kExtraLimits ); }); @@ -83,18 +96,30 @@ fn(async (t) => { await t.testDeviceWithRequestedMaximumLimits( limitTest, testValueName, - async ({ device, testValue, shouldError }) => { - const kNumGroups = 3; + async ({ device, testValue, shouldError, actualLimit }) => { + const maxBindingsPerBindGroup = Math.min( + t.device.limits.maxBindingsPerBindGroup, + actualLimit + ); + const kNumGroups = Math.ceil(testValue / maxBindingsPerBindGroup); + + // Not sure what to do in this case but best we get notified if it happens. + assert(kNumGroups <= t.device.limits.maxBindGroups); + const bindGroupLayouts = range(kNumGroups, (i) => { - const minInGroup = Math.floor(testValue / kNumGroups); - const numInGroup = i ? minInGroup : testValue - minInGroup * (kNumGroups - 1); + const numInGroup = Math.min( + testValue - i * maxBindingsPerBindGroup, + maxBindingsPerBindGroup + ); return createBindGroupLayout(device, visibility, order, numInGroup); }); + await t.expectValidationError( () => device.createPipelineLayout({ bindGroupLayouts }), shouldError ); - } + }, + kExtraLimits ); }); @@ -122,12 +147,18 @@ fn(async (t) => { limitTest, testValueName, async ({ device, testValue, actualLimit, shouldError }) => { + t.skipIf( + bindGroupTest === 'sameGroup' && testValue > device.limits.maxBindingsPerBindGroup, + `can not test ${testValue} bindings in same group because maxBindingsPerBindGroup = ${device.limits.maxBindingsPerBindGroup}` + ); + const code = getPerStageWGSLForBindingCombination( bindingCombination, order, bindGroupTest, (i, j) => `var u${j}_${i}: f32`, (i, j) => `_ = u${j}_${i};`, + device.limits.maxBindGroups, testValue ); const module = device.createShaderModule({ code }); @@ -139,6 +170,7 @@ fn(async (t) => { shouldError, `actualLimit: ${actualLimit}, testValue: ${testValue}\n:${code}` ); - } + }, + kExtraLimits ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxVertexBuffers.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxVertexBuffers.spec.js index 860c40687e..142297311a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxVertexBuffers.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/limits/maxVertexBuffers.spec.js @@ -1,41 +1,23 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { range } from '../../../../../common/util/util.js';import { kRenderEncoderTypes, kMaximumLimitBaseParams, makeLimitTestGroup } from './limit_utils.js'; - -const kPipelineTypes = ['withoutLocations', 'withLocations']; - +**/import { kRenderEncoderTypes, kMaximumLimitBaseParams, makeLimitTestGroup } from './limit_utils.js';function getPipelineDescriptor(device, testValue) { + const module = device.createShaderModule({ + code: ` + @vertex fn vs(@location(0) p: vec4f) -> @builtin(position) vec4f { + return p; + }` + }); + const buffers = new Array(testValue); + buffers[testValue - 1] = { + arrayStride: 16, + attributes: [{ shaderLocation: 0, offset: 0, format: 'float32' }] + }; -function getPipelineDescriptor( -device, -pipelineType, -testValue) -{ - const code = - pipelineType === 'withLocations' ? - ` - struct VSInput { - ${range(testValue, (i) => `@location(${i}) p${i}: f32,`).join('\n')} - } - @vertex fn vs(v: VSInput) -> @builtin(position) vec4f { - let x = ${range(testValue, (i) => `v.p${i}`).join(' + ')}; - return vec4f(x, 0, 0, 1); - } - ` : - ` - @vertex fn vs() -> @builtin(position) vec4f { - return vec4f(0); - } - `; - const module = device.createShaderModule({ code }); return { layout: 'auto', vertex: { module, - entryPoint: 'vs', - buffers: range(testValue, (i) => ({ - arrayStride: 32, - attributes: [{ shaderLocation: i, offset: 0, format: 'float32' }] - })) + buffers } }; } @@ -45,18 +27,22 @@ export const { g, description } = makeLimitTestGroup(limit); g.test('createRenderPipeline,at_over'). desc(`Test using at and over ${limit} limit in createRenderPipeline(Async)`). -params( - kMaximumLimitBaseParams.combine('async', [false, true]).combine('pipelineType', kPipelineTypes) -). +params(kMaximumLimitBaseParams.combine('async', [false, true])). fn(async (t) => { - const { limitTest, testValueName, async, pipelineType } = t.params; + const { limitTest, testValueName, async } = t.params; await t.testDeviceWithRequestedMaximumLimits( limitTest, testValueName, - async ({ device, testValue, shouldError }) => { - const pipelineDescriptor = getPipelineDescriptor(device, pipelineType, testValue); + async ({ device, testValue, shouldError, actualLimit }) => { + const pipelineDescriptor = getPipelineDescriptor(device, testValue); + const lastIndex = testValue - 1; - await t.testCreateRenderPipeline(pipelineDescriptor, async, shouldError); + await t.testCreateRenderPipeline( + pipelineDescriptor, + async, + shouldError, + `lastIndex: ${lastIndex}, actualLimit: ${actualLimit}, shouldError: ${shouldError}` + ); } ); }); @@ -77,10 +63,10 @@ fn(async (t) => { usage: GPUBufferUsage.VERTEX }); - await t.testGPURenderCommandsMixin( + await t.testGPURenderAndBindingCommandsMixin( encoderType, - ({ mixin }) => { - mixin.setVertexBuffer(lastIndex, buffer); + ({ passEncoder }) => { + passEncoder.setVertexBuffer(lastIndex, buffer); }, shouldError, `lastIndex: ${lastIndex}, actualLimit: ${actualLimit}, shouldError: ${shouldError}` diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/compute_pipeline.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/compute_pipeline.spec.js index 3d2c5a7641..a9ad3c4476 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/compute_pipeline.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/compute_pipeline.spec.js @@ -5,9 +5,16 @@ createComputePipeline and createComputePipelineAsync validation tests. Note: entry point matching tests are in shader_module/entry_point.spec.ts `;import { makeTestGroup } from '../../../common/framework/test_group.js'; +import { keysOf } from '../../../common/util/data_tables.js'; import { kValue } from '../../util/constants.js'; import { getShaderWithEntryPoint } from '../../util/shader.js'; +import { + kAPIResources, + getWGSLShaderForResource, + getAPIBindGroupLayoutForResource, + doResourcesMatch } from +'./utils.js'; import { ValidationTest } from './validation_test.js'; class F extends ValidationTest { @@ -689,4 +696,47 @@ fn((t) => { testFn(1, 1, true); testFn(maxVec4Count + 1, 0, false); testFn(0, maxMat4Count + 1, false); +}); + +g.test('resource_compatibility'). +desc( + 'Tests validation of resource (bind group) compatibility between pipeline layout and WGSL shader' +). +params((u) => +u // +.combine('apiResource', keysOf(kAPIResources)). +beginSubcases(). +combine('isAsync', [true, false]). +combine('wgslResource', keysOf(kAPIResources)) +). +fn((t) => { + const apiResource = kAPIResources[t.params.apiResource]; + const wgslResource = kAPIResources[t.params.wgslResource]; + t.skipIf( + wgslResource.storageTexture !== undefined && + wgslResource.storageTexture.access !== 'write-only' && + !t.hasLanguageFeature('readonly_and_readwrite_storage_textures'), + 'Storage textures require language feature' + ); + + const layout = t.device.createPipelineLayout({ + bindGroupLayouts: [ + getAPIBindGroupLayoutForResource(t.device, GPUShaderStage.COMPUTE, apiResource)] + + }); + + const descriptor = { + layout, + compute: { + module: t.device.createShaderModule({ + code: getWGSLShaderForResource('compute', wgslResource) + }), + entryPoint: 'main' + } + }; + t.doCreateComputePipelineTest( + t.params.isAsync, + doResourcesMatch(apiResource, wgslResource), + descriptor + ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroup.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroup.spec.js index 15691f4bf7..283fe97fd2 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroup.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroup.spec.js @@ -8,6 +8,7 @@ import { assert, makeValueTestVariant, unreachable } from '../../../common/util/util.js'; import { allBindingEntries, + bindingTypeInfo, bufferBindingEntries, bufferBindingTypeInfo, @@ -106,7 +107,7 @@ g.test('binding_must_contain_resource_defined_in_layout'). desc( 'Test that only compatible resource types specified in the BindGroupLayout are allowed for each entry.' ). -paramsSubcasesOnly((u) => +params((u) => u // .combine('resourceType', kBindableResources). combine('entry', allBindingEntries(false)) @@ -121,6 +122,17 @@ fn((t) => { const resource = t.getBindingResource(resourceType); + const IsStorageTextureResourceType = (resourceType) => { + switch (resourceType) { + case 'readonlyStorageTex': + case 'readwriteStorageTex': + case 'writeonlyStorageTex': + return true; + default: + return false; + } + }; + let resourceBindingIsCompatible; switch (info.resource) { // Either type of sampler may be bound to a filtering sampler binding. @@ -131,6 +143,11 @@ fn((t) => { case 'nonFiltSamp': resourceBindingIsCompatible = resourceType === 'nonFiltSamp'; break; + case 'readonlyStorageTex': + case 'readwriteStorageTex': + case 'writeonlyStorageTex': + resourceBindingIsCompatible = IsStorageTextureResourceType(resourceType); + break; default: resourceBindingIsCompatible = info.resource === resourceType; break; @@ -166,7 +183,7 @@ fn((t) => { const descriptor = { size: { width: 16, height: 16, depthOrArrayLayers: 1 }, - format: 'rgba8unorm', + format: 'r32float', usage: appliedUsage, sampleCount: info.resource === 'sampledTexMS' ? 4 : 1 }; @@ -313,6 +330,19 @@ fn((t) => { }); t.skipIfTextureViewDimensionNotSupported(viewDimension, dimension); + if (t.isCompatibility && texture.dimension === '2d') { + if (depthOrArrayLayers === 1) { + t.skipIf( + viewDimension !== '2d', + '1 layer 2d textures default to textureBindingViewDimension: "2d" in compat mode' + ); + } else { + t.skipIf( + viewDimension !== '2d-array', + '> 1 layer 2d textures default to textureBindingViewDimension "2d-array" in compat mode' + ); + } + } const shouldError = viewDimension !== dimension; const textureView = texture.createView({ dimension }); @@ -526,9 +556,7 @@ fn((t) => { g.test('texture,resource_state'). desc('Test bind group creation with various texture resource states'). paramsSubcasesOnly((u) => -u. -combine('state', kResourceStates). -combine('entry', sampledAndStorageBindingEntries(true, 'rgba8unorm')) +u.combine('state', kResourceStates).combine('entry', sampledAndStorageBindingEntries(true)) ). fn((t) => { const { state, entry } = t.params; @@ -548,10 +576,11 @@ fn((t) => { const usage = entry.texture?.multisampled ? info.usage | GPUConst.TextureUsage.RENDER_ATTACHMENT : info.usage; + const format = entry.storageTexture !== undefined ? 'r32float' : 'rgba8unorm'; const texture = t.createTextureWithState(state, { usage, size: [1, 1], - format: 'rgba8unorm', + format, sampleCount: entry.texture?.multisampled ? 4 : 1 }); @@ -626,7 +655,9 @@ combine('entry', [ { buffer: { type: 'storage' } }, { sampler: { type: 'filtering' } }, { texture: { multisampled: false } }, -{ storageTexture: { access: 'write-only', format: 'rgba8unorm' } }] +{ storageTexture: { access: 'write-only', format: 'r32float' } }, +{ storageTexture: { access: 'read-only', format: 'r32float' } }, +{ storageTexture: { access: 'read-write', format: 'r32float' } }] ). beginSubcases(). combineWithParams([ @@ -784,6 +815,10 @@ u // .combine('storageTextureFormat', kStorageTextureFormats). combine('resourceFormat', kStorageTextureFormats) ). +beforeAllSubcases((t) => { + const { storageTextureFormat, resourceFormat } = t.params; + t.skipIfTextureFormatNotUsableAsStorageTexture(storageTextureFormat, resourceFormat); +}). fn((t) => { const { storageTextureFormat, resourceFormat } = t.params; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js index 580a64af4f..b5d98f8d44 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js @@ -163,8 +163,10 @@ combine('access', [undefined, ...kStorageTextureAccessValues]) fn((t) => { const { shaderStage, access } = t.params; + const appliedAccess = access ?? 'write-only'; const success = !( - (access ?? 'write-only') === 'write-only' && shaderStage & GPUShaderStage.VERTEX); + // If visibility includes VERETX, storageTexture.access must be "read-only" + shaderStage & GPUShaderStage.VERTEX && appliedAccess !== 'read-only'); t.expectValidationError(() => { @@ -173,7 +175,7 @@ fn((t) => { { binding: 0, visibility: shaderStage, - storageTexture: { access, format: 'rgba8unorm' } + storageTexture: { access, format: 'r32uint' } }] }); @@ -436,29 +438,36 @@ fn((t) => { g.test('storage_texture,formats'). desc( ` - Test that a validation error is generated if the format doesn't support the storage usage. + Test that a validation error is generated if the format doesn't support the storage usage. A + validation error is also generated if the format doesn't support the 'read-write' storage access + when the storage access is 'read-write'. ` ). -params((u) => u.combine('format', kAllTextureFormats)). +params((u) => +u // +.combine('format', kAllTextureFormats) // +.combine('access', kStorageTextureAccessValues) +). beforeAllSubcases((t) => { t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format); + t.skipIfTextureFormatNotUsableAsStorageTexture(t.params.format); }). fn((t) => { - const { format } = t.params; + const { format, access } = t.params; const info = kTextureFormatInfo[format]; - t.expectValidationError( - () => { - t.device.createBindGroupLayout({ - entries: [ - { - binding: 0, - visibility: GPUShaderStage.COMPUTE, - storageTexture: { format } - }] - - }); - }, - !info.color?.storage - ); + const success = + info.color?.storage && !(access === 'read-write' && !info.color?.readWriteStorage); + + t.expectValidationError(() => { + t.device.createBindGroupLayout({ + entries: [ + { + binding: 0, + visibility: GPUShaderStage.COMPUTE, + storageTexture: { format, access } + }] + + }); + }, !success); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createTexture.spec.js index d2ea68ef85..57c80946c0 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createTexture.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createTexture.spec.js @@ -6,7 +6,7 @@ import { assert, makeValueTestVariant } from '../../../common/util/util.js'; import { kTextureDimensions, kTextureUsages } from '../../capability_info.js'; import { GPUConst } from '../../constants.js'; import { - kTextureFormats, + kAllTextureFormats, kTextureFormatInfo, kCompressedTextureFormats, kUncompressedTextureFormats, @@ -14,7 +14,8 @@ import { kFeaturesForFormats, filterFormatsByFeature, viewCompatible, - textureDimensionAndFormatCompatible } from + textureDimensionAndFormatCompatible, + isTextureFormatUsableAsStorageFormat } from '../../format_info.js'; import { maxMipLevelCount } from '../../util/texture/base.js'; @@ -103,7 +104,9 @@ desc( `Test every dimension type on every format. Note that compressed formats and depth/stencil formats are not valid for 1D/3D dimension types.` ). params((u) => -u.combine('dimension', [undefined, ...kTextureDimensions]).combine('format', kTextureFormats) +u // +.combine('dimension', [undefined, ...kTextureDimensions]). +combine('format', kAllTextureFormats) ). beforeAllSubcases((t) => { const { format } = t.params; @@ -135,7 +138,7 @@ desc( params((u) => u. combine('dimension', [undefined, ...kTextureDimensions]). -combine('format', kTextureFormats). +combine('format', kAllTextureFormats). beginSubcases(). combine('mipLevelCount', [1, 2, 3, 6, 7]) // Filter out incompatible dimension type and format combinations. @@ -270,7 +273,7 @@ desc( params((u) => u. combine('dimension', [undefined, '2d']). -combine('format', kTextureFormats). +combine('format', kAllTextureFormats). beginSubcases(). combine('sampleCount', [0, 1, 2, 4, 8, 16, 32, 256]) ). @@ -296,7 +299,7 @@ fn((t) => { usage }; - const success = sampleCount === 1 || sampleCount === 4 && info.multisample && info.renderable; + const success = sampleCount === 1 || sampleCount === 4 && info.multisample; t.expectValidationError(() => { t.device.createTexture(descriptor); @@ -317,7 +320,7 @@ desc( params((u) => u. combine('dimension', [undefined, ...kTextureDimensions]). -combine('format', kTextureFormats). +combine('format', kAllTextureFormats). beginSubcases(). combine('sampleCount', [1, 4]). combine('arrayLayerCount', [1, 2]). @@ -372,8 +375,12 @@ fn((t) => { usage }; + const satisfyWithStorageUsageRequirement = + (usage & GPUConst.TextureUsage.STORAGE_BINDING) === 0 || + isTextureFormatUsableAsStorageFormat(format, t.isCompatibility); + const success = - sampleCount === 1 || + sampleCount === 1 && satisfyWithStorageUsageRequirement || sampleCount === 4 && ( dimension === '2d' || dimension === undefined) && kTextureFormatInfo[format].multisample && @@ -589,6 +596,7 @@ params((u) => u. combine('dimension', [undefined, '2d']). combine('format', kCompressedTextureFormats). +beginSubcases(). expand('sizeVariant', (p) => { const { blockWidth, blockHeight } = kTextureFormatInfo[p.format]; return [ @@ -1026,7 +1034,7 @@ desc( params((u) => u. combine('dimension', [undefined, ...kTextureDimensions]). -combine('format', kTextureFormats). +combine('format', kAllTextureFormats). beginSubcases() // If usage0 and usage1 are the same, then the usage being test is a single usage. Otherwise, it is a combined usage. .combine('usage0', kTextureUsages). @@ -1058,12 +1066,13 @@ fn((t) => { // Note that we unconditionally test copy usages for all formats. We don't check copySrc/copyDst in kTextureFormatInfo in capability_info.js // if (!info.copySrc && (usage & GPUTextureUsage.COPY_SRC) !== 0) success = false; // if (!info.copyDst && (usage & GPUTextureUsage.COPY_DST) !== 0) success = false; - if (!info.color?.storage && (usage & GPUTextureUsage.STORAGE_BINDING) !== 0) success = false; - if ( - (!info.renderable || appliedDimension !== '2d') && - (usage & GPUTextureUsage.RENDER_ATTACHMENT) !== 0) - - success = false; + if (usage & GPUTextureUsage.STORAGE_BINDING) { + if (!isTextureFormatUsableAsStorageFormat(format, t.isCompatibility)) success = false; + } + if (usage & GPUTextureUsage.RENDER_ATTACHMENT) { + if (appliedDimension === '1d') success = false; + if (info.color && !info.colorRender) success = false; + } t.expectValidationError(() => { t.device.createTexture(descriptor); @@ -1080,10 +1089,10 @@ combine('formatFeature', kFeaturesForFormats). combine('viewFormatFeature', kFeaturesForFormats). beginSubcases(). expand('format', ({ formatFeature }) => -filterFormatsByFeature(formatFeature, kTextureFormats) +filterFormatsByFeature(formatFeature, kAllTextureFormats) ). expand('viewFormat', ({ viewFormatFeature }) => -filterFormatsByFeature(viewFormatFeature, kTextureFormats) +filterFormatsByFeature(viewFormatFeature, kAllTextureFormats) ) ). beforeAllSubcases((t) => { @@ -1096,7 +1105,7 @@ fn((t) => { t.skipIfTextureFormatNotSupported(format, viewFormat); - const compatible = viewCompatible(format, viewFormat); + const compatible = viewCompatible(t.isCompatibility, format, viewFormat); // Test the viewFormat in the list. t.expectValidationError(() => { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createView.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createView.spec.js index b001cb0b7a..9cf00c5d0b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createView.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createView.spec.js @@ -10,7 +10,7 @@ import { '../../capability_info.js'; import { kTextureFormatInfo, - kTextureFormats, + kAllTextureFormats, kFeaturesForFormats, filterFormatsByFeature, viewCompatible } from @@ -39,10 +39,10 @@ combine('textureFormatFeature', kFeaturesForFormats). combine('viewFormatFeature', kFeaturesForFormats). beginSubcases(). expand('textureFormat', ({ textureFormatFeature }) => -filterFormatsByFeature(textureFormatFeature, kTextureFormats) +filterFormatsByFeature(textureFormatFeature, kAllTextureFormats) ). expand('viewFormat', ({ viewFormatFeature }) => -filterFormatsByFeature(viewFormatFeature, [undefined, ...kTextureFormats]) +filterFormatsByFeature(viewFormatFeature, [undefined, ...kAllTextureFormats]) ). combine('useViewFormatList', [false, true]) ). @@ -56,7 +56,8 @@ fn((t) => { t.skipIfTextureFormatNotSupported(textureFormat, viewFormat); - const compatible = viewFormat === undefined || viewCompatible(textureFormat, viewFormat); + const compatible = + viewFormat === undefined || viewCompatible(t.isCompatibility, textureFormat, viewFormat); const texture = t.device.createTexture({ format: textureFormat, @@ -123,7 +124,7 @@ desc( ). params((u) => u // -.combine('format', kTextureFormats). +.combine('format', kAllTextureFormats). combine('aspect', kTextureAspects) ). beforeAllSubcases((t) => { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.js index 00bf4e83d8..aa14c176c4 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.js @@ -6,7 +6,7 @@ copyTextureToTexture tests. import { kTextureUsages, kTextureDimensions } from '../../../../capability_info.js'; import { kTextureFormatInfo, - kTextureFormats, + kAllTextureFormats, kCompressedTextureFormats, kDepthStencilFormats, kFeaturesForFormats, @@ -255,6 +255,12 @@ u // .combine('srcSampleCount', [1, 4]). combine('dstSampleCount', [1, 4]) ). +beforeAllSubcases((t) => { + t.skipIf( + t.isCompatibility && (t.params.srcSampleCount !== 1 || t.params.dstSampleCount !== 1), + 'multisample textures are not copyable in compatibility mode' + ); +}). fn((t) => { const { srcSampleCount, dstSampleCount } = t.params; @@ -307,6 +313,9 @@ combine('dstCopyOrigin', [ expand('copyWidth', (p) => [32 - Math.max(p.srcCopyOrigin.x, p.dstCopyOrigin.x), 16]). expand('copyHeight', (p) => [16 - Math.max(p.srcCopyOrigin.y, p.dstCopyOrigin.y), 8]) ). +beforeAllSubcases((t) => { + t.skipIf(t.isCompatibility, 'multisample textures are not copyable in compatibility mode'); +}). fn((t) => { const { srcCopyOrigin, dstCopyOrigin, copyWidth, copyHeight } = t.params; @@ -351,10 +360,10 @@ combine('srcFormatFeature', kFeaturesForFormats). combine('dstFormatFeature', kFeaturesForFormats). beginSubcases(). expand('srcFormat', ({ srcFormatFeature }) => -filterFormatsByFeature(srcFormatFeature, kTextureFormats) +filterFormatsByFeature(srcFormatFeature, kAllTextureFormats) ). expand('dstFormat', ({ dstFormatFeature }) => -filterFormatsByFeature(dstFormatFeature, kTextureFormats) +filterFormatsByFeature(dstFormatFeature, kAllTextureFormats) ) ). beforeAllSubcases((t) => { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.js index b78322cbff..a22353bc04 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.js @@ -196,10 +196,7 @@ fn((t) => { g.test('depth_stencil_readonly'). desc( ` - Tests that createRenderBundleEncoder validation of depthReadOnly and stencilReadOnly - - With depth-only formats - - With stencil-only formats - - With depth-stencil-combined formats + Test that allow combinations of depth-stencil format, depthReadOnly and stencilReadOnly are allowed. ` ). params((u) => @@ -215,44 +212,9 @@ beforeAllSubcases((t) => { }). fn((t) => { const { depthStencilFormat, depthReadOnly, stencilReadOnly } = t.params; - - let shouldError = false; - if ( - kTextureFormatInfo[depthStencilFormat].depth && - kTextureFormatInfo[depthStencilFormat].stencil && - depthReadOnly !== stencilReadOnly) - { - shouldError = true; - } - - t.expectValidationError(() => { - t.device.createRenderBundleEncoder({ - colorFormats: [], - depthStencilFormat, - depthReadOnly, - stencilReadOnly - }); - }, shouldError); -}); - -g.test('depth_stencil_readonly_with_undefined_depth'). -desc( - ` - Tests that createRenderBundleEncoder validation of depthReadOnly and stencilReadOnly is ignored - if there is no depthStencilFormat set. - ` -). -params((u) => -u // -.beginSubcases(). -combine('depthReadOnly', [false, true]). -combine('stencilReadOnly', [false, true]) -). -fn((t) => { - const { depthReadOnly, stencilReadOnly } = t.params; - t.device.createRenderBundleEncoder({ - colorFormats: ['bgra8unorm'], + colorFormats: [], + depthStencilFormat, depthReadOnly, stencilReadOnly }); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_open_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_open_state.spec.js index 663db39fa1..b635fe1594 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_open_state.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_open_state.spec.js @@ -57,6 +57,9 @@ class F extends ValidationTest { export const g = makeTestGroup(F); +// MAINTENANCE_TODO: Remove writeTimestamp from here once it's (hopefully) added back to the spec. + + const kEncoderCommandInfo = @@ -146,6 +149,8 @@ desc( ` Test that functions of GPUCommandEncoder generate a validation error if the encoder is already finished. + + TODO: writeTimestamp is removed from the spec so it's skipped if it TypeErrors. ` ). params((u) => @@ -260,8 +265,11 @@ fn((t) => { } break; case 'writeTimestamp': - { + try { + encoder.writeTimestamp(querySet, 0); + } catch (ex) { + t.skipIf(ex instanceof TypeError, 'writeTimestamp is actually not available'); } break; case 'resolveQuerySet': diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat.spec.js index cb15b694de..825f0f69e0 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat.spec.js @@ -32,13 +32,32 @@ const kComputeCmds = ['dispatch', 'dispatchIndirect']; const kRenderCmds = ['draw', 'drawIndexed', 'drawIndirect', 'drawIndexedIndirect']; +const kPipelineTypes = ['auto0', 'explicit']; + +const kBindingTypes = ['auto0', 'auto1', 'explicit']; + + +const kEmptyBindGroup0Ndx = 0; +const kEmptyBindGroup1Ndx = 1; +const kNonEmptyBindGroup0Ndx = 2; +const kNonEmptyBindGroup1Ndx = 3; + +// Swaps 2 array elements in place. +function swapArrayElements(array, ndx1, ndx2) { + const t = array[ndx1]; + array[ndx1] = array[ndx2]; + array[ndx2] = t; +} + // Test resource type compatibility in pipeline and bind group // [1]: Need to add externalTexture const kResourceTypes = [ 'uniformBuf', 'filtSamp', 'sampledTex', -'storageTex']; +'readonlyStorageTex', +'writeonlyStorageTex', +'readwriteStorageTex']; function getTestCmds( @@ -75,7 +94,17 @@ class F extends ValidationTest { if (entry.buffer !== undefined) return 'uniformBuf'; if (entry.sampler !== undefined) return 'filtSamp'; if (entry.texture !== undefined) return 'sampledTex'; - if (entry.storageTexture !== undefined) return 'storageTex'; + if (entry.storageTexture !== undefined) { + switch (entry.storageTexture.access) { + case undefined: + case 'write-only': + return 'writeonlyStorageTex'; + case 'read-only': + return 'readonlyStorageTex'; + case 'read-write': + return 'readwriteStorageTex'; + } + } unreachable(); } @@ -208,8 +237,14 @@ class F extends ValidationTest { case 'sampledTex': entry.texture = {}; // default sampleType: float break; - case 'storageTex': - entry.storageTexture = { access: 'write-only', format: 'rgba8unorm' }; + case 'readonlyStorageTex': + entry.storageTexture = { access: 'read-only', format: 'r32float' }; + break; + case 'writeonlyStorageTex': + entry.storageTexture = { access: 'write-only', format: 'r32float' }; + break; + case 'readwriteStorageTex': + entry.storageTexture = { access: 'read-write', format: 'r32float' }; break; } @@ -259,6 +294,135 @@ class F extends ValidationTest { validateFinish(success); } + + runDefaultLayoutBindingTest({ + visibility, + empty, + pipelineType, + bindingType, + swap, + success, + makePipelinesFn, + doCommandFn + + + + + + + + + + + + + + + + }) { + const { device } = this; + const explicitEmptyBindGroupLayout = device.createBindGroupLayout({ + entries: [] + }); + const explicitBindGroupLayout = device.createBindGroupLayout({ + entries: [ + { + binding: 0, + visibility, + buffer: {} + }] + + }); + const explicitPipelineLayout = device.createPipelineLayout({ + bindGroupLayouts: [ + explicitEmptyBindGroupLayout, + explicitEmptyBindGroupLayout, + explicitBindGroupLayout, + explicitBindGroupLayout] + + }); + + const [pipelineAuto0, pipelineAuto1, pipelineExplicit] = makePipelinesFn( + this, + explicitPipelineLayout + ); + + const buffer = device.createBuffer({ + size: 16, + usage: GPUBufferUsage.UNIFORM + }); + this.trackForCleanup(buffer); + + let emptyBindGroupLayouts; + let nonEmptyBindGroupLayouts; + const pipeline = pipelineType === 'auto0' ? pipelineAuto0 : pipelineExplicit; + + // Gets a bindGroupLayout either from the explicit layout passed in + // or one of the 2 `layout: 'auto'` pipelines. + const getBindGroupLayout = ( + explicitBindGroupLayout, + bindGroupIndex) => + + bindingType === 'explicit' ? + explicitBindGroupLayout : + bindingType === 'auto0' ? + pipelineAuto0.getBindGroupLayout(bindGroupIndex) : + pipelineAuto1.getBindGroupLayout(bindGroupIndex); + + if (empty) { + // Testing empty: + // - emptyBindGroupLayout comes from a possibly incompatible place. + // - nonEmptyBindGroupLayout comes from the pipeline we'll render/compute with. + emptyBindGroupLayouts = [ + getBindGroupLayout(explicitEmptyBindGroupLayout, kEmptyBindGroup0Ndx), + getBindGroupLayout(explicitEmptyBindGroupLayout, kEmptyBindGroup1Ndx)]; + + if (swap) { + swapArrayElements(emptyBindGroupLayouts, 0, 1); + } + nonEmptyBindGroupLayouts = [ + pipeline.getBindGroupLayout(kNonEmptyBindGroup0Ndx), + pipeline.getBindGroupLayout(kNonEmptyBindGroup1Ndx)]; + + } else { + // Testing non-empty: + // - nonEmptyBindGroupLayout comes from a possibly incompatible place. + // - emptyBindGroupLayout comes from the pipeline we'll render/compute with. + nonEmptyBindGroupLayouts = [ + getBindGroupLayout(explicitBindGroupLayout, kNonEmptyBindGroup0Ndx), + getBindGroupLayout(explicitBindGroupLayout, kNonEmptyBindGroup1Ndx)]; + + if (swap) { + swapArrayElements(nonEmptyBindGroupLayouts, 0, 1); + } + emptyBindGroupLayouts = [ + pipeline.getBindGroupLayout(kEmptyBindGroup0Ndx), + pipeline.getBindGroupLayout(kEmptyBindGroup1Ndx)]; + + } + + const emptyBindGroups = emptyBindGroupLayouts.map((layout) => + device.createBindGroup({ + layout, + entries: [] + }) + ); + + const nonEmptyBindGroups = nonEmptyBindGroupLayouts.map((layout) => + device.createBindGroup({ + layout, + entries: [{ binding: 0, resource: { buffer } }] + }) + ); + + const encoder = device.createCommandEncoder(); + + doCommandFn({ t: this, encoder, pipeline, emptyBindGroups, nonEmptyBindGroups }); + + this.expectValidationError(() => { + encoder.finish(); + }, !success); + } } export const g = makeTestGroup(F); @@ -774,4 +938,175 @@ fn((t) => { t.expectValidationError(() => { encoder.finish(); }, !success); +}); + +// pipelineType specifies which pipeline to try to render/compute with +// auto0 = the first `layout: 'auto'` pipeline +// explicit = a pipeline crated with an explicit pipeline layout using explicit bind group layouts +// +// bindingType specifies where to get bindGroupLayouts to use to create bindGroups +// auto0 = the first `layout: 'auto'` pipeline +// auto1 = the second `layout: 'auto'` pipeline +// explicit = a pipeline crated with an explicit pipeline layout using explicit bind group layouts +// +// swap specifies to swap the bindgroups we're testing. We test 2 of each type, 2 empty bindgroups and +// 2 non-empty bindgroups. The 2 empty bindgroups, when swapped should still be compatible. Similarly +// the 2 non-empty bindgroups, when swapped, should still be compatible. +const kPipelineTypesAndBindingTypeParams = [ +{ pipelineType: 'auto0', bindingType: 'auto0', swap: false, _success: true }, +{ pipelineType: 'explicit', bindingType: 'explicit', swap: false, _success: true }, +{ pipelineType: 'explicit', bindingType: 'auto0', swap: false, _success: false }, +{ pipelineType: 'auto0', bindingType: 'explicit', swap: false, _success: false }, +{ pipelineType: 'auto0', bindingType: 'auto1', swap: false, _success: false }, +{ pipelineType: 'auto0', bindingType: 'auto0', swap: true, _success: true }]; + + +g.test('default_bind_group_layouts_never_match,compute_pass'). +desc( + ` + Test that bind groups created with default bind group layouts never match other layouts, including empty bind groups. + + * Test that a pipeline with an explicit layout can not be used with a bindGroup from an auto layout + * Test that a pipeline with an auto layout can not be used with a bindGroup from an explicit layout + * Test that an auto layout from one pipeline can not be used with an auto layout from a different pipeline. + * Test matching bindgroup layouts on the same default layout pipeline are compatible. In other words if + you only define group(2) then group(0)'s empty layout and group(1)'s empty layout should be compatible. + Similarly if group(2) and group(3) have the same types of resources they should be compatible. + ` +). +params((u) => +u. +combineWithParams(kPipelineTypesAndBindingTypeParams). +combine('empty', [false, true]). +combine('computeCommand', ['dispatchIndirect', 'dispatch']) +). +fn((t) => { + const { pipelineType, bindingType, swap, _success: success, computeCommand, empty } = t.params; + + t.runDefaultLayoutBindingTest({ + visibility: GPUShaderStage.COMPUTE, + empty, + pipelineType, + bindingType, + swap, + success, + makePipelinesFn: (t, explicitPipelineLayout) => { + return ['auto', 'auto', explicitPipelineLayout].map((layout) => + t.device.createComputePipeline({ + layout, + compute: { + module: t.device.createShaderModule({ + code: ` + @group(2) @binding(0) var u1: vec4f; + @group(3) @binding(0) var u2: vec4f; + @compute @workgroup_size(2) fn main() { _ = u1; _ = u2; } + ` + }), + entryPoint: 'main' + } + }) + ); + }, + doCommandFn: ({ t, encoder, pipeline, emptyBindGroups, nonEmptyBindGroups }) => { + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(kEmptyBindGroup0Ndx, emptyBindGroups[0]); + pass.setBindGroup(kEmptyBindGroup1Ndx, emptyBindGroups[1]); + pass.setBindGroup(kNonEmptyBindGroup0Ndx, nonEmptyBindGroups[0]); + pass.setBindGroup(kNonEmptyBindGroup1Ndx, nonEmptyBindGroups[1]); + t.doCompute(pass, computeCommand, true); + pass.end(); + } + }); +}); + +g.test('default_bind_group_layouts_never_match,render_pass'). +desc( + ` + Test that bind groups created with default bind group layouts never match other layouts, including empty bind groups. + + * Test that a pipeline with an explicit layout can not be used with a bindGroup from an auto layout + * Test that a pipeline with an auto layout can not be used with a bindGroup from an explicit layout + * Test that an auto layout from one pipeline can not be used with an auto layout from a different pipeline. + * Test matching bindgroup layouts on the same default layout pipeline are compatible. In other words if + you only define group(2) then group(0)'s empty layout and group(1)'s empty layout should be compatible. + Similarly if group(2) and group(3) have the same types of resources they should be compatible. + ` +). +params((u) => +u. +combineWithParams(kPipelineTypesAndBindingTypeParams). +combine('empty', [false, true]). +combine('renderCommand', [ +'draw', +'drawIndexed', +'drawIndirect', +'drawIndexedIndirect'] +) +). +fn((t) => { + const { pipelineType, bindingType, swap, _success: success, renderCommand, empty } = t.params; + + t.runDefaultLayoutBindingTest({ + visibility: GPUShaderStage.VERTEX, + empty, + pipelineType, + bindingType, + swap, + success, + makePipelinesFn: (t, explicitPipelineLayout) => { + return ['auto', 'auto', explicitPipelineLayout].map( + (layout) => { + const colorFormat = 'rgba8unorm'; + return t.device.createRenderPipeline({ + layout, + vertex: { + module: t.device.createShaderModule({ + code: ` + @group(2) @binding(0) var u1: vec4f; + @group(3) @binding(0) var u2: vec4f; + @vertex fn main() -> @builtin(position) vec4f { return u1 + u2; } + ` + }), + entryPoint: 'main' + }, + fragment: { + module: t.device.createShaderModule({ + code: `@fragment fn main() {}` + }), + entryPoint: 'main', + targets: [{ format: colorFormat, writeMask: 0 }] + } + }); + } + ); + }, + doCommandFn: ({ t, encoder, pipeline, emptyBindGroups, nonEmptyBindGroups }) => { + const attachmentTexture = t.device.createTexture({ + format: 'rgba8unorm', + size: { width: 16, height: 16, depthOrArrayLayers: 1 }, + usage: GPUTextureUsage.RENDER_ATTACHMENT + }); + t.trackForCleanup(attachmentTexture); + + const renderPass = encoder.beginRenderPass({ + colorAttachments: [ + { + view: attachmentTexture.createView(), + clearValue: [0, 0, 0, 0], + loadOp: 'clear', + storeOp: 'store' + }] + + }); + + renderPass.setPipeline(pipeline); + renderPass.setBindGroup(kEmptyBindGroup0Ndx, emptyBindGroups[0]); + renderPass.setBindGroup(kEmptyBindGroup1Ndx, emptyBindGroups[1]); + renderPass.setBindGroup(kNonEmptyBindGroup0Ndx, nonEmptyBindGroups[0]); + renderPass.setBindGroup(kNonEmptyBindGroup1Ndx, nonEmptyBindGroups[1]); + t.doRender(renderPass, renderCommand, true); + renderPass.end(); + } + }); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/general.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/general.spec.js index 4d7342c990..984da88430 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/general.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/general.spec.js @@ -68,14 +68,16 @@ fn((t) => { encoder.validateFinish(t.params.queryIndex < 2); }); -g.test('timestamp_query,query_type_and_index'). +g.test('writeTimestamp,query_type_and_index'). desc( ` Tests that write timestamp to all types of query set on all possible encoders: - type {occlusion, timestamp} - queryIndex {in, out of} range for GPUQuerySet - x= {non-pass} encoder - ` + +TODO: writeTimestamp is removed from the spec so it's skipped if it TypeErrors. +` ). params((u) => u. @@ -101,16 +103,23 @@ fn((t) => { const querySet = createQuerySetWithType(t, type, count); const encoder = t.createEncoder('non-pass'); - encoder.encoder.writeTimestamp(querySet, queryIndex); + try { + + encoder.encoder.writeTimestamp(querySet, queryIndex); + } catch (ex) { + t.skipIf(ex instanceof TypeError, 'writeTimestamp is actually not available'); + } encoder.validateFinish(type === 'timestamp' && queryIndex < count); }); -g.test('timestamp_query,invalid_query_set'). +g.test('writeTimestamp,invalid_query_set'). desc( ` Tests that write timestamp to a invalid query set that failed during creation: - x= {non-pass} encoder - ` + +TODO: writeTimestamp is removed from the spec so it's skipped if it TypeErrors. +` ). paramsSubcasesOnly((u) => u.combine('querySetState', ['valid', 'invalid'])). beforeAllSubcases((t) => { @@ -125,12 +134,22 @@ fn((t) => { }); const encoder = t.createEncoder('non-pass'); - encoder.encoder.writeTimestamp(querySet, 0); + try { + + encoder.encoder.writeTimestamp(querySet, 0); + } catch (ex) { + t.skipIf(ex instanceof TypeError, 'writeTimestamp is actually not available'); + } encoder.validateFinish(querySetState !== 'invalid'); }); -g.test('timestamp_query,device_mismatch'). -desc('Tests writeTimestamp cannot be called with a query set created from another device'). +g.test('writeTimestamp,device_mismatch'). +desc( + `Tests writeTimestamp cannot be called with a query set created from another device + + TODO: writeTimestamp is removed from the spec so it's skipped if it TypeErrors. + ` +). paramsSubcasesOnly((u) => u.combine('mismatched', [true, false])). beforeAllSubcases((t) => { t.selectDeviceForQueryTypeOrSkipTestCase('timestamp'); @@ -147,6 +166,11 @@ fn((t) => { t.trackForCleanup(querySet); const encoder = t.createEncoder('non-pass'); - encoder.encoder.writeTimestamp(querySet, 0); + try { + + encoder.encoder.writeTimestamp(querySet, 0); + } catch (ex) { + t.skipIf(ex instanceof TypeError, 'writeTimestamp is actually not available'); + } encoder.validateFinish(!mismatched); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/render_bundle.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/render_bundle.spec.js index 49e9902f8a..bb752533a9 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/render_bundle.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/render_bundle.spec.js @@ -3,7 +3,7 @@ **/export const description = ` Tests execution of render bundles. `;import { makeTestGroup } from '../../../../common/framework/test_group.js'; -import { kDepthStencilFormats, kTextureFormatInfo } from '../../../format_info.js'; +import { kDepthStencilFormats } from '../../../format_info.js'; import { ValidationTest } from '../validation_test.js'; export const g = makeTestGroup(ValidationTest); @@ -169,19 +169,7 @@ beginSubcases(). combine('bundleDepthReadOnly', [false, true]). combine('bundleStencilReadOnly', [false, true]). combine('passDepthReadOnly', [false, true]). -combine('passStencilReadOnly', [false, true]). -filter((p) => { - // For combined depth/stencil formats the depth and stencil read only state must match - // in order to create a valid render bundle or render pass. - const depthStencilInfo = kTextureFormatInfo[p.depthStencilFormat]; - if (depthStencilInfo.depth && depthStencilInfo.stencil) { - return ( - p.passDepthReadOnly === p.passStencilReadOnly && - p.bundleDepthReadOnly === p.bundleStencilReadOnly); - - } - return true; -}) +combine('passStencilReadOnly', [false, true]) ). beforeAllSubcases((t) => { t.selectDeviceForTextureFormatOrSkipTestCase(t.params.depthStencilFormat); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/error_scope.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/error_scope.spec.js index e5d76f175c..cfca6157fc 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/error_scope.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/error_scope.spec.js @@ -26,7 +26,17 @@ class ErrorScopeTests extends Fixture { const gpu = getGPU(this.rec); const adapter = await gpu.requestAdapter(); assert(adapter !== null); - const device = await adapter.requestDevice(); + + // We need to max out the adapter limits related to texture dimensions to more reliably cause an + // OOM error when asked for it, so set that on the device now. + const device = this.trackForCleanup( + await adapter.requestDevice({ + requiredLimits: { + maxTextureDimension2D: adapter.limits.maxTextureDimension2D, + maxTextureArrayLayers: adapter.limits.maxTextureArrayLayers + } + }) + ); assert(device !== null); this._device = device; } @@ -146,7 +156,7 @@ Tests that popping an empty error scope stack should reject. ). fn((t) => { const promise = t.device.popErrorScope(); - t.shouldReject('OperationError', promise); + t.shouldReject('OperationError', promise, { allowMissingStack: true }); }); g.test('parent_scope'). @@ -250,7 +260,7 @@ fn(async (t) => { { // Trying to pop an additional non-existing scope should reject. const promise = t.device.popErrorScope(); - t.shouldReject('OperationError', promise); + t.shouldReject('OperationError', promise, { allowMissingStack: true }); } const errors = await Promise.all(promises); @@ -286,6 +296,6 @@ fn(async (t) => { { // Trying to pop an additional non-existing scope should reject. const promise = t.device.popErrorScope(); - t.shouldReject('OperationError', promise); + t.shouldReject('OperationError', promise, { allowMissingStack: true }); } }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/gpu_external_texture_expiration.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/gpu_external_texture_expiration.spec.js index 4afd966260..0b271d6afd 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/gpu_external_texture_expiration.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/gpu_external_texture_expiration.spec.js @@ -86,10 +86,7 @@ fn(async (t) => { sourceType === 'VideoFrame' ? await getVideoFrameFromVideoElement(t, videoElement) : videoElement; - externalTexture = t.device.importExternalTexture({ - - source: source - }); + externalTexture = t.device.importExternalTexture({ source }); bindGroup = t.device.createBindGroup({ layout: t.getDefaultBindGroupLayout(), @@ -99,10 +96,7 @@ fn(async (t) => { t.submitCommandBuffer(bindGroup, true); // Import again in the same task scope should return same object. - const mayBeTheSameExternalTexture = t.device.importExternalTexture({ - - source: source - }); + const mayBeTheSameExternalTexture = t.device.importExternalTexture({ source }); if (externalTexture === mayBeTheSameExternalTexture) { t.submitCommandBuffer(bindGroup, true); @@ -142,10 +136,7 @@ fn(async (t) => { // Import GPUExternalTexture queueMicrotask(() => { - externalTexture = t.device.importExternalTexture({ - - source: source - }); + externalTexture = t.device.importExternalTexture({ source }); }); // Submit GPUExternalTexture @@ -182,10 +173,7 @@ fn(async (t) => { sourceType === 'VideoFrame' ? await getVideoFrameFromVideoElement(t, videoElement) : videoElement; - externalTexture = t.device.importExternalTexture({ - - source: source - }); + externalTexture = t.device.importExternalTexture({ source }); bindGroup = t.device.createBindGroup({ layout: t.getDefaultBindGroupLayout(), @@ -218,10 +206,7 @@ fn(async (t) => { let source; await startPlayingAndWaitForVideo(videoElement, () => { source = videoElement; - externalTexture = t.device.importExternalTexture({ - - source: source - }); + externalTexture = t.device.importExternalTexture({ source }); bindGroup = t.device.createBindGroup({ layout: t.getDefaultBindGroupLayout(), @@ -232,10 +217,7 @@ fn(async (t) => { }); await waitForNextTask(() => { - const mayBeTheSameExternalTexture = t.device.importExternalTexture({ - - source: source - }); + const mayBeTheSameExternalTexture = t.device.importExternalTexture({ source }); if (externalTexture === mayBeTheSameExternalTexture) { // ImportExternalTexture should refresh expired GPUExternalTexture. @@ -264,10 +246,7 @@ fn(async (t) => { let externalTexture; await startPlayingAndWaitForVideo(videoElement, async () => { const source = await getVideoFrameFromVideoElement(t, videoElement); - externalTexture = t.device.importExternalTexture({ - - source: source - }); + externalTexture = t.device.importExternalTexture({ source }); bindGroup = t.device.createBindGroup({ layout: t.getDefaultBindGroupLayout(), diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/image_copy.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/image_copy.js index 3cffa6b3ce..96115f0bf2 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/image_copy.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/image_copy.js @@ -255,9 +255,9 @@ export function formatCopyableWithMethod({ format, method }) { return supportedAspects.length > 0; } if (method === 'CopyT2B') { - return info.copySrc; + return info.color.copySrc; } else { - return info.copyDst; + return info.color.copyDst; } } diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/texture_related.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/texture_related.spec.js index 7b535935c3..ec9501e307 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/texture_related.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/texture_related.spec.js @@ -440,7 +440,7 @@ fn((t) => { const texture = t.createAlignedTexture(format, size, origin, dimension); const bytesPerRow = align( - Math.max(1, Math.ceil(size.width / info.blockWidth)) * info.bytesPerBlock, + Math.max(1, Math.ceil(size.width / info.blockWidth)) * info.color.bytes, 256 ); const rowsPerImage = Math.ceil(size.height / info.blockHeight); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/layout_shader_compat.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/layout_shader_compat.spec.js index f579b416d1..9722aec086 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/layout_shader_compat.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/layout_shader_compat.spec.js @@ -3,12 +3,291 @@ **/export const description = ` TODO: - interface matching between pipeline layout and shader - - x= {compute, vertex, fragment, vertex+fragment}, visibilities - x= bind group index values, binding index values, multiple bindings - - x= types of bindings - - x= {equal, superset, subset} + - x= {superset, subset} `;import { makeTestGroup } from '../../../common/framework/test_group.js'; +import { + kShaderStageCombinations, + kShaderStages } from + +'../../capability_info.js'; +import { GPUConst } from '../../constants.js'; import { ValidationTest } from './validation_test.js'; -export const g = makeTestGroup(ValidationTest); \ No newline at end of file + +const kBindableResources = [ +'uniformBuf', +'storageBuf', +'readonlyStorageBuf', +'filtSamp', +'nonFiltSamp', +'compareSamp', +'sampledTex', +'sampledTexMS', +'readonlyStorageTex', +'writeonlyStorageTex', +'readwriteStorageTex']; + + +const bindGroupLayoutEntryContents = { + compareSamp: { + sampler: { + type: 'comparison' + } + }, + filtSamp: { + sampler: { + type: 'filtering' + } + }, + nonFiltSamp: { + sampler: { + type: 'non-filtering' + } + }, + sampledTex: { + texture: { + sampleType: 'unfilterable-float' + } + }, + sampledTexMS: { + texture: { + sampleType: 'unfilterable-float', + multisampled: true + } + }, + storageBuf: { + buffer: { + type: 'storage' + } + }, + readonlyStorageBuf: { + buffer: { + type: 'read-only-storage' + } + }, + uniformBuf: { + buffer: { + type: 'uniform' + } + }, + readonlyStorageTex: { + storageTexture: { + format: 'r32float', + access: 'read-only' + } + }, + writeonlyStorageTex: { + storageTexture: { + format: 'r32float', + access: 'write-only' + } + }, + readwriteStorageTex: { + storageTexture: { + format: 'r32float', + access: 'read-write' + } + } +}; + +class F extends ValidationTest { + createPipelineLayout( + bindingInPipelineLayout, + visibility) + { + return this.device.createPipelineLayout({ + bindGroupLayouts: [ + this.device.createBindGroupLayout({ + entries: [ + { + binding: 0, + visibility, + ...bindGroupLayoutEntryContents[bindingInPipelineLayout] + }] + + })] + + }); + } + + GetBindableResourceShaderDeclaration(bindableResource) { + switch (bindableResource) { + case 'compareSamp': + return 'var tmp : sampler_comparison'; + case 'filtSamp': + case 'nonFiltSamp': + return 'var tmp : sampler'; + case 'sampledTex': + return 'var tmp : texture_2d'; + case 'sampledTexMS': + return 'var tmp : texture_multisampled_2d'; + case 'storageBuf': + return 'var tmp : vec4u'; + case 'readonlyStorageBuf': + return 'var tmp : vec4u'; + case 'uniformBuf': + return 'var tmp : vec4u;'; + case 'readonlyStorageTex': + return 'var tmp : texture_storage_2d'; + case 'writeonlyStorageTex': + return 'var tmp : texture_storage_2d'; + case 'readwriteStorageTex': + return 'var tmp : texture_storage_2d'; + } + } +} + +const BindingResourceCompatibleWithShaderStages = function ( +bindingResource, +shaderStages) +{ + if ((shaderStages & GPUConst.ShaderStage.VERTEX) > 0) { + switch (bindingResource) { + case 'writeonlyStorageTex': + case 'readwriteStorageTex': + case 'storageBuf': + return false; + default: + break; + } + } + return true; +}; + +export const g = makeTestGroup(F); + +g.test('pipeline_layout_shader_exact_match'). +desc( + ` + Test that the binding type in the pipeline layout must match the related declaration in shader. + Note that read-write storage textures in the pipeline layout can match write-only storage textures + in the shader. + ` +). +params((u) => +u. +combine('bindingInPipelineLayout', kBindableResources). +combine('bindingInShader', kBindableResources). +beginSubcases(). +combine('pipelineLayoutVisibility', kShaderStageCombinations). +combine('shaderStageWithBinding', kShaderStages). +combine('isBindingStaticallyUsed', [true, false]). +unless( + (p) => + // We don't test using non-filtering sampler in shader because it has the same declaration + // as filtering sampler. + p.bindingInShader === 'nonFiltSamp' || + !BindingResourceCompatibleWithShaderStages( + p.bindingInPipelineLayout, + p.pipelineLayoutVisibility + ) || + !BindingResourceCompatibleWithShaderStages(p.bindingInShader, p.shaderStageWithBinding) +) +). +fn((t) => { + const { + bindingInPipelineLayout, + bindingInShader, + pipelineLayoutVisibility, + shaderStageWithBinding, + isBindingStaticallyUsed + } = t.params; + + const layout = t.createPipelineLayout(bindingInPipelineLayout, pipelineLayoutVisibility); + const bindResourceDeclaration = `@group(0) @binding(0) ${t.GetBindableResourceShaderDeclaration( + bindingInShader + )}`; + const staticallyUseBinding = isBindingStaticallyUsed ? '_ = tmp; ' : ''; + const isAsync = false; + + let success = true; + if (isBindingStaticallyUsed) { + success = bindingInPipelineLayout === bindingInShader; + + // Filtering and non-filtering both have the same shader declaration. + success ||= bindingInPipelineLayout === 'nonFiltSamp' && bindingInShader === 'filtSamp'; + + // Promoting storage textures that are read-write in the layout can be readonly in the shader. + success ||= + bindingInPipelineLayout === 'readwriteStorageTex' && + bindingInShader === 'writeonlyStorageTex'; + + // The shader using the resource must be included in the visibility in the layout. + success &&= (pipelineLayoutVisibility & shaderStageWithBinding) > 0; + } + + switch (shaderStageWithBinding) { + case GPUConst.ShaderStage.COMPUTE:{ + const computeShader = ` + ${bindResourceDeclaration}; + @compute @workgroup_size(1) + fn main() { + ${staticallyUseBinding} + } + `; + t.doCreateComputePipelineTest(isAsync, success, { + layout, + compute: { + module: t.device.createShaderModule({ + code: computeShader + }) + } + }); + break; + } + case GPUConst.ShaderStage.VERTEX:{ + const vertexShader = ` + ${bindResourceDeclaration}; + @vertex + fn main() -> @builtin(position) vec4f { + ${staticallyUseBinding} + return vec4f(); + } + `; + t.doCreateRenderPipelineTest(isAsync, success, { + layout, + vertex: { + module: t.device.createShaderModule({ + code: vertexShader + }) + } + }); + break; + } + case GPUConst.ShaderStage.FRAGMENT:{ + const fragmentShader = ` + ${bindResourceDeclaration}; + @fragment + fn main() -> @location(0) vec4f { + ${staticallyUseBinding} + return vec4f(); + } + `; + t.doCreateRenderPipelineTest(isAsync, success, { + layout, + vertex: { + module: t.device.createShaderModule({ + code: ` + @vertex + fn main() -> @builtin(position) vec4f { + return vec4f(); + }` + }) + }, + fragment: { + module: t.device.createShaderModule({ + code: fragmentShader + }), + targets: [ + { + format: 'rgba8unorm' + }] + + } + }); + break; + } + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.js index a66b9a7747..f7248cf964 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.js @@ -14,7 +14,7 @@ import { raceWithRejectOnTimeout, unreachable, assert } from '../../../../../com import { kTextureUsages } from '../../../../capability_info.js'; import { kTextureFormatInfo, - kTextureFormats, + kAllTextureFormats, kValidTextureFormatsForCopyE2T } from '../../../../format_info.js'; import { kResourceStates } from '../../../../gpu_test.js'; @@ -669,7 +669,7 @@ desc( ). params((u) => u. -combine('format', kTextureFormats). +combine('format', kAllTextureFormats). beginSubcases(). combine('copySize', [ { width: 0, height: 0, depthOrArrayLayers: 0 }, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/query_set.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/query_set.spec.js index 606a0a7a03..ac8f810f16 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/query_set.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/query_set.spec.js @@ -24,11 +24,13 @@ fn((t) => { encoder.validateFinishAndSubmitGivenState(t.params.querySetState); }); -g.test('writeTimestamp'). +g.test('timestamps'). desc( ` -Tests that use a destroyed query set in writeTimestamp on {non-pass, compute, render} encoder. +Tests that use a destroyed query set in timestamp query on {non-pass, compute, render} encoder. - x= {destroyed, not destroyed (control case)} + + TODO: writeTimestamp is removed from the spec so it's skipped if it TypeErrors. ` ). params((u) => u.beginSubcases().combine('querySetState', ['valid', 'destroyed'])). @@ -39,9 +41,50 @@ fn((t) => { count: 2 }); - const encoder = t.createEncoder('non-pass'); - encoder.encoder.writeTimestamp(querySet, 0); - encoder.validateFinishAndSubmitGivenState(t.params.querySetState); + { + const encoder = t.createEncoder('non-pass'); + try { + + encoder.encoder.writeTimestamp(querySet, 0); + } catch (ex) { + t.skipIf(ex instanceof TypeError, 'writeTimestamp is actually not available'); + } + encoder.validateFinishAndSubmitGivenState(t.params.querySetState); + } + + { + const encoder = t.createEncoder('non-pass'); + encoder.encoder. + beginComputePass({ + timestampWrites: { querySet, beginningOfPassWriteIndex: 0 } + }). + end(); + encoder.validateFinishAndSubmitGivenState(t.params.querySetState); + } + + { + const texture = t.trackForCleanup( + t.device.createTexture({ + size: [1, 1, 1], + format: 'rgba8unorm', + usage: GPUTextureUsage.RENDER_ATTACHMENT + }) + ); + const encoder = t.createEncoder('non-pass'); + encoder.encoder. + beginRenderPass({ + colorAttachments: [ + { + view: texture.createView(), + loadOp: 'load', + storeOp: 'store' + }], + + timestampWrites: { querySet, beginningOfPassWriteIndex: 0 } + }). + end(); + encoder.validateFinishAndSubmitGivenState(t.params.querySetState); + } }); g.test('resolveQuerySet'). diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/texture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/texture.spec.js index eb32232b51..2f64023806 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/texture.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/texture.spec.js @@ -164,16 +164,17 @@ Tests that using a destroyed texture referenced by a bindGroup set with setBindG paramsSubcasesOnly((u) => u. combine('destroyed', [false, true]). -combine('encoderType', ['compute pass', 'render pass', 'render bundle']) +combine('encoderType', ['compute pass', 'render pass', 'render bundle']). +combine('bindingType', ['texture', 'storageTexture']) ). fn((t) => { - const { destroyed, encoderType } = t.params; + const { destroyed, encoderType, bindingType } = t.params; const { device } = t; const texture = t.trackForCleanup( t.device.createTexture({ size: [1, 1, 1], format: 'rgba8unorm', - usage: GPUTextureUsage.TEXTURE_BINDING + usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING }) ); @@ -182,7 +183,9 @@ fn((t) => { { binding: 0, visibility: GPUShaderStage.COMPUTE, - texture: {} + [bindingType]: { + format: texture.format + } }] }); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/attachment_compatibility.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/attachment_compatibility.spec.js index 7712bf64c4..6579343b49 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/attachment_compatibility.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/attachment_compatibility.spec.js @@ -551,13 +551,6 @@ combine('cullMode', ['none', 'front', 'back']). filter((p) => { if (p.format) { const depthStencilInfo = kTextureFormatInfo[p.format]; - // For combined depth/stencil formats the depth and stencil read only state must match - // in order to create a valid render bundle or render pass. - if (depthStencilInfo.depth && depthStencilInfo.stencil) { - if (p.depthReadOnly !== p.stencilReadOnly) { - return false; - } - } // If the format has no depth aspect, the depthReadOnly, depthWriteEnabled of the pipeline must not be true // in order to create a valid render pipeline. if (!depthStencilInfo.depth && p.depthWriteEnabled) { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/render_pass_descriptor.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/render_pass_descriptor.spec.js index 5108b21fc7..94633c2f70 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/render_pass_descriptor.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/render_pass_descriptor.spec.js @@ -26,10 +26,12 @@ class F extends ValidationTest { + {}) { const { format = 'rgba8unorm', + dimension = '2d', width = 16, height = 16, arrayLayerCount = 1, @@ -41,6 +43,7 @@ class F extends ValidationTest { return this.device.createTexture({ size: { width, height, depthOrArrayLayers: arrayLayerCount }, format, + dimension, mipLevelCount, sampleCount, usage @@ -90,6 +93,7 @@ class F extends ValidationTest { } export const g = makeTestGroup(F); +const kArrayLayerCount = 10; g.test('attachments,one_color_attachment'). desc(`Test that a render pass works with only one color attachment.`). @@ -278,6 +282,184 @@ fn((t) => { t.tryRenderPass(success, { colorAttachments }); }); +g.test('color_attachments,depthSlice,definedness'). +desc( + ` + Test that depthSlice must be undefined for 2d color attachments and defined for 3d color attachments." + - The special value '0xFFFFFFFF' is not treated as 'undefined'. + ` +). +params((u) => +u. +combine('dimension', ['2d', '3d']). +beginSubcases(). +combine('depthSlice', [undefined, 0, 0xffffffff]) +). +fn((t) => { + const { dimension, depthSlice } = t.params; + const texture = t.createTexture({ dimension }); + + const colorAttachment = t.getColorAttachment(texture); + if (depthSlice !== undefined) { + colorAttachment.depthSlice = depthSlice; + } + + const descriptor = { + colorAttachments: [colorAttachment] + }; + + const success = + dimension === '2d' && depthSlice === undefined || dimension === '3d' && depthSlice === 0; + + t.tryRenderPass(success, descriptor); +}); + +g.test('color_attachments,depthSlice,bound_check'). +desc( + ` + Test that depthSlice must be less than the depthOrArrayLayers of 3d texture's subresource at mip levels. + - Check depth bounds with 3d texture size [16, 1, 10], which has 5 mip levels with depth [10, 5, 2, 1, 1] + for testing more mip level size computation. + - Failed if depthSlice >= the depth of each mip level. + ` +). +params((u) => +u. +combine('mipLevel', [0, 1, 2, 3, 4]). +beginSubcases(). +expand('depthSlice', ({ mipLevel }) => { + const depthAtMipLevel = Math.max(kArrayLayerCount >> mipLevel, 1); + // Use Set() to exclude duplicates when the depthAtMipLevel is 1 and 2 + return [...new Set([0, 1, depthAtMipLevel - 1, depthAtMipLevel])]; +}) +). +fn((t) => { + const { mipLevel, depthSlice } = t.params; + + const texture = t.createTexture({ + dimension: '3d', + width: 16, + height: 1, + arrayLayerCount: kArrayLayerCount, + mipLevelCount: mipLevel + 1 + }); + + const viewDescriptor = { + baseMipLevel: mipLevel, + mipLevelCount: 1, + baseArrayLayer: 0, + arrayLayerCount: 1 + }; + + const colorAttachment = t.getColorAttachment(texture, viewDescriptor); + colorAttachment.depthSlice = depthSlice; + + const passDescriptor = { + colorAttachments: [colorAttachment] + }; + + const success = depthSlice < Math.max(kArrayLayerCount >> mipLevel, 1); + + t.tryRenderPass(success, passDescriptor); +}); + +g.test('color_attachments,depthSlice,overlaps,same_miplevel'). +desc( + ` + Test that the depth slices of 3d color attachments have no overlaps for same texture in a render + pass. + - Succeed if the depth slices are different, or from different textures, or on different render + passes. + - Fail if same depth slice from same texture's same mip level is overwritten in a render pass. + ` +). +params((u) => +u. +combine('sameDepthSlice', [true, false]). +beginSubcases(). +combine('sameTexture', [true, false]). +combine('samePass', [true, false]) +). +fn((t) => { + const { sameDepthSlice, sameTexture, samePass } = t.params; + const arrayLayerCount = 4; + + const texDescriptor = { + dimension: '3d', + arrayLayerCount + }; + const texture = t.createTexture(texDescriptor); + + const colorAttachments = []; + for (let i = 0; i < arrayLayerCount; i++) { + const colorAttachment = t.getColorAttachment( + sameTexture ? texture : t.createTexture(texDescriptor) + ); + colorAttachment.depthSlice = sameDepthSlice ? 0 : i; + colorAttachments.push(colorAttachment); + } + + const encoder = t.createEncoder('non-pass'); + if (samePass) { + const pass = encoder.encoder.beginRenderPass({ colorAttachments }); + pass.end(); + } else { + for (let i = 0; i < arrayLayerCount; i++) { + const pass = encoder.encoder.beginRenderPass({ colorAttachments: [colorAttachments[i]] }); + pass.end(); + } + } + + const success = !sameDepthSlice || !sameTexture || !samePass; + + encoder.validateFinish(success); +}); + +g.test('color_attachments,depthSlice,overlaps,diff_miplevel'). +desc( + ` + Test that the same depth slice from different mip levels of a 3d texture with size [1, 1, N] can + be set in a render pass's color attachments. + ` +). +params((u) => u.combine('sameMipLevel', [true, false])). +fn((t) => { + const { sameMipLevel } = t.params; + const mipLevelCount = 4; + + const texDescriptor = { + dimension: '3d', + width: 1, + height: 1, + arrayLayerCount: 1 << mipLevelCount, + mipLevelCount + }; + const texture = t.createTexture(texDescriptor); + + const viewDescriptor = { + baseMipLevel: 0, + mipLevelCount: 1, + baseArrayLayer: 0, + arrayLayerCount: 1 + }; + + const colorAttachments = []; + for (let i = 0; i < mipLevelCount; i++) { + if (!sameMipLevel) { + viewDescriptor.baseMipLevel = i; + } + const colorAttachment = t.getColorAttachment(texture, viewDescriptor); + colorAttachment.depthSlice = 0; + colorAttachments.push(colorAttachment); + } + + const encoder = t.createEncoder('non-pass'); + const pass = encoder.encoder.beginRenderPass({ colorAttachments }); + pass.end(); + + encoder.validateFinish(!sameMipLevel); +}); + g.test('attachments,same_size'). desc( ` @@ -909,10 +1091,8 @@ fn((t) => { const hasDepth = info.depth; const hasStencil = info.stencil; - const goodAspectCombo = - (hasDepth && hasStencil ? !depthReadOnly === !stencilReadOnly : true) && ( - hasDepthSettings ? hasDepth : true) && ( - hasStencilSettings ? hasStencil : true); + const goodAspectSettingsPresent = + (hasDepthSettings ? hasDepth : true) && (hasStencilSettings ? hasStencil : true); const hasBothDepthOps = !!depthLoadOp && !!depthStoreOp; const hasBothStencilOps = !!stencilLoadOp && !!stencilStoreOp; @@ -923,7 +1103,7 @@ fn((t) => { const goodStencilCombo = hasStencil && !stencilReadOnly ? hasBothStencilOps : hasNeitherStencilOps; - const shouldError = !goodAspectCombo || !goodDepthCombo || !goodStencilCombo; + const shouldError = !goodAspectSettingsPresent || !goodDepthCombo || !goodStencilCombo; t.expectValidationError(() => { encoder.finish(); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/common.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/common.js index 2b4283b32c..6785346a2f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/common.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/common.js @@ -6,6 +6,8 @@ kDefaultVertexShaderCode } from '../../../util/shader.js'; import { ValidationTest } from '../validation_test.js'; + + const values = [0, 1, 0, 1]; export class CreateRenderPipelineValidationTest extends ValidationTest { getDescriptor( @@ -19,17 +21,16 @@ export class CreateRenderPipelineValidationTest extends ValidationTest { {}) { - const defaultTargets = [{ format: 'rgba8unorm' }]; const { primitive = {}, - targets = defaultTargets, + targets = [{ format: 'rgba8unorm' }], multisample = {}, depthStencil, fragmentShaderCode = getFragmentShaderCodeWithOutput([ { values, plainType: getPlainTypeInfo( - kTextureFormatInfo[targets[0] ? targets[0].format : 'rgba8unorm'].sampleType + kTextureFormatInfo[targets[0] ? targets[0].format : 'rgba8unorm'].color.type ), componentCount: 4 }] diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.js index d47041b4fc..8be7ee6e88 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.js @@ -5,7 +5,11 @@ This test dedicatedly tests validation of GPUDepthStencilState of createRenderPi `;import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { unreachable } from '../../../../common/util/util.js'; import { kCompareFunctions, kStencilOperations } from '../../../capability_info.js'; -import { kTextureFormats, kTextureFormatInfo, kDepthStencilFormats } from '../../../format_info.js'; +import { + kAllTextureFormats, + kTextureFormatInfo, + kDepthStencilFormats } from +'../../../format_info.js'; import { getFragmentShaderCodeWithOutput } from '../../../util/shader.js'; import { CreateRenderPipelineValidationTest } from './common.js'; @@ -14,7 +18,11 @@ export const g = makeTestGroup(CreateRenderPipelineValidationTest); g.test('format'). desc(`The texture format in depthStencilState must be a depth/stencil format.`). -params((u) => u.combine('isAsync', [false, true]).combine('format', kTextureFormats)). +params((u) => +u // +.combine('isAsync', [false, true]). +combine('format', kAllTextureFormats) +). beforeAllSubcases((t) => { const { format } = t.params; const info = kTextureFormatInfo[format]; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/fragment_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/fragment_state.spec.js index 6e7a46e943..efaca1883f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/fragment_state.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/fragment_state.spec.js @@ -10,15 +10,17 @@ import { kMaxColorAttachmentsToTest } from '../../../capability_info.js'; import { - kTextureFormats, + kAllTextureFormats, kRenderableColorTextureFormats, kTextureFormatInfo, - computeBytesPerSampleFromFormats } from + computeBytesPerSampleFromFormats, + kColorTextureFormats } from '../../../format_info.js'; import { getFragmentShaderCodeWithOutput, getPlainTypeInfo, - kDefaultFragmentShaderCode } from + kDefaultFragmentShaderCode, + kDefaultVertexShaderCode } from '../../../util/shader.js'; import { kTexelRepresentationInfo } from '../../../util/texture/texel_data.js'; @@ -49,9 +51,60 @@ fn((t) => { t.doCreateRenderPipelineTest(isAsync, false, badDescriptor); }); +g.test('targets_format_is_color_format'). +desc( + `Tests that color target state format must be a color format, regardless of how the + fragment shader writes to it.` +). +params((u) => +u +// Test all non-color texture formats, plus 'rgba8unorm' as a control case. +.combine('format', kAllTextureFormats). +filter(({ format }) => { + return format === 'rgba8unorm' || !kTextureFormatInfo[format].color; +}). +combine('isAsync', [false, true]). +beginSubcases(). +combine('fragOutType', ['f32', 'u32', 'i32']) +). +beforeAllSubcases((t) => { + const { format } = t.params; + const info = kTextureFormatInfo[format]; + t.skipIfTextureFormatNotSupported(t.params.format); + t.selectDeviceOrSkipTestCase(info.feature); +}). +fn((t) => { + const { isAsync, format, fragOutType } = t.params; + + const fragmentShaderCode = getFragmentShaderCodeWithOutput([ + { values, plainType: fragOutType, componentCount: 4 }] + ); + + const success = format === 'rgba8unorm' && fragOutType === 'f32'; + t.doCreateRenderPipelineTest(isAsync, success, { + vertex: { + module: t.device.createShaderModule({ code: kDefaultVertexShaderCode }), + entryPoint: 'main' + }, + fragment: { + module: t.device.createShaderModule({ code: fragmentShaderCode }), + entryPoint: 'main', + targets: [{ format }] + }, + layout: 'auto' + }); +}); + g.test('targets_format_renderable'). -desc(`Tests that color target state format must have RENDER_ATTACHMENT capability.`). -params((u) => u.combine('isAsync', [false, true]).combine('format', kTextureFormats)). +desc( + `Tests that color target state format must have RENDER_ATTACHMENT capability + (tests only color formats).` +). +params((u) => +u // +.combine('isAsync', [false, true]). +combine('format', kColorTextureFormats) +). beforeAllSubcases((t) => { const { format } = t.params; const info = kTextureFormatInfo[format]; @@ -158,22 +211,10 @@ combineWithParams([ // become 4 and 4+4+8+16+1 > 32. Re-ordering this so the R8Unorm's are at the end, however // is allowed: 4+8+16+1+1 < 32. { - formats: [ - 'r8unorm', - 'r32float', - 'rgba8unorm', - 'rgba32float', - 'r8unorm'] - + formats: ['r8unorm', 'r32float', 'rgba8unorm', 'rgba32float', 'r8unorm'] }, { - formats: [ - 'r32float', - 'rgba8unorm', - 'rgba32float', - 'r8unorm', - 'r8unorm'] - + formats: ['r32float', 'rgba8unorm', 'rgba32float', 'r8unorm', 'r8unorm'] }] ). beginSubcases(). diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/inter_stage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/inter_stage.spec.js index 019d725d3c..f6280ccf76 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/inter_stage.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/inter_stage.spec.js @@ -3,7 +3,7 @@ **/export const description = ` Interface matching between vertex and fragment shader validation for createRenderPipeline. `;import { makeTestGroup } from '../../../../common/framework/test_group.js'; -import { assert, range } from '../../../../common/util/util.js'; +import { range } from '../../../../common/util/util.js'; import { CreateRenderPipelineValidationTest } from './common.js'; @@ -97,8 +97,18 @@ fn((t) => { }); g.test('location,superset'). -desc(`TODO: implement after spec is settled: https://github.com/gpuweb/gpuweb/issues/2038`). -unimplemented(); +desc(`Tests that validation should succeed when vertex output is superset of fragment input`). +params((u) => u.combine('isAsync', [false, true])). +fn((t) => { + const { isAsync } = t.params; + + const descriptor = t.getDescriptorWithStates( + t.getVertexStateWithOutputs(['@location(0) vout0: f32', '@location(1) vout1: f32']), + t.getFragmentStateWithInputs(['@location(1) fin1: f32']) + ); + + t.doCreateRenderPipelineTest(isAsync, true, descriptor); +}); g.test('location,subset'). desc(`Tests that validation should fail when vertex output is a subset of fragment input.`). @@ -159,20 +169,27 @@ u.combine('isAsync', [false, true]).combineWithParams([ { output: '@interpolate(linear)', input: '@interpolate(perspective)' }, { output: '@interpolate(flat)', input: '@interpolate(perspective)' }, { output: '@interpolate(linear)', input: '@interpolate(flat)' }, -{ output: '@interpolate(linear, center)', input: '@interpolate(linear, center)' }] +{ + output: '@interpolate(linear, center)', + input: '@interpolate(linear, center)', + _compat_success: false +}] ) ). fn((t) => { - const { isAsync, output, input, _success } = t.params; + const { isAsync, output, input, _success, _compat_success } = t.params; const descriptor = t.getDescriptorWithStates( t.getVertexStateWithOutputs([`@location(0) ${output} vout0: f32`]), t.getFragmentStateWithInputs([`@location(0) ${input} fin0: f32`]) ); - t.doCreateRenderPipelineTest(isAsync, _success ?? output === input, descriptor); -}); + const shouldSucceed = + (_success ?? output === input) && (!t.isCompatibility || _compat_success !== false); + t.doCreateRenderPipelineTest(isAsync, shouldSucceed, descriptor); +}); +1; g.test('interpolation_sampling'). desc( `Tests that validation should fail when interpolation sampling of vertex output and fragment input at the same location doesn't match.` @@ -186,7 +203,12 @@ u.combine('isAsync', [false, true]).combineWithParams([ input: '@interpolate(perspective, center)', _success: true }, -{ output: '@interpolate(linear, center)', input: '@interpolate(linear)', _success: true }, +{ + output: '@interpolate(linear, center)', + input: '@interpolate(linear)', + _success: true, + _compat_success: false +}, { output: '@interpolate(flat)', input: '@interpolate(flat)' }, { output: '@interpolate(perspective)', input: '@interpolate(perspective, sample)' }, { output: '@interpolate(perspective, center)', input: '@interpolate(perspective, sample)' }, @@ -198,14 +220,17 @@ u.combine('isAsync', [false, true]).combineWithParams([ ) ). fn((t) => { - const { isAsync, output, input, _success } = t.params; + const { isAsync, output, input, _success, _compat_success } = t.params; const descriptor = t.getDescriptorWithStates( t.getVertexStateWithOutputs([`@location(0) ${output} vout0: f32`]), t.getFragmentStateWithInputs([`@location(0) ${input} fin0: f32`]) ); - t.doCreateRenderPipelineTest(isAsync, _success ?? output === input, descriptor); + const shouldSucceed = + (_success ?? output === input) && (!t.isCompatibility || _compat_success !== false); + + t.doCreateRenderPipelineTest(isAsync, shouldSucceed, descriptor); }); g.test('max_shader_variable_location'). @@ -251,9 +276,6 @@ fn((t) => { const numVec4 = Math.floor(numScalarComponents / 4); const numTrailingScalars = numScalarComponents % 4; - const numUserDefinedInterStageVariables = numTrailingScalars > 0 ? numVec4 + 1 : numVec4; - - assert(numUserDefinedInterStageVariables <= t.device.limits.maxInterStageShaderVariables); const outputs = range(numVec4, (i) => `@location(${i}) vout${i}: vec4`); const inputs = range(numVec4, (i) => `@location(${i}) fin${i}: vec4`); @@ -280,23 +302,23 @@ desc( params((u) => u.combine('isAsync', [false, true]).combineWithParams([ // Number of user-defined input scalar components in test shader = device.limits.maxInterStageShaderComponents + numScalarDelta. -{ numScalarDelta: 0, useExtraBuiltinInputs: false, _success: true }, -{ numScalarDelta: 1, useExtraBuiltinInputs: false, _success: false }, -{ numScalarDelta: 0, useExtraBuiltinInputs: true, _success: false }, -{ numScalarDelta: -3, useExtraBuiltinInputs: true, _success: true }, -{ numScalarDelta: -2, useExtraBuiltinInputs: true, _success: false }] +{ numScalarDelta: 0, useExtraBuiltinInputs: false }, +{ numScalarDelta: 1, useExtraBuiltinInputs: false }, +{ numScalarDelta: 0, useExtraBuiltinInputs: true }, +{ numScalarDelta: -3, useExtraBuiltinInputs: true }, +{ numScalarDelta: -2, useExtraBuiltinInputs: true }] ) ). fn((t) => { - const { isAsync, numScalarDelta, useExtraBuiltinInputs, _success } = t.params; + const { isAsync, numScalarDelta, useExtraBuiltinInputs } = t.params; const numScalarComponents = t.device.limits.maxInterStageShaderComponents + numScalarDelta; + const numExtraComponents = useExtraBuiltinInputs ? t.isCompatibility ? 2 : 3 : 0; + const numUsedComponents = numScalarComponents + numExtraComponents; + const success = numUsedComponents <= t.device.limits.maxInterStageShaderComponents; const numVec4 = Math.floor(numScalarComponents / 4); const numTrailingScalars = numScalarComponents % 4; - const numUserDefinedInterStageVariables = numTrailingScalars > 0 ? numVec4 + 1 : numVec4; - - assert(numUserDefinedInterStageVariables <= t.device.limits.maxInterStageShaderVariables); const outputs = range(numVec4, (i) => `@location(${i}) vout${i}: vec4`); const inputs = range(numVec4, (i) => `@location(${i}) fin${i}: vec4`); @@ -310,9 +332,11 @@ fn((t) => { if (useExtraBuiltinInputs) { inputs.push( '@builtin(front_facing) front_facing_in: bool', - '@builtin(sample_index) sample_index_in: u32', '@builtin(sample_mask) sample_mask_in: u32' ); + if (!t.isCompatibility) { + inputs.push('@builtin(sample_index) sample_index_in: u32'); + } } const descriptor = t.getDescriptorWithStates( @@ -320,5 +344,5 @@ fn((t) => { t.getFragmentStateWithInputs(inputs, true) ); - t.doCreateRenderPipelineTest(isAsync, _success, descriptor); + t.doCreateRenderPipelineTest(isAsync, success, descriptor); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/misc.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/misc.spec.js index 79dddb51e0..d4489a549f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/misc.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/misc.spec.js @@ -95,4 +95,38 @@ fn((t) => { }; t.doCreateRenderPipelineTest(isAsync, !mismatched, descriptor); +}); + +g.test('external_texture'). +desc('Tests createRenderPipeline() with an external_texture'). +fn((t) => { + const shader = t.device.createShaderModule({ + code: ` + @vertex + fn vertexMain() -> @builtin(position) vec4f { + return vec4f(1); + } + + @group(0) @binding(0) var myTexture: texture_external; + + @fragment + fn fragmentMain() -> @location(0) vec4f { + let result = textureLoad(myTexture, vec2u(1, 1)); + return vec4f(1); + } + ` + }); + + const descriptor = { + layout: 'auto', + vertex: { + module: shader + }, + fragment: { + module: shader, + targets: [{ format: 'rgba8unorm' }] + } + }; + + t.doCreateRenderPipelineTest(false, true, descriptor); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/resource_compatibility.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/resource_compatibility.spec.js new file mode 100644 index 0000000000..6b1d18290f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/resource_compatibility.spec.js @@ -0,0 +1,95 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Tests for resource compatibilty between pipeline layout and shader modules + `;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { + kAPIResources, + getWGSLShaderForResource, + getAPIBindGroupLayoutForResource, + doResourcesMatch } from +'../utils.js'; + +import { CreateRenderPipelineValidationTest } from './common.js'; + +export const g = makeTestGroup(CreateRenderPipelineValidationTest); + +g.test('resource_compatibility'). +desc( + 'Tests validation of resource (bind group) compatibility between pipeline layout and WGSL shader' +). +params((u) => +u // +.combine('stage', ['vertex', 'fragment']). +combine('apiResource', keysOf(kAPIResources)). +filter((t) => { + const res = kAPIResources[t.apiResource]; + if (t.stage === 'vertex') { + if (res.buffer && res.buffer.type === 'storage') { + return false; + } + if (res.storageTexture && res.storageTexture.access !== 'read-only') { + return false; + } + } + return true; +}). +beginSubcases(). +combine('isAsync', [true, false]). +combine('wgslResource', keysOf(kAPIResources)) +). +fn((t) => { + const apiResource = kAPIResources[t.params.apiResource]; + const wgslResource = kAPIResources[t.params.wgslResource]; + t.skipIf( + wgslResource.storageTexture !== undefined && + wgslResource.storageTexture.access !== 'write-only' && + !t.hasLanguageFeature('readonly_and_readwrite_storage_textures'), + 'Storage textures require language feature' + ); + const emptyVS = ` +@vertex +fn main() -> @builtin(position) vec4f { + return vec4f(); +} +`; + const emptyFS = ` +@fragment +fn main() -> @location(0) vec4f { + return vec4f(); +} +`; + + const code = getWGSLShaderForResource(t.params.stage, wgslResource); + const vsCode = t.params.stage === 'vertex' ? code : emptyVS; + const fsCode = t.params.stage === 'fragment' ? code : emptyFS; + const gpuStage = + t.params.stage === 'vertex' ? GPUShaderStage.VERTEX : GPUShaderStage.FRAGMENT; + const layout = t.device.createPipelineLayout({ + bindGroupLayouts: [getAPIBindGroupLayoutForResource(t.device, gpuStage, apiResource)] + }); + + const descriptor = { + layout, + vertex: { + module: t.device.createShaderModule({ + code: vsCode + }), + entryPoint: 'main' + }, + fragment: { + module: t.device.createShaderModule({ + code: fsCode + }), + entryPoint: 'main', + targets: [{ format: 'rgba8unorm' }] + } + }; + + t.doCreateRenderPipelineTest( + t.params.isAsync, + doResourcesMatch(apiResource, wgslResource), + descriptor + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.js index f354053e4f..7977c3fb9d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.js @@ -14,10 +14,17 @@ import { import { ValidationTest } from '../../validation_test.js'; + + + + + const kTextureBindingTypes = [ 'sampled-texture', 'multisampled-texture', -'writeonly-storage-texture']; +'writeonly-storage-texture', +'readonly-storage-texture', +'readwrite-storage-texture']; const SIZE = 32; @@ -39,7 +46,7 @@ class TextureUsageTracking extends ValidationTest { arrayLayerCount = 1, mipLevelCount = 1, sampleCount = 1, - format = 'rgba8unorm', + format = 'r32float', usage = GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING } = options; @@ -75,6 +82,14 @@ class TextureUsageTracking extends ValidationTest { assert(format !== undefined); entry = { storageTexture: { access: 'write-only', format, viewDimension } }; break; + case 'readonly-storage-texture': + assert(format !== undefined); + entry = { storageTexture: { access: 'read-only', format, viewDimension } }; + break; + case 'readwrite-storage-texture': + assert(format !== undefined); + entry = { storageTexture: { access: 'read-write', format, viewDimension } }; + break; } return this.device.createBindGroupLayout({ @@ -107,7 +122,7 @@ class TextureUsageTracking extends ValidationTest { depthStencilFormat) { const bundleEncoder = this.device.createRenderBundleEncoder({ - colorFormats: ['rgba8unorm'], + colorFormats: ['r32float'], depthStencilFormat }); bundleEncoder.setBindGroup(binding, bindGroup); @@ -129,16 +144,21 @@ class TextureUsageTracking extends ValidationTest { } /** - * Create two bind groups. Resource usages conflict between these two bind groups. But resource - * usage inside each bind group doesn't conflict. + * Create two bind groups with one texture view. */ - makeConflictingBindGroups() { + makeTwoBindGroupsWithOneTextureView(usage1, usage2) { const view = this.createTexture({ usage: GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING }).createView(); const bindGroupLayouts = [ - this.createBindGroupLayout(0, 'sampled-texture', '2d'), - this.createBindGroupLayout(0, 'writeonly-storage-texture', '2d', { format: 'rgba8unorm' })]; + this.createBindGroupLayout(0, usage1, '2d', { + sampleType: 'unfilterable-float', + format: 'r32float' + }), + this.createBindGroupLayout(0, usage2, '2d', { + sampleType: 'unfilterable-float', + format: 'r32float' + })]; return { bindGroupLayouts, @@ -155,14 +175,21 @@ class TextureUsageTracking extends ValidationTest { }; } - testValidationScope(compute) + testValidationScope( + compute, + usage1, + usage2) + { - const { bindGroupLayouts, bindGroups } = this.makeConflictingBindGroups(); + const { bindGroupLayouts, bindGroups } = this.makeTwoBindGroupsWithOneTextureView( + usage1, + usage2 + ); const encoder = this.device.createCommandEncoder(); const pass = compute ? @@ -175,7 +202,7 @@ class TextureUsageTracking extends ValidationTest { }); const pipeline = compute ? this.createNoOpComputePipeline(pipelineLayout) : - this.createNoOpRenderPipeline(pipelineLayout); + this.createNoOpRenderPipeline(pipelineLayout, 'r32float'); return { bindGroup0: bindGroups[0], bindGroup1: bindGroups[1], @@ -237,6 +264,8 @@ expandWithParams( [ { _usageOK: true, type0: 'sampled-texture', type1: 'sampled-texture' }, { _usageOK: false, type0: 'sampled-texture', type1: 'writeonly-storage-texture' }, + { _usageOK: true, type0: 'sampled-texture', type1: 'readonly-storage-texture' }, + { _usageOK: false, type0: 'sampled-texture', type1: 'readwrite-storage-texture' }, { _usageOK: false, type0: 'sampled-texture', type1: 'render-target' }, // Race condition upon multiple writable storage texture is valid. // For p.compute === true, fails at pass.dispatch because aliasing exists. @@ -245,7 +274,34 @@ expandWithParams( type0: 'writeonly-storage-texture', type1: 'writeonly-storage-texture' }, + { + _usageOK: true, + type0: 'readonly-storage-texture', + type1: 'readonly-storage-texture' + }, + { + _usageOK: !p.compute, + type0: 'readwrite-storage-texture', + type1: 'readwrite-storage-texture' + }, + { + _usageOK: false, + type0: 'readonly-storage-texture', + type1: 'writeonly-storage-texture' + }, + { + _usageOK: false, + type0: 'readonly-storage-texture', + type1: 'readwrite-storage-texture' + }, + { + _usageOK: false, + type0: 'writeonly-storage-texture', + type1: 'readwrite-storage-texture' + }, + { _usageOK: false, type0: 'readonly-storage-texture', type1: 'render-target' }, { _usageOK: false, type0: 'writeonly-storage-texture', type1: 'render-target' }, + { _usageOK: false, type0: 'readwrite-storage-texture', type1: 'render-target' }, { _usageOK: false, type0: 'render-target', type1: 'render-target' }] ). @@ -428,6 +484,11 @@ fn((t) => { _resourceSuccess } = t.params; + t.skipIf( + t.isCompatibility, + 'multiple views of the same texture in a single draw/dispatch are not supported in compat, nor are sub ranges of layers' + ); + const texture = t.createTexture({ arrayLayerCount: TOTAL_LAYERS, mipLevelCount: TOTAL_LEVELS, @@ -497,9 +558,13 @@ fn((t) => { const bgls = []; // Create bind groups. Set bind groups in pass directly or set bind groups in bundle. - const storageTextureFormat0 = type0 === 'sampled-texture' ? undefined : 'rgba8unorm'; + const storageTextureFormat0 = type0 === 'sampled-texture' ? undefined : 'r32float'; + const sampleType0 = type0 === 'sampled-texture' ? 'unfilterable-float' : undefined; - const bgl0 = t.createBindGroupLayout(0, type0, dimension0, { format: storageTextureFormat0 }); + const bgl0 = t.createBindGroupLayout(0, type0, dimension0, { + format: storageTextureFormat0, + sampleType: sampleType0 + }); const bindGroup0 = t.device.createBindGroup({ layout: bgl0, entries: [{ binding: 0, resource: view0 }] @@ -513,10 +578,11 @@ fn((t) => { pass.setBindGroup(0, bindGroup0); } if (type1 !== 'render-target') { - const storageTextureFormat1 = type1 === 'sampled-texture' ? undefined : 'rgba8unorm'; - + const storageTextureFormat1 = type1 === 'sampled-texture' ? undefined : 'r32float'; + const sampleType1 = type1 === 'sampled-texture' ? 'unfilterable-float' : undefined; const bgl1 = t.createBindGroupLayout(1, type1, dimension1, { - format: storageTextureFormat1 + format: storageTextureFormat1, + sampleType: sampleType1 }); const bindGroup1 = t.device.createBindGroup({ layout: bgl1, @@ -653,6 +719,8 @@ fn((t) => { _usageSuccess } = t.params; + t.skipIf(t.isCompatibility, 'sub ranges of layers are not supported in compat mode'); + const texture = t.createTexture({ arrayLayerCount: TOTAL_LAYERS, mipLevelCount: TOTAL_LEVELS, @@ -781,10 +849,22 @@ GPUConst.ShaderStage.VERTEX, GPUConst.ShaderStage.FRAGMENT, GPUConst.ShaderStage.COMPUTE] ). -combine('writeVisibility', [0, GPUConst.ShaderStage.FRAGMENT, GPUConst.ShaderStage.COMPUTE]) +combine('writeVisibility', [0, GPUConst.ShaderStage.FRAGMENT, GPUConst.ShaderStage.COMPUTE]). +combine('readEntry', [ +{ texture: { sampleType: 'unfilterable-float' } }, +{ storageTexture: { access: 'read-only', format: 'r32float' } }] +). +combine('storageWriteAccess', ['write-only', 'read-write']) ). fn((t) => { - const { compute, readVisibility, writeVisibility, secondUseConflicts } = t.params; + const { + compute, + readEntry, + storageWriteAccess, + readVisibility, + writeVisibility, + secondUseConflicts + } = t.params; const usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING; const view = t.createTexture({ usage }).createView(); @@ -792,11 +872,11 @@ fn((t) => { const bgl = t.device.createBindGroupLayout({ entries: [ - { binding: 0, visibility: readVisibility, texture: {} }, + { binding: 0, visibility: readVisibility, ...readEntry }, { binding: 1, visibility: writeVisibility, - storageTexture: { access: 'write-only', format: 'rgba8unorm' } + storageTexture: { access: storageWriteAccess, format: 'r32float' } }] }); @@ -850,20 +930,24 @@ combine('readVisibility', [ GPUConst.ShaderStage.VERTEX, GPUConst.ShaderStage.FRAGMENT, GPUConst.ShaderStage.COMPUTE] +). +combine('readEntry', [ +{ texture: { sampleType: 'unfilterable-float' } }, +{ storageTexture: { access: 'read-only', format: 'r32float' } }] ) ). fn((t) => { - const { readVisibility, secondUseConflicts } = t.params; + const { readVisibility, readEntry, secondUseConflicts } = t.params; - // writeonly-storage-texture binding type is not supported in vertex stage. So, this test - // uses writeonly-storage-texture binding as writable binding upon the same subresource if - // vertex stage is not included. Otherwise, it uses output attachment instead. - const usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT; + const usage = + GPUTextureUsage.TEXTURE_BINDING | + GPUTextureUsage.RENDER_ATTACHMENT | + GPUTextureUsage.STORAGE_BINDING; const view = t.createTexture({ usage }).createView(); const view2 = secondUseConflicts ? view : t.createTexture({ usage }).createView(); const bgl = t.device.createBindGroupLayout({ - entries: [{ binding: 0, visibility: readVisibility, texture: {} }] + entries: [{ binding: 0, visibility: readVisibility, ...readEntry }] }); const bindGroup = t.device.createBindGroup({ layout: bgl, @@ -898,8 +982,10 @@ u. combine('compute', [false, true]). combine('callDrawOrDispatch', [false, true]). combine('entry', [ -{ texture: {} }, -{ storageTexture: { access: 'write-only', format: 'rgba8unorm' } }] +{ texture: { sampleType: 'unfilterable-float' } }, +{ storageTexture: { access: 'read-only', format: 'r32float' } }, +{ storageTexture: { access: 'write-only', format: 'r32float' } }, +{ storageTexture: { access: 'read-write', format: 'r32float' } }] ) ). fn((t) => { @@ -912,7 +998,11 @@ fn((t) => { // Create bindGroup0. It has two bindings. These two bindings use different views/subresources. const bglEntries0 = [ - { binding: 0, visibility: GPUShaderStage.FRAGMENT, texture: {} }, + { + binding: 0, + visibility: GPUShaderStage.FRAGMENT, + texture: { sampleType: 'unfilterable-float' } + }, { binding: 1, visibility: GPUShaderStage.FRAGMENT, @@ -930,7 +1020,9 @@ fn((t) => { // Create bindGroup1. It has one binding, which use the same view/subresource of a binding in // bindGroup0. So it may or may not conflicts with that binding in bindGroup0. - const bindGroup1 = t.createBindGroup(0, sampledStorageView, 'sampled-texture', '2d', undefined); + const bindGroup1 = t.createBindGroup(0, sampledStorageView, 'sampled-texture', '2d', { + sampleType: 'unfilterable-float' + }); const encoder = t.device.createCommandEncoder(); const pass = compute ? @@ -941,7 +1033,9 @@ fn((t) => { // But bindings in bindGroup0 should be validated too. pass.setBindGroup(0, bindGroup0); if (callDrawOrDispatch) { - const pipeline = compute ? t.createNoOpComputePipeline() : t.createNoOpRenderPipeline(); + const pipeline = compute ? + t.createNoOpComputePipeline() : + t.createNoOpRenderPipeline('auto', 'r32float'); t.setPipeline(pass, pipeline); t.issueDrawOrDispatch(pass); } @@ -951,7 +1045,9 @@ fn((t) => { // MAINTENANCE_TODO: If the Compatible Usage List // (https://gpuweb.github.io/gpuweb/#compatible-usage-list) gets programmatically defined in // capability_info, use it here, instead of this logic, for clarity. - let success = entry.storageTexture?.access !== 'write-only'; + let success = + entry.storageTexture?.access !== 'write-only' && + entry.storageTexture?.access !== 'read-write'; // Replaced bindings should not be validated in compute pass, because validation only occurs // inside dispatchWorkgroups() which only looks at the current resource usages. success ||= compute; @@ -981,7 +1077,9 @@ expandWithParams(function* ({ type0, type1 }) { case 'multisampled-texture': case 'sampled-texture': return 'TEXTURE_BINDING'; + case 'readonly-storage-texture': case 'writeonly-storage-texture': + case 'readwrite-storage-texture': return 'STORAGE_BINDING'; case 'render-target': return 'RENDER_ATTACHMENT'; @@ -1033,17 +1131,17 @@ fn((t) => { const bindGroups = []; if (type0 !== 'render-target') { - const binding0TexFormat = type0 === 'sampled-texture' ? undefined : 'rgba8unorm'; + const binding0TexFormat = type0 === 'sampled-texture' ? undefined : 'r32float'; bindGroups[0] = t.createBindGroup(0, view, type0, '2d', { format: binding0TexFormat, - sampleType: _sampleCount && 'unfilterable-float' + sampleType: 'unfilterable-float' }); } if (type1 !== 'render-target') { - const binding1TexFormat = type1 === 'sampled-texture' ? undefined : 'rgba8unorm'; + const binding1TexFormat = type1 === 'sampled-texture' ? undefined : 'r32float'; bindGroups[1] = t.createBindGroup(1, view, type1, '2d', { format: binding1TexFormat, - sampleType: _sampleCount && 'unfilterable-float' + sampleType: 'unfilterable-float' }); } @@ -1062,7 +1160,7 @@ fn((t) => { // 'render-target'). if (bindingsInBundle[i]) { const bundleEncoder = t.device.createRenderBundleEncoder({ - colorFormats: ['rgba8unorm'] + colorFormats: ['r32float'] }); bundleEncoder.setBindGroup(i, bindGroups[i]); const bundleInPass = bundleEncoder.finish(); @@ -1078,6 +1176,7 @@ fn((t) => { switch (t) { case 'sampled-texture': case 'multisampled-texture': + case 'readonly-storage-texture': return true; default: return false; @@ -1089,7 +1188,8 @@ fn((t) => { success = true; } - if (type0 === 'writeonly-storage-texture' && type1 === 'writeonly-storage-texture') { + // Writable storage textures (write-only and read-write storage textures) cannot be aliased. + if (type0 === type1) { success = true; } @@ -1110,6 +1210,8 @@ desc( params((u) => u. combine('compute', [false, true]). +combine('readOnlyUsage', ['sampled-texture', 'readonly-storage-texture']). +combine('writableUsage', ['writeonly-storage-texture', 'readwrite-storage-texture']). combine('useBindGroup0', [false, true]). combine('useBindGroup1', [false, true]). combine('setBindGroupsOrder', ['common', 'reversed']). @@ -1119,41 +1221,49 @@ combine('callDrawOrDispatch', [false, true]) fn((t) => { const { compute, + readOnlyUsage, + writableUsage, useBindGroup0, useBindGroup1, setBindGroupsOrder, setPipeline, callDrawOrDispatch } = t.params; + if (writableUsage === 'readwrite-storage-texture') { + t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); + } + const view = t. createTexture({ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING }). createView(); - const bindGroup0 = t.createBindGroup(0, view, 'sampled-texture', '2d', { - format: 'rgba8unorm' + const bindGroup0 = t.createBindGroup(0, view, readOnlyUsage, '2d', { + sampleType: 'unfilterable-float', + format: 'r32float' }); - const bindGroup1 = t.createBindGroup(0, view, 'writeonly-storage-texture', '2d', { - format: 'rgba8unorm' + const bindGroup1 = t.createBindGroup(0, view, writableUsage, '2d', { + format: 'r32float' }); + const writeAccess = writableUsage === 'writeonly-storage-texture' ? 'write' : 'read_write'; const wgslVertex = `@vertex fn main() -> @builtin(position) vec4 { return vec4(); }`; const wgslFragment = pp` ${pp._if(useBindGroup0)} - @group(0) @binding(0) var image0 : texture_storage_2d; + @group(0) @binding(0) var image0 : texture_storage_2d; ${pp._endif} ${pp._if(useBindGroup1)} - @group(1) @binding(0) var image1 : texture_storage_2d; + @group(1) @binding(0) var image1 : texture_storage_2d; ${pp._endif} @fragment fn main() {} `; const wgslCompute = pp` ${pp._if(useBindGroup0)} - @group(0) @binding(0) var image0 : texture_storage_2d; + @group(0) @binding(0) var image0 : texture_storage_2d; ${pp._endif} ${pp._if(useBindGroup1)} - @group(1) @binding(0) var image1 : texture_storage_2d; + @group(1) @binding(0) var image1 : texture_storage_2d; ${pp._endif} @compute @workgroup_size(1) fn main() {} `; @@ -1181,7 +1291,7 @@ fn((t) => { code: wgslFragment }), entryPoint: 'main', - targets: [{ format: 'rgba8unorm', writeMask: 0 }] + targets: [{ format: 'r32float', writeMask: 0 }] }, primitive: { topology: 'triangle-list' } }); @@ -1237,14 +1347,28 @@ desc( params((u) => u. combine('dispatch', ['none', 'direct', 'indirect']). +expandWithParams( + (p) => + [ + { usage1: 'sampled-texture', usage2: 'writeonly-storage-texture' }, + { usage1: 'sampled-texture', usage2: 'readwrite-storage-texture' }, + { usage1: 'readonly-storage-texture', usage2: 'writeonly-storage-texture' }, + { usage1: 'readonly-storage-texture', usage2: 'readwrite-storage-texture' }, + { usage1: 'writeonly-storage-texture', usage2: 'readwrite-storage-texture' }] + +). beginSubcases(). expand('setBindGroup0', (p) => p.dispatch ? [true] : [false, true]). expand('setBindGroup1', (p) => p.dispatch ? [true] : [false, true]) ). fn((t) => { - const { dispatch, setBindGroup0, setBindGroup1 } = t.params; + const { dispatch, usage1, usage2, setBindGroup0, setBindGroup1 } = t.params; - const { bindGroup0, bindGroup1, encoder, pass, pipeline } = t.testValidationScope(true); + const { bindGroup0, bindGroup1, encoder, pass, pipeline } = t.testValidationScope( + true, + usage1, + usage2 + ); assert(pass instanceof GPUComputePassEncoder); t.setPipeline(pass, pipeline); @@ -1283,12 +1407,22 @@ desc( paramsSubcasesOnly((u) => u // .combine('setBindGroup0', [false, true]). -combine('setBindGroup1', [false, true]) +combine('setBindGroup1', [false, true]). +expandWithParams( + (p) => + [ + { usage1: 'sampled-texture', usage2: 'writeonly-storage-texture' }, + { usage1: 'sampled-texture', usage2: 'readwrite-storage-texture' }, + { usage1: 'readonly-storage-texture', usage2: 'writeonly-storage-texture' }, + { usage1: 'readonly-storage-texture', usage2: 'readwrite-storage-texture' }, + { usage1: 'writeonly-storage-texture', usage2: 'readwrite-storage-texture' }] + +) ). fn((t) => { - const { setBindGroup0, setBindGroup1 } = t.params; + const { setBindGroup0, setBindGroup1, usage1, usage2 } = t.params; - const { bindGroup0, bindGroup1, encoder, pass } = t.testValidationScope(false); + const { bindGroup0, bindGroup1, encoder, pass } = t.testValidationScope(false, usage1, usage2); assert(pass instanceof GPURenderPassEncoder); if (setBindGroup0) pass.setBindGroup(0, bindGroup0); @@ -1308,11 +1442,22 @@ desc( boundary in between. This should always be valid. ` ). -paramsSubcasesOnly((u) => u.combine('splitPass', [false, true])). +paramsSubcasesOnly((u) => +u.combine('splitPass', [false, true]).expandWithParams( + (p) => + [ + { usage1: 'sampled-texture', usage2: 'writeonly-storage-texture' }, + { usage1: 'sampled-texture', usage2: 'readwrite-storage-texture' }, + { usage1: 'readonly-storage-texture', usage2: 'writeonly-storage-texture' }, + { usage1: 'readonly-storage-texture', usage2: 'readwrite-storage-texture' }, + { usage1: 'writeonly-storage-texture', usage2: 'readwrite-storage-texture' }] + +) +). fn((t) => { - const { splitPass } = t.params; + const { splitPass, usage1, usage2 } = t.params; - const { bindGroupLayouts, bindGroups } = t.makeConflictingBindGroups(); + const { bindGroupLayouts, bindGroups } = t.makeTwoBindGroupsWithOneTextureView(usage1, usage2); const encoder = t.device.createCommandEncoder(); @@ -1354,24 +1499,36 @@ desc( paramsSubcasesOnly((u) => u // .combine('splitPass', [false, true]). -combine('draw', [false, true]) +combine('draw', [false, true]). +expandWithParams( + (p) => + [ + { usage1: 'sampled-texture', usage2: 'writeonly-storage-texture' }, + { usage1: 'sampled-texture', usage2: 'readwrite-storage-texture' }, + { usage1: 'readonly-storage-texture', usage2: 'writeonly-storage-texture' }, + { usage1: 'readonly-storage-texture', usage2: 'readwrite-storage-texture' }, + { usage1: 'writeonly-storage-texture', usage2: 'readwrite-storage-texture' }] + +) ). fn((t) => { - const { splitPass, draw } = t.params; + const { splitPass, draw, usage1, usage2 } = t.params; - const { bindGroupLayouts, bindGroups } = t.makeConflictingBindGroups(); + const { bindGroupLayouts, bindGroups } = t.makeTwoBindGroupsWithOneTextureView(usage1, usage2); const encoder = t.device.createCommandEncoder(); const pipelineUsingBG0 = t.createNoOpRenderPipeline( t.device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayouts[0]] - }) + }), + 'r32float' ); const pipelineUsingBG1 = t.createNoOpRenderPipeline( t.device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayouts[1]] - }) + }), + 'r32float' ); const attachment = t.createTexture().createView(); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_common.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_common.spec.js index 2a5a002327..5ba4ecfcf7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_common.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_common.spec.js @@ -6,6 +6,21 @@ Texture Usages Validation Tests in Same or Different Render Pass Encoders. import { assert, unreachable } from '../../../../../common/util/util.js'; import { ValidationTest } from '../../validation_test.js'; + + + + + +export const kTextureBindingTypes = [ +'sampled-texture', +'writeonly-storage-texture', +'readonly-storage-texture', +'readwrite-storage-texture']; + +export function IsReadOnlyTextureBindingType(t) { + return t === 'sampled-texture' || t === 'readonly-storage-texture'; +} + class F extends ValidationTest { getColorAttachment( texture, @@ -31,13 +46,27 @@ class F extends ValidationTest { visibility: GPUShaderStage.FRAGMENT }; switch (textureUsage) { - case 'texture': + case 'sampled-texture': bindGroupLayoutEntry.texture = { viewDimension: '2d-array', sampleType }; break; - case 'storage': + case 'readonly-storage-texture': + bindGroupLayoutEntry.storageTexture = { + access: 'read-only', + format: 'r32float', + viewDimension: '2d-array' + }; + break; + case 'readwrite-storage-texture': + bindGroupLayoutEntry.storageTexture = { + access: 'read-write', + format: 'r32float', + viewDimension: '2d-array' + }; + break; + case 'writeonly-storage-texture': bindGroupLayoutEntry.storageTexture = { access: 'write-only', - format: 'rgba8unorm', + format: 'r32float', viewDimension: '2d-array' }; break; @@ -89,7 +118,7 @@ fn((t) => { const { layer0, level0, layer1, level1, inSamePass } = t.params; const texture = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.RENDER_ATTACHMENT, size: [kTextureSize, kTextureSize, kTextureLayers], mipLevelCount: kTextureLevels @@ -152,8 +181,8 @@ combineWithParams([ { bgLayer: 1, bgLayerCount: 1 }, { bgLayer: 1, bgLayerCount: 2 }] ). -combine('bgUsage', ['texture', 'storage']). -unless((t) => t.bgUsage === 'storage' && t.bgLevelCount > 1). +combine('bgUsage', kTextureBindingTypes). +unless((t) => t.bgUsage !== 'sampled-texture' && t.bgLevelCount > 1). combine('inSamePass', [true, false]) ). fn((t) => { @@ -169,7 +198,7 @@ fn((t) => { } = t.params; const texture = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | @@ -184,7 +213,7 @@ fn((t) => { baseMipLevel: bgLevel, mipLevelCount: bgLevelCount }); - const bindGroup = t.createBindGroupForTest(bindGroupView, bgUsage, 'float'); + const bindGroup = t.createBindGroupForTest(bindGroupView, bgUsage, 'unfilterable-float'); const colorAttachment = t.getColorAttachment(texture, { dimension: '2d', @@ -205,7 +234,7 @@ fn((t) => { renderPass.end(); const texture2 = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.RENDER_ATTACHMENT, size: [kTextureSize, kTextureSize, 1], mipLevelCount: 1 @@ -261,7 +290,8 @@ combineWithParams([ { bgLayer: 1, bgLayerCount: 2 }] ). beginSubcases(). -combine('dsReadOnly', [true, false]). +combine('depthReadOnly', [true, false]). +combine('stencilReadOnly', [true, false]). combine('bgAspect', ['depth-only', 'stencil-only']). combine('inSamePass', [true, false]) ). @@ -273,7 +303,8 @@ fn((t) => { bgLevelCount, bgLayer, bgLayerCount, - dsReadOnly, + depthReadOnly, + stencilReadOnly, bgAspect, inSamePass } = t.params; @@ -293,7 +324,7 @@ fn((t) => { aspect: bgAspect }); const sampleType = bgAspect === 'depth-only' ? 'depth' : 'uint'; - const bindGroup = t.createBindGroupForTest(bindGroupView, 'texture', sampleType); + const bindGroup = t.createBindGroupForTest(bindGroupView, 'sampled-texture', sampleType); const attachmentView = texture.createView({ dimension: '2d', @@ -304,12 +335,12 @@ fn((t) => { }); const depthStencilAttachment = { view: attachmentView, - depthReadOnly: dsReadOnly, - depthLoadOp: dsReadOnly ? undefined : 'load', - depthStoreOp: dsReadOnly ? undefined : 'store', - stencilReadOnly: dsReadOnly, - stencilLoadOp: dsReadOnly ? undefined : 'load', - stencilStoreOp: dsReadOnly ? undefined : 'store' + depthReadOnly, + depthLoadOp: depthReadOnly ? undefined : 'load', + depthStoreOp: depthReadOnly ? undefined : 'store', + stencilReadOnly, + stencilLoadOp: stencilReadOnly ? undefined : 'load', + stencilStoreOp: stencilReadOnly ? undefined : 'store' }; const encoder = t.device.createCommandEncoder(); @@ -350,8 +381,11 @@ fn((t) => { bgLayer + bgLayerCount - 1 ); const isNotOverlapped = isMipLevelNotOverlapped || isArrayLayerNotOverlapped; + const readonly = + bgAspect === 'stencil-only' && stencilReadOnly || + bgAspect === 'depth-only' && depthReadOnly; - const success = !inSamePass || isNotOverlapped || dsReadOnly; + const success = !inSamePass || isNotOverlapped || readonly; t.expectValidationError(() => { encoder.finish(); }, !success); @@ -388,20 +422,21 @@ combine('bg1Layers', [ { base: 1, count: 1 }, { base: 1, count: 2 }] ). -combine('bgUsage0', ['texture', 'storage']). -combine('bgUsage1', ['texture', 'storage']). +combine('bgUsage0', kTextureBindingTypes). +combine('bgUsage1', kTextureBindingTypes). unless( (t) => - t.bgUsage0 === 'storage' && t.bg0Levels.count > 1 || - t.bgUsage1 === 'storage' && t.bg1Levels.count > 1 + t.bgUsage0 !== 'sampled-texture' && t.bg0Levels.count > 1 || + t.bgUsage1 !== 'sampled-texture' && t.bg1Levels.count > 1 ). +beginSubcases(). combine('inSamePass', [true, false]) ). fn((t) => { const { bg0Levels, bg0Layers, bg1Levels, bg1Layers, bgUsage0, bgUsage1, inSamePass } = t.params; const texture = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING, size: [kTextureSize, kTextureSize, kTextureLayers], mipLevelCount: kTextureLevels @@ -420,11 +455,11 @@ fn((t) => { baseMipLevel: bg1Levels.base, mipLevelCount: bg1Levels.count }); - const bindGroup0 = t.createBindGroupForTest(bg0, bgUsage0, 'float'); - const bindGroup1 = t.createBindGroupForTest(bg1, bgUsage1, 'float'); + const bindGroup0 = t.createBindGroupForTest(bg0, bgUsage0, 'unfilterable-float'); + const bindGroup1 = t.createBindGroupForTest(bg1, bgUsage1, 'unfilterable-float'); const colorTexture = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.RENDER_ATTACHMENT, size: [kTextureSize, kTextureSize, 1], mipLevelCount: 1 @@ -449,6 +484,8 @@ fn((t) => { renderPass2.end(); } + const bothReadOnly = + IsReadOnlyTextureBindingType(bgUsage0) && IsReadOnlyTextureBindingType(bgUsage1); const isMipLevelNotOverlapped = t.isRangeNotOverlapped( bg0Levels.base, bg0Levels.base + bg0Levels.count - 1, @@ -463,7 +500,7 @@ fn((t) => { ); const isNotOverlapped = isMipLevelNotOverlapped || isArrayLayerNotOverlapped; - const success = !inSamePass || isNotOverlapped || bgUsage0 === bgUsage1; + const success = !inSamePass || bothReadOnly || isNotOverlapped || bgUsage0 === bgUsage1; t.expectValidationError(() => { encoder.finish(); }, !success); @@ -531,8 +568,8 @@ fn((t) => { const sampleType0 = aspect0 === 'depth-only' ? 'depth' : 'uint'; const sampleType1 = aspect1 === 'depth-only' ? 'depth' : 'uint'; - const bindGroup0 = t.createBindGroupForTest(bindGroupView0, 'texture', sampleType0); - const bindGroup1 = t.createBindGroupForTest(bindGroupView1, 'texture', sampleType1); + const bindGroup0 = t.createBindGroupForTest(bindGroupView0, 'sampled-texture', sampleType0); + const bindGroup1 = t.createBindGroupForTest(bindGroupView1, 'sampled-texture', sampleType1); const colorTexture = t.device.createTexture({ format: 'rgba8unorm', diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_misc.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_misc.spec.js index 1cab1548ea..0b7733c9d6 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_misc.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_misc.spec.js @@ -5,6 +5,11 @@ Texture Usages Validation Tests on All Kinds of WebGPU Subresource Usage Scopes. `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { unreachable } from '../../../../../common/util/util.js'; import { ValidationTest } from '../../validation_test.js'; +import { + + kTextureBindingTypes, + IsReadOnlyTextureBindingType } from +'../texture/in_render_common.spec.js'; class F extends ValidationTest { createBindGroupLayoutForTest( @@ -18,13 +23,27 @@ class F extends ValidationTest { }; switch (textureUsage) { - case 'texture': + case 'sampled-texture': bindGroupLayoutEntry.texture = { viewDimension: '2d-array', sampleType }; break; - case 'storage': + case 'readonly-storage-texture': + bindGroupLayoutEntry.storageTexture = { + access: 'read-only', + format: 'r32float', + viewDimension: '2d-array' + }; + break; + case 'writeonly-storage-texture': bindGroupLayoutEntry.storageTexture = { access: 'write-only', - format: 'rgba8unorm', + format: 'r32float', + viewDimension: '2d-array' + }; + break; + case 'readwrite-storage-texture': + bindGroupLayoutEntry.storageTexture = { + access: 'read-write', + format: 'r32float', viewDimension: '2d-array' }; break; @@ -64,20 +83,16 @@ desc( ). params((u) => u. -combineWithParams([ -{ useDifferentTextureAsTexture2: true, baseLayer2: 0, view2Binding: 'texture' }, -{ useDifferentTextureAsTexture2: false, baseLayer2: 0, view2Binding: 'texture' }, -{ useDifferentTextureAsTexture2: false, baseLayer2: 1, view2Binding: 'texture' }, -{ useDifferentTextureAsTexture2: false, baseLayer2: 0, view2Binding: 'storage' }, -{ useDifferentTextureAsTexture2: false, baseLayer2: 1, view2Binding: 'storage' }] -). -combine('hasConflict', [true, false]) +combine('useDifferentTextureAsTexture2', [true, false]). +combine('baseLayer2', [0, 1]). +combine('view1Binding', kTextureBindingTypes). +combine('view2Binding', kTextureBindingTypes) ). fn((t) => { - const { useDifferentTextureAsTexture2, baseLayer2, view2Binding, hasConflict } = t.params; + const { useDifferentTextureAsTexture2, baseLayer2, view1Binding, view2Binding } = t.params; const texture0 = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING, size: [kTextureSize, kTextureSize, kTextureLayers] }); @@ -87,19 +102,12 @@ fn((t) => { baseArrayLayer: 0, arrayLayerCount: 1 }); - const bindGroup0 = t.createBindGroupForTest(textureView0, view2Binding, 'float'); - - // In one renderPassEncoder it is an error to set both bindGroup0 and bindGroup1. - const view1Binding = hasConflict ? - view2Binding === 'texture' ? - 'storage' : - 'texture' : - view2Binding; - const bindGroup1 = t.createBindGroupForTest(textureView0, view1Binding, 'float'); + const bindGroup0 = t.createBindGroupForTest(textureView0, view1Binding, 'unfilterable-float'); + const bindGroup1 = t.createBindGroupForTest(textureView0, view2Binding, 'unfilterable-float'); const texture2 = useDifferentTextureAsTexture2 ? t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING, size: [kTextureSize, kTextureSize, kTextureLayers] }) : @@ -110,10 +118,14 @@ fn((t) => { arrayLayerCount: kTextureLayers - baseLayer2 }); // There should be no conflict between bindGroup0 and validBindGroup2. - const validBindGroup2 = t.createBindGroupForTest(textureView2, view2Binding, 'float'); + const validBindGroup2 = t.createBindGroupForTest( + textureView2, + view2Binding, + 'unfilterable-float' + ); - const colorTexture = t.device.createTexture({ - format: 'rgba8unorm', + const unusedColorTexture = t.device.createTexture({ + format: 'r32float', usage: GPUTextureUsage.RENDER_ATTACHMENT, size: [kTextureSize, kTextureSize, 1] }); @@ -121,7 +133,7 @@ fn((t) => { const renderPassEncoder = encoder.beginRenderPass({ colorAttachments: [ { - view: colorTexture.createView(), + view: unusedColorTexture.createView(), loadOp: 'load', storeOp: 'store' }] @@ -132,9 +144,12 @@ fn((t) => { renderPassEncoder.setBindGroup(1, validBindGroup2); renderPassEncoder.end(); + const noConflict = + IsReadOnlyTextureBindingType(view1Binding) && IsReadOnlyTextureBindingType(view2Binding) || + view1Binding === view2Binding; t.expectValidationError(() => { encoder.finish(); - }, hasConflict); + }, !noConflict); }); g.test('subresources,set_bind_group_on_same_index_depth_stencil_texture'). @@ -154,7 +169,10 @@ fn((t) => { const depthStencilTexture = t.device.createTexture({ format: 'depth24plus-stencil8', usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT, - size: [kTextureSize, kTextureSize, 1] + size: [kTextureSize, kTextureSize, 1], + ...(t.isCompatibility && { + textureBindingViewDimension: '2d-array' + }) }); const conflictedToNonReadOnlyAttachmentBindGroup = t.createBindGroupForTest( @@ -162,21 +180,24 @@ fn((t) => { dimension: '2d-array', aspect: bindAspect }), - 'texture', + 'sampled-texture', bindAspect === 'depth-only' ? 'depth' : 'uint' ); const colorTexture = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING, - size: [kTextureSize, kTextureSize, 1] + size: [kTextureSize, kTextureSize, 1], + ...(t.isCompatibility && { + textureBindingViewDimension: '2d-array' + }) }); const validBindGroup = t.createBindGroupForTest( colorTexture.createView({ dimension: '2d-array' }), - 'texture', - 'float' + 'sampled-texture', + 'unfilterable-float' ); const encoder = t.device.createCommandEncoder(); @@ -204,12 +225,24 @@ desc( used in the same render or compute pass encoder, its list of internal usages within one usage scope can only be a compatible usage list.` ). -params((u) => u.combine('inRenderPass', [true, false]).combine('hasConflict', [true, false])). +params((u) => +u. +combine('inRenderPass', [true, false]). +combine('textureUsage0', kTextureBindingTypes). +combine('textureUsage1', kTextureBindingTypes) +). fn((t) => { - const { inRenderPass, hasConflict } = t.params; + const { inRenderPass, textureUsage0, textureUsage1 } = t.params; + + if ( + textureUsage0 === 'readwrite-storage-texture' || + textureUsage1 === 'readwrite-storage-texture') + { + t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); + } const texture0 = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING, size: [kTextureSize, kTextureSize, kTextureLayers] }); @@ -221,40 +254,85 @@ fn((t) => { }); const visibility = inRenderPass ? GPUShaderStage.FRAGMENT : GPUShaderStage.COMPUTE; // bindGroup0 is used by the pipelines, and bindGroup1 is not used by the pipelines. - const textureUsage0 = inRenderPass ? 'texture' : 'storage'; - const textureUsage1 = hasConflict ? inRenderPass ? 'storage' : 'texture' : textureUsage0; - const bindGroup0 = t.createBindGroupForTest(textureView0, textureUsage0, 'float', visibility); - const bindGroup1 = t.createBindGroupForTest(textureView0, textureUsage1, 'float', visibility); + const bindGroup0 = t.createBindGroupForTest( + textureView0, + textureUsage0, + 'unfilterable-float', + visibility + ); + const bindGroup1 = t.createBindGroupForTest( + textureView0, + textureUsage1, + 'unfilterable-float', + visibility + ); const encoder = t.device.createCommandEncoder(); const colorTexture = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.RENDER_ATTACHMENT, size: [kTextureSize, kTextureSize, 1] }); - const pipelineLayout = t.device.createPipelineLayout({ - bindGroupLayouts: [t.createBindGroupLayoutForTest(textureUsage0, 'float', visibility)] - }); if (inRenderPass) { + let fragmentShader = ''; + switch (textureUsage0) { + case 'sampled-texture': + fragmentShader = ` + @group(0) @binding(0) var texture0 : texture_2d_array; + @fragment fn main() + -> @location(0) vec4 { + return textureLoad(texture0, vec2(), 0, 0); + } + `; + break; + case `readonly-storage-texture`: + fragmentShader = ` + @group(0) @binding(0) var texture0 : texture_storage_2d_array; + @fragment fn main() + -> @location(0) vec4 { + return textureLoad(texture0, vec2(), 0); + } + `; + break; + case `writeonly-storage-texture`: + fragmentShader = ` + @group(0) @binding(0) var texture0 : texture_storage_2d_array; + @fragment fn main() + -> @location(0) vec4 { + textureStore(texture0, vec2i(), 0, vec4f(1, 0, 0, 1)); + return vec4f(0, 0, 0, 1); + } + `; + break; + case `readwrite-storage-texture`: + fragmentShader = ` + @group(0) @binding(0) var texture0 : texture_storage_2d_array; + @fragment fn main() + -> @location(0) vec4 { + let color = textureLoad(texture0, vec2i(), 0); + textureStore(texture0, vec2i(), 0, vec4f(1, 0, 0, 1)); + return color; + } + `; + break; + } + const renderPipeline = t.device.createRenderPipeline({ - layout: pipelineLayout, + layout: t.device.createPipelineLayout({ + bindGroupLayouts: [ + t.createBindGroupLayoutForTest(textureUsage0, 'unfilterable-float', visibility)] + + }), vertex: { module: t.device.createShaderModule({ code: t.getNoOpShaderCode('VERTEX') - }), - entryPoint: 'main' + }) }, fragment: { module: t.device.createShaderModule({ - code: ` - @group(0) @binding(0) var texture0 : texture_2d_array; - @fragment fn main() - -> @location(0) vec4 { - return textureLoad(texture0, vec2(), 0, 0); - }` + code: fragmentShader }), - entryPoint: 'main', - targets: [{ format: 'rgba8unorm' }] + targets: [{ format: 'r32float' }] } }); @@ -273,29 +351,97 @@ fn((t) => { renderPassEncoder.draw(1); renderPassEncoder.end(); } else { + let computeShader = ''; + switch (textureUsage0) { + case 'sampled-texture': + computeShader = ` + @group(0) @binding(0) var texture0 : texture_2d_array; + @group(1) @binding(0) var writableStorage : texture_storage_2d_array; + @compute @workgroup_size(1) fn main() { + let value = textureLoad(texture0, vec2i(), 0, 0); + textureStore(writableStorage, vec2i(), 0, value); + } + `; + break; + case `readonly-storage-texture`: + computeShader = ` + @group(0) @binding(0) var texture0 : texture_storage_2d_array; + @group(1) @binding(0) var writableStorage : texture_storage_2d_array; + @compute @workgroup_size(1) fn main() { + let value = textureLoad(texture0, vec2(), 0); + textureStore(writableStorage, vec2i(), 0, value); + } + `; + break; + case `writeonly-storage-texture`: + computeShader = ` + @group(0) @binding(0) var texture0 : texture_storage_2d_array; + @group(1) @binding(0) var writableStorage : texture_storage_2d_array; + @compute @workgroup_size(1) fn main() { + textureStore(texture0, vec2i(), 0, vec4f(1, 0, 0, 1)); + textureStore(writableStorage, vec2i(), 0, vec4f(1, 0, 0, 1)); + } + `; + break; + case `readwrite-storage-texture`: + computeShader = ` + @group(0) @binding(0) var texture0 : texture_storage_2d_array; + @group(1) @binding(0) var writableStorage : texture_storage_2d_array; + @compute @workgroup_size(1) fn main() { + let color = textureLoad(texture0, vec2i(), 0); + textureStore(texture0, vec2i(), 0, vec4f(1, 0, 0, 1)); + textureStore(writableStorage, vec2i(), 0, color); + } + `; + break; + } + + const pipelineLayout = t.device.createPipelineLayout({ + bindGroupLayouts: [ + t.createBindGroupLayoutForTest(textureUsage0, 'unfilterable-float', visibility), + t.createBindGroupLayoutForTest( + 'writeonly-storage-texture', + 'unfilterable-float', + visibility + )] + + }); const computePipeline = t.device.createComputePipeline({ layout: pipelineLayout, compute: { module: t.device.createShaderModule({ - code: ` - @group(0) @binding(0) var texture0 : texture_storage_2d_array; - @compute @workgroup_size(1) - fn main() { - textureStore(texture0, vec2(), 0, vec4()); - }` - }), - entryPoint: 'main' + code: computeShader + }) } }); + + const writableStorageTexture = t.device.createTexture({ + format: 'r32float', + usage: GPUTextureUsage.STORAGE_BINDING, + size: [kTextureSize, kTextureSize, 1] + }); + const writableStorageTextureView = writableStorageTexture.createView({ + dimension: '2d-array', + baseArrayLayer: 0, + arrayLayerCount: 1 + }); + const writableStorageTextureBindGroup = t.createBindGroupForTest( + writableStorageTextureView, + 'writeonly-storage-texture', + 'unfilterable-float', + visibility + ); + const computePassEncoder = encoder.beginComputePass(); computePassEncoder.setBindGroup(0, bindGroup0); - computePassEncoder.setBindGroup(1, bindGroup1); + computePassEncoder.setBindGroup(1, writableStorageTextureBindGroup); + computePassEncoder.setBindGroup(2, bindGroup1); computePassEncoder.setPipeline(computePipeline); computePassEncoder.dispatchWorkgroups(1); computePassEncoder.end(); } - // In WebGPU SPEC (Chapter 3.4.5, Synchronization): + // In WebGPU SPEC (https://gpuweb.github.io/gpuweb/#programming-model-synchronization): // This specification defines the following usage scopes: // - In a compute pass, each dispatch command (dispatchWorkgroups() or // dispatchWorkgroupsIndirect()) is one usage scope. A subresource is "used" in the usage @@ -306,7 +452,11 @@ fn((t) => { // referenced by any (state-setting or non-state-setting) command. For example, in // setBindGroup(index, bindGroup, dynamicOffsets), every subresource in bindGroup is "used" in // the render pass’s usage scope. - const success = !inRenderPass || !hasConflict; + const success = + !inRenderPass || + IsReadOnlyTextureBindingType(textureUsage0) && + IsReadOnlyTextureBindingType(textureUsage1) || + textureUsage0 === textureUsage1; t.expectValidationError(() => { encoder.finish(); }, !success); @@ -324,16 +474,14 @@ u. combine('usage0', [ 'copy-src', 'copy-dst', -'texture', -'storage', -'color-attachment'] +'color-attachment', +...kTextureBindingTypes] ). combine('usage1', [ 'copy-src', 'copy-dst', -'texture', -'storage', -'color-attachment'] +'color-attachment', +...kTextureBindingTypes] ). filter( ({ usage0, usage1 }) => @@ -347,14 +495,17 @@ fn((t) => { const { usage0, usage1 } = t.params; const texture = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT, - size: [kTextureSize, kTextureSize, 1] + size: [kTextureSize, kTextureSize, 1], + ...(t.isCompatibility && { + textureBindingViewDimension: '2d-array' + }) }); const UseTextureOnCommandEncoder = ( @@ -386,10 +537,12 @@ fn((t) => { renderPassEncoder.end(); break; } - case 'texture': - case 'storage':{ + case 'sampled-texture': + case 'readonly-storage-texture': + case 'writeonly-storage-texture': + case 'readwrite-storage-texture':{ const colorTexture = t.device.createTexture({ - format: 'rgba8unorm', + format: 'r32float', usage: GPUTextureUsage.RENDER_ATTACHMENT, size: [kTextureSize, kTextureSize, 1] }); @@ -403,7 +556,7 @@ fn((t) => { dimension: '2d-array' }), usage, - 'float' + 'unfilterable-float' ); renderPassEncoder.setBindGroup(0, bindGroup); renderPassEncoder.end(); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/entry_point.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/entry_point.spec.js index a76f5550aa..c8e7a0109d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/entry_point.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/entry_point.spec.js @@ -5,6 +5,7 @@ This tests entry point validation of compute/render pipelines and their shader m The entryPoint in shader module include standard "main" and others. The entryPoint assigned in descriptor include: +- Undefined with matching entry point for stage - Matching case (control case) - Empty string - Mistyping @@ -12,7 +13,6 @@ The entryPoint assigned in descriptor include: - Unicode entrypoints and their ASCIIfied version TODO: -- Test unicode normalization (gpuweb/gpuweb#1160) - Fine-tune test cases to reduce number by removing trivially similar cases `;import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { kDefaultVertexShaderCode, getShaderWithEntryPoint } from '../../../util/shader.js'; @@ -43,23 +43,52 @@ const kEntryPointTestCases = [ g.test('compute'). desc( ` -Tests calling createComputePipeline(Async) with valid vertex stage shader and different entryPoints, +Tests calling createComputePipeline(Async) with valid compute stage shader and different entryPoints, and check that the APIs only accept matching entryPoint. ` ). -params((u) => u.combine('isAsync', [true, false]).combineWithParams(kEntryPointTestCases)). +params((u) => +u. +combine('isAsync', [true, false]). +combine('shaderModuleStage', ['compute', 'vertex', 'fragment']). +beginSubcases(). +combine('provideEntryPoint', [true, false]). +combine('extraEntryPoint', [true, false]). +combineWithParams(kEntryPointTestCases) +). fn((t) => { - const { isAsync, shaderModuleEntryPoint, stageEntryPoint } = t.params; + const { + isAsync, + provideEntryPoint, + extraEntryPoint, + shaderModuleStage, + shaderModuleEntryPoint, + stageEntryPoint + } = t.params; + const entryPoint = provideEntryPoint ? stageEntryPoint : undefined; + let code = getShaderWithEntryPoint(shaderModuleStage, shaderModuleEntryPoint); + if (extraEntryPoint) { + code += ` ${getShaderWithEntryPoint(shaderModuleStage, 'extra')}`; + } const descriptor = { layout: 'auto', compute: { module: t.device.createShaderModule({ - code: getShaderWithEntryPoint('compute', shaderModuleEntryPoint) + code }), - entryPoint: stageEntryPoint + entryPoint } }; - const _success = shaderModuleEntryPoint === stageEntryPoint; + let _success = true; + if (shaderModuleStage !== 'compute') { + _success = false; + } + if (!provideEntryPoint && extraEntryPoint) { + _success = false; + } + if (shaderModuleEntryPoint !== stageEntryPoint && provideEntryPoint) { + _success = false; + } t.doCreateComputePipelineTest(isAsync, _success, descriptor); }); @@ -70,19 +99,46 @@ Tests calling createRenderPipeline(Async) with valid vertex stage shader and dif and check that the APIs only accept matching entryPoint. ` ). -params((u) => u.combine('isAsync', [true, false]).combineWithParams(kEntryPointTestCases)). +params((u) => +u. +combine('isAsync', [true, false]). +combine('shaderModuleStage', ['compute', 'vertex', 'fragment']). +beginSubcases(). +combine('provideEntryPoint', [true, false]). +combine('extraEntryPoint', [true, false]). +combineWithParams(kEntryPointTestCases) +). fn((t) => { - const { isAsync, shaderModuleEntryPoint, stageEntryPoint } = t.params; + const { + isAsync, + provideEntryPoint, + extraEntryPoint, + shaderModuleStage, + shaderModuleEntryPoint, + stageEntryPoint + } = t.params; + const entryPoint = provideEntryPoint ? stageEntryPoint : undefined; + let code = getShaderWithEntryPoint(shaderModuleStage, shaderModuleEntryPoint); + if (extraEntryPoint) { + code += ` ${getShaderWithEntryPoint(shaderModuleStage, 'extra')}`; + } const descriptor = { layout: 'auto', vertex: { - module: t.device.createShaderModule({ - code: getShaderWithEntryPoint('vertex', shaderModuleEntryPoint) - }), - entryPoint: stageEntryPoint + module: t.device.createShaderModule({ code }), + entryPoint } }; - const _success = shaderModuleEntryPoint === stageEntryPoint; + let _success = true; + if (shaderModuleStage !== 'vertex') { + _success = false; + } + if (!provideEntryPoint && extraEntryPoint) { + _success = false; + } + if (shaderModuleEntryPoint !== stageEntryPoint && provideEntryPoint) { + _success = false; + } t.doCreateRenderPipelineTest(isAsync, _success, descriptor); }); @@ -93,25 +149,155 @@ Tests calling createRenderPipeline(Async) with valid fragment stage shader and d and check that the APIs only accept matching entryPoint. ` ). -params((u) => u.combine('isAsync', [true, false]).combineWithParams(kEntryPointTestCases)). +params((u) => +u. +combine('isAsync', [true, false]). +combine('shaderModuleStage', ['compute', 'vertex', 'fragment']). +beginSubcases(). +combine('provideEntryPoint', [true, false]). +combine('extraEntryPoint', [true, false]). +combineWithParams(kEntryPointTestCases) +). fn((t) => { - const { isAsync, shaderModuleEntryPoint, stageEntryPoint } = t.params; + const { + isAsync, + provideEntryPoint, + extraEntryPoint, + shaderModuleStage, + shaderModuleEntryPoint, + stageEntryPoint + } = t.params; + const entryPoint = provideEntryPoint ? stageEntryPoint : undefined; + let code = getShaderWithEntryPoint(shaderModuleStage, shaderModuleEntryPoint); + if (extraEntryPoint) { + code += ` ${getShaderWithEntryPoint(shaderModuleStage, 'extra')}`; + } const descriptor = { layout: 'auto', vertex: { module: t.device.createShaderModule({ code: kDefaultVertexShaderCode - }), - entryPoint: 'main' + }) }, fragment: { module: t.device.createShaderModule({ - code: getShaderWithEntryPoint('fragment', shaderModuleEntryPoint) + code }), - entryPoint: stageEntryPoint, + entryPoint, targets: [{ format: 'rgba8unorm' }] } }; - const _success = shaderModuleEntryPoint === stageEntryPoint; + let _success = true; + if (shaderModuleStage !== 'fragment') { + _success = false; + } + if (!provideEntryPoint && extraEntryPoint) { + _success = false; + } + if (shaderModuleEntryPoint !== stageEntryPoint && provideEntryPoint) { + _success = false; + } t.doCreateRenderPipelineTest(isAsync, _success, descriptor); +}); + +g.test('compute_undefined_entry_point_and_extra_stage'). +desc( + ` +Tests calling createComputePipeline(Async) with compute stage shader and +an undefined entryPoint is valid if there's an extra shader stage. +` +). +params((u) => +u. +combine('isAsync', [true, false]). +combine('extraShaderModuleStage', ['compute', 'vertex', 'fragment']) +). +fn((t) => { + const { isAsync, extraShaderModuleStage } = t.params; + const code = ` + ${getShaderWithEntryPoint('compute', 'main')} + ${getShaderWithEntryPoint(extraShaderModuleStage, 'extra')} + `; + const descriptor = { + layout: 'auto', + compute: { + module: t.device.createShaderModule({ + code + }), + entryPoint: undefined + } + }; + + const success = extraShaderModuleStage !== 'compute'; + t.doCreateComputePipelineTest(isAsync, success, descriptor); +}); + +g.test('vertex_undefined_entry_point_and_extra_stage'). +desc( + ` +Tests calling createRenderPipeline(Async) with vertex stage shader and +an undefined entryPoint is valid if there's an extra shader stage. +` +). +params((u) => +u. +combine('isAsync', [true, false]). +combine('extraShaderModuleStage', ['compute', 'vertex', 'fragment']) +). +fn((t) => { + const { isAsync, extraShaderModuleStage } = t.params; + const code = ` + ${getShaderWithEntryPoint('vertex', 'main')} + ${getShaderWithEntryPoint(extraShaderModuleStage, 'extra')} + `; + const descriptor = { + layout: 'auto', + vertex: { + module: t.device.createShaderModule({ + code + }), + entryPoint: undefined + } + }; + + const success = extraShaderModuleStage !== 'vertex'; + t.doCreateRenderPipelineTest(isAsync, success, descriptor); +}); + +g.test('fragment_undefined_entry_point_and_extra_stage'). +desc( + ` +Tests calling createRenderPipeline(Async) with fragment stage shader and +an undefined entryPoint is valid if there's an extra shader stage. +` +). +params((u) => +u. +combine('isAsync', [true, false]). +combine('extraShaderModuleStage', ['compute', 'vertex', 'fragment']) +). +fn((t) => { + const { isAsync, extraShaderModuleStage } = t.params; + const code = ` + ${getShaderWithEntryPoint('fragment', 'main')} + ${getShaderWithEntryPoint(extraShaderModuleStage, 'extra')} + `; + const descriptor = { + layout: 'auto', + vertex: { + module: t.device.createShaderModule({ + code: kDefaultVertexShaderCode + }) + }, + fragment: { + module: t.device.createShaderModule({ + code + }), + entryPoint: undefined, + targets: [{ format: 'rgba8unorm' }] + } + }; + + const success = extraShaderModuleStage !== 'fragment'; + t.doCreateRenderPipelineTest(isAsync, success, descriptor); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/state/device_lost/destroy.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/state/device_lost/destroy.spec.js index d5087f9315..e8a43b50f7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/state/device_lost/destroy.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/state/device_lost/destroy.spec.js @@ -704,10 +704,7 @@ fn(async (t) => { entries: [ { binding: 0, - resource: t.device.importExternalTexture({ - - source: source - }) + resource: t.device.importExternalTexture({ source }) }] }); @@ -899,7 +896,12 @@ fn(async (t) => { const { type, stage, awaitLost } = t.params; const querySet = t.device.createQuerySet({ type, count: 2 }); await t.executeCommandsAfterDestroy(stage, awaitLost, 'non-pass', (maker) => { - maker.encoder.writeTimestamp(querySet, 0); + try { + + maker.encoder.writeTimestamp(querySet, 0); + } catch (ex) { + t.skipIf(ex instanceof TypeError, 'writeTimestamp is actually not available'); + } return maker; }); }); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/bgra8unorm_storage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/bgra8unorm_storage.spec.js index 57e1c5a23e..cae789a19d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/bgra8unorm_storage.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/bgra8unorm_storage.spec.js @@ -81,37 +81,6 @@ fn((t) => { }); }); -g.test('create_shader_module_with_bgra8unorm_storage'). -desc( - ` -Test that it is valid to declare the format of a storage texture as bgra8unorm in a shader module if -the feature bgra8unorm-storage is enabled. -` -). -beforeAllSubcases((t) => { - t.selectDeviceOrSkipTestCase('bgra8unorm-storage'); -}). -params((u) => u.combine('shaderType', ['fragment', 'compute'])). -fn((t) => { - const { shaderType } = t.params; - - t.testCreateShaderModuleWithBGRA8UnormStorage(shaderType, true); -}); - -g.test('create_shader_module_without_bgra8unorm_storage'). -desc( - ` -Test that it is invalid to declare the format of a storage texture as bgra8unorm in a shader module -if the feature bgra8unorm-storage is not enabled. -` -). -params((u) => u.combine('shaderType', ['fragment', 'compute'])). -fn((t) => { - const { shaderType } = t.params; - - t.testCreateShaderModuleWithBGRA8UnormStorage(shaderType, false); -}); - g.test('configure_storage_usage_on_canvas_context_without_bgra8unorm_storage'). desc( ` diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/utils.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/utils.js new file mode 100644 index 0000000000..de27f6773a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/utils.js @@ -0,0 +1,275 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + + + + + + + +/** + * Returns an array of possible resources + */ +function generateResources() { + const resources = [ + // Buffers + { + buffer: { type: 'uniform' }, + code: `var res : array`, + staticUse: `res[0]` + }, + { + buffer: { type: 'storage' }, + code: `var res : array`, + staticUse: `res[0]` + }, + { + buffer: { type: 'read-only-storage' }, + code: `var res : array`, + staticUse: `res[0]` + }, + + // Samplers + { + sampler: { type: 'filtering' }, + code: `var res : sampler` + }, + { + sampler: { type: 'non-filtering' }, + code: `var res : sampler` + }, + { + sampler: { type: 'comparison' }, + code: `var res : sampler_comparison` + }, + // Multisampled textures + { + texture: { sampleType: 'depth', viewDimension: '2d', multisampled: true }, + code: `var res : texture_depth_multisampled_2d` + }, + { + texture: { sampleType: 'unfilterable-float', viewDimension: '2d', multisampled: true }, + code: `var res : texture_multisampled_2d` + }, + { + texture: { sampleType: 'sint', viewDimension: '2d', multisampled: true }, + code: `var res : texture_multisampled_2d` + }, + { + texture: { sampleType: 'uint', viewDimension: '2d', multisampled: true }, + code: `var res : texture_multisampled_2d` + }]; + + + // Sampled textures + const sampleDims = [ + '1d', + '2d', + '2d-array', + '3d', + 'cube', + 'cube-array']; + + const sampleTypes = ['float', 'unfilterable-float', 'sint', 'uint']; + const sampleWGSL = ['f32', 'f32', 'i32', 'u32']; + for (const dim of sampleDims) { + let i = 0; + for (const type of sampleTypes) { + resources.push({ + texture: { sampleType: type, viewDimension: dim, multisampled: false }, + code: `var res : texture_${dim.replace('-', '_')}<${sampleWGSL[i++]}>` + }); + } + } + + // Depth textures + const depthDims = ['2d', '2d-array', 'cube', 'cube-array']; + for (const dim of depthDims) { + resources.push({ + texture: { sampleType: 'depth', viewDimension: dim, multisampled: false }, + code: `var res : texture_depth_${dim.replace('-', '_')}` + }); + } + + // Storage textures + // Only cover r32uint, r32sint, and r32float here for ease of testing. + const storageDims = ['1d', '2d', '2d-array', '3d']; + const formats = ['r32float', 'r32sint', 'r32uint']; + const accesses = ['write-only', 'read-only', 'read-write']; + for (const dim of storageDims) { + for (const format of formats) { + for (const access of accesses) { + resources.push({ + storageTexture: { access, format, viewDimension: dim }, + code: `var res : texture_storage_${dim.replace('-', '_')}<${format},${access. + replace('-only', ''). + replace('-', '_')}>` + }); + } + } + } + + return resources; +} + +/** + * Returns a string suitable as a Record key. + */ +function resourceKey(res) { + if (res.buffer) { + return `${res.buffer.type}_buffer`; + } + if (res.sampler) { + return `${res.sampler.type}_sampler`; + } + if (res.texture) { + return `texture_${res.texture.sampleType}_${res.texture.viewDimension}_${res.texture.multisampled}`; + } + if (res.storageTexture) { + return `storage_texture_${res.storageTexture.viewDimension}_${res.storageTexture.format}_${res.storageTexture.access}`; + } + if (res.externalTexture) { + return `external_texture`; + } + return ``; +} + +/** + * Resource array converted to a Record for nicer test parameterization names. + */ +export const kAPIResources = Object.fromEntries( + generateResources().map((x) => [resourceKey(x), x]) +); + +/** + * Generates a shader of the specified stage using the specified resource at binding (0,0). + */ +export function getWGSLShaderForResource(stage, resource) { + let code = `@group(0) @binding(0) ${resource.code};\n`; + + code += `@${stage}`; + if (stage === 'compute') { + code += `@workgroup_size(1)`; + } + + let retTy = ''; + let retVal = ''; + if (stage === 'vertex') { + retTy = ' -> @builtin(position) vec4f'; + retVal = 'return vec4f();'; + } else if (stage === 'fragment') { + retTy = ' -> @location(0) vec4f'; + retVal = 'return vec4f();'; + } + code += ` +fn main() ${retTy} { + _ = ${resource.staticUse ?? 'res'}; + ${retVal} +} +`; + + return code; +} + +/** + * Generates a bind group layout for for the given resource at binding 0. + */ +export function getAPIBindGroupLayoutForResource( +device, +stage, +resource) +{ + const entry = { + binding: 0, + visibility: stage + }; + if (resource.buffer) { + entry.buffer = resource.buffer; + } + if (resource.sampler) { + entry.sampler = resource.sampler; + } + if (resource.texture) { + entry.texture = resource.texture; + } + if (resource.storageTexture) { + entry.storageTexture = resource.storageTexture; + } + if (resource.externalTexture) { + entry.externalTexture = resource.externalTexture; + } + + const entries = [entry]; + return device.createBindGroupLayout({ entries }); +} + +/** + * Returns true if the sample types are compatible. + */ +function doSampleTypesMatch(api, wgsl) { + if (api === 'float' || api === 'unfilterable-float') { + return wgsl === 'float' || wgsl === 'unfilterable-float'; + } + return api === wgsl; +} + +/** + * Returns true if the access modes are compatible. + */ +function doAccessesMatch(api, wgsl) { + if (api === 'read-write') { + return wgsl === 'read-write' || wgsl === 'write-only'; + } + return api === wgsl; +} + +/** + * Returns true if the resources are compatible. + */ +export function doResourcesMatch(api, wgsl) { + if (api.buffer) { + if (!wgsl.buffer) { + return false; + } + return api.buffer.type === wgsl.buffer.type; + } + if (api.sampler) { + if (!wgsl.sampler) { + return false; + } + return ( + api.sampler.type === wgsl.sampler.type || + api.sampler.type !== 'comparison' && wgsl.sampler.type !== 'comparison'); + + } + if (api.texture) { + if (!wgsl.texture) { + return false; + } + const aType = api.texture.sampleType; + const wType = wgsl.texture.sampleType; + return ( + doSampleTypesMatch(aType, wType) && + api.texture.viewDimension === wgsl.texture.viewDimension && + api.texture.multisampled === wgsl.texture.multisampled); + + } + if (api.storageTexture) { + if (!wgsl.storageTexture) { + return false; + } + const aAccess = api.storageTexture.access; + const wAccess = wgsl.storageTexture.access; + return ( + doAccessesMatch(aAccess, wAccess) && + api.storageTexture.format === wgsl.storageTexture.format && + api.storageTexture.viewDimension === wgsl.storageTexture.viewDimension); + + } + if (api.externalTexture) { + return wgsl.externalTexture !== undefined; + } + + return false; +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/validation_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/validation_test.js index 9ddb6d9fad..f602556d0a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/validation_test.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/validation_test.js @@ -152,11 +152,11 @@ export class ValidationTest extends GPUTest { } /** Return an arbitrarily-configured GPUTexture with the `STORAGE_BINDING` usage. */ - getStorageTexture() { + getStorageTexture(format) { return this.trackForCleanup( this.device.createTexture({ size: { width: 16, height: 16, depthOrArrayLayers: 1 }, - format: 'rgba8unorm', + format, usage: GPUTextureUsage.STORAGE_BINDING }) ); @@ -220,8 +220,10 @@ export class ValidationTest extends GPUTest { return this.getSampledTexture(1).createView(); case 'sampledTexMS': return this.getSampledTexture(4).createView(); - case 'storageTex': - return this.getStorageTexture().createView(); + case 'readonlyStorageTex': + case 'writeonlyStorageTex': + case 'readwriteStorageTex': + return this.getStorageTexture('r32float').createView(); } } @@ -255,10 +257,10 @@ export class ValidationTest extends GPUTest { } /** Return an arbitrarily-configured GPUTexture with the `STORAGE` usage from mismatched device. */ - getDeviceMismatchedStorageTexture() { + getDeviceMismatchedStorageTexture(format) { return this.getDeviceMismatchedTexture({ size: { width: 4, height: 4, depthOrArrayLayers: 1 }, - format: 'rgba8unorm', + format, usage: GPUTextureUsage.STORAGE_BINDING }); } @@ -289,8 +291,10 @@ export class ValidationTest extends GPUTest { return this.getDeviceMismatchedSampledTexture(1).createView(); case 'sampledTexMS': return this.getDeviceMismatchedSampledTexture(4).createView(); - case 'storageTex': - return this.getDeviceMismatchedStorageTexture().createView(); + case 'readonlyStorageTex': + case 'writeonlyStorageTex': + case 'readwriteStorageTex': + return this.getDeviceMismatchedStorageTexture('r32float').createView(); } } @@ -317,7 +321,8 @@ export class ValidationTest extends GPUTest { /** Return a GPURenderPipeline with default options and no-op vertex and fragment shaders. */ createNoOpRenderPipeline( - layout = 'auto') + layout = 'auto', + colorFormat = 'rgba8unorm') { return this.device.createRenderPipeline({ layout, @@ -332,7 +337,7 @@ export class ValidationTest extends GPUTest { code: this.getNoOpShaderCode('FRAGMENT') }), entryPoint: 'main', - targets: [{ format: 'rgba8unorm', writeMask: 0 }] + targets: [{ format: colorFormat, writeMask: 0 }] }, primitive: { topology: 'triangle-list' } }); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js index dbcb833947..eb330bb567 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js @@ -323,6 +323,8 @@ export const kVertexFormats = keysOf(kVertexFormatInfo); + + /** * Classes of `PerPipelineLayout` binding limits. Two bindings with the same class * count toward the same `PerPipelineLayout` limit(s) in the spec (if any). @@ -340,6 +342,8 @@ export const kVertexFormats = keysOf(kVertexFormatInfo); + + /** * Types of resource binding which have distinct binding rules, by spec * (e.g. filtering vs non-filtering sampler, multisample vs non-multisample texture). @@ -353,7 +357,9 @@ export const kBindableResources = [ 'compareSamp', 'sampledTex', 'sampledTexMS', -'storageTex', +'readonlyStorageTex', +'writeonlyStorageTex', +'readwriteStorageTex', 'errorBuf', 'errorSamp', 'errorTex']; @@ -380,7 +386,9 @@ export const kPerStageBindingLimits = 'storageBuf': { class: 'storageBuf', maxLimit: 'maxStorageBuffersPerShaderStage' }, 'sampler': { class: 'sampler', maxLimit: 'maxSamplersPerShaderStage' }, 'sampledTex': { class: 'sampledTex', maxLimit: 'maxSampledTexturesPerShaderStage' }, - 'storageTex': { class: 'storageTex', maxLimit: 'maxStorageTexturesPerShaderStage' } + 'readonlyStorageTex': { class: 'readonlyStorageTex', maxLimit: 'maxStorageTexturesPerShaderStage' }, + 'writeonlyStorageTex': { class: 'writeonlyStorageTex', maxLimit: 'maxStorageTexturesPerShaderStage' }, + 'readwriteStorageTex': { class: 'readwriteStorageTex', maxLimit: 'maxStorageTexturesPerShaderStage' } }; /** @@ -402,7 +410,9 @@ export const kPerPipelineBindingLimits = 'storageBuf': { class: 'storageBuf', maxDynamicLimit: 'maxDynamicStorageBuffersPerPipelineLayout' }, 'sampler': { class: 'sampler', maxDynamicLimit: '' }, 'sampledTex': { class: 'sampledTex', maxDynamicLimit: '' }, - 'storageTex': { class: 'storageTex', maxDynamicLimit: '' } + 'readonlyStorageTex': { class: 'readonlyStorageTex', maxDynamicLimit: '' }, + 'writeonlyStorageTex': { class: 'writeonlyStorageTex', maxDynamicLimit: '' }, + 'readwriteStorageTex': { class: 'readwriteStorageTex', maxDynamicLimit: '' } }; @@ -423,7 +433,9 @@ const kBindingKind = compareSamp: { resource: 'compareSamp', perStageLimitClass: kPerStageBindingLimits.sampler, perPipelineLimitClass: kPerPipelineBindingLimits.sampler }, sampledTex: { resource: 'sampledTex', perStageLimitClass: kPerStageBindingLimits.sampledTex, perPipelineLimitClass: kPerPipelineBindingLimits.sampledTex }, sampledTexMS: { resource: 'sampledTexMS', perStageLimitClass: kPerStageBindingLimits.sampledTex, perPipelineLimitClass: kPerPipelineBindingLimits.sampledTex }, - storageTex: { resource: 'storageTex', perStageLimitClass: kPerStageBindingLimits.storageTex, perPipelineLimitClass: kPerPipelineBindingLimits.storageTex } + readonlyStorageTex: { resource: 'readonlyStorageTex', perStageLimitClass: kPerStageBindingLimits.readonlyStorageTex, perPipelineLimitClass: kPerPipelineBindingLimits.readonlyStorageTex }, + writeonlyStorageTex: { resource: 'writeonlyStorageTex', perStageLimitClass: kPerStageBindingLimits.writeonlyStorageTex, perPipelineLimitClass: kPerPipelineBindingLimits.writeonlyStorageTex }, + readwriteStorageTex: { resource: 'readwriteStorageTex', perStageLimitClass: kPerStageBindingLimits.readwriteStorageTex, perPipelineLimitClass: kPerPipelineBindingLimits.readwriteStorageTex } }; // Binding type info @@ -483,14 +495,30 @@ assertTypeTrue(); /** Binding type info (including class limits) for the specified GPUStorageTextureBindingLayout. */ export function storageTextureBindingTypeInfo(d) { - return { - usage: GPUConst.TextureUsage.STORAGE_BINDING, - ...kBindingKind.storageTex, - ...kValidStagesStorageWrite - }; + switch (d.access) { + case undefined: + case 'write-only': + return { + usage: GPUConst.TextureUsage.STORAGE_BINDING, + ...kBindingKind.writeonlyStorageTex, + ...kValidStagesStorageWrite + }; + case 'read-only': + return { + usage: GPUConst.TextureUsage.STORAGE_BINDING, + ...kBindingKind.readonlyStorageTex, + ...kValidStagesAll + }; + case 'read-write': + return { + usage: GPUConst.TextureUsage.STORAGE_BINDING, + ...kBindingKind.readwriteStorageTex, + ...kValidStagesStorageWrite + }; + } } /** List of all GPUStorageTextureAccess values. */ -export const kStorageTextureAccessValues = ['write-only']; +export const kStorageTextureAccessValues = ['read-only', 'read-write', 'write-only']; assertTypeTrue(); /** GPUBindGroupLayoutEntry, but only the "union" fields, not the common fields. */ @@ -539,8 +567,10 @@ export function samplerBindingEntries(includeUndefined) { */ export function textureBindingEntries(includeUndefined) { return [ - ...(includeUndefined ? [{ texture: { multisampled: undefined } }] : []), - { texture: { multisampled: false } }, + ...(includeUndefined ? + [{ texture: { multisampled: undefined, sampleType: 'unfilterable-float' } }] : + []), + { texture: { multisampled: false, sampleType: 'unfilterable-float' } }, { texture: { multisampled: true, sampleType: 'unfilterable-float' } }]; } @@ -549,19 +579,17 @@ export function textureBindingEntries(includeUndefined) { * * Note: Generates different `access` options, but not `format` or `viewDimension` options. */ -export function storageTextureBindingEntries(format) { - return [{ storageTexture: { access: 'write-only', format } }]; -} -/** Generate a list of possible texture-or-storageTexture-typed BGLEntry values. */ -export function sampledAndStorageBindingEntries( -includeUndefined, -storageTextureFormat = 'rgba8unorm') -{ +export function storageTextureBindingEntries() { return [ - ...textureBindingEntries(includeUndefined), - ...storageTextureBindingEntries(storageTextureFormat)]; + { storageTexture: { access: 'write-only', format: 'r32float' } }, + { storageTexture: { access: 'read-only', format: 'r32float' } }, + { storageTexture: { access: 'read-write', format: 'r32float' } }]; } +/** Generate a list of possible texture-or-storageTexture-typed BGLEntry values. */ +export function sampledAndStorageBindingEntries(includeUndefined) { + return [...textureBindingEntries(includeUndefined), ...storageTextureBindingEntries()]; +} /** * Generate a list of possible BGLEntry values of every type, but not variants with different: * - buffer.hasDynamicOffset @@ -569,14 +597,11 @@ storageTextureFormat = 'rgba8unorm') * - texture.viewDimension * - storageTexture.viewDimension */ -export function allBindingEntries( -includeUndefined, -storageTextureFormat = 'rgba8unorm') -{ +export function allBindingEntries(includeUndefined) { return [ ...bufferBindingEntries(includeUndefined), ...samplerBindingEntries(includeUndefined), - ...sampledAndStorageBindingEntries(includeUndefined, storageTextureFormat)]; + ...sampledAndStorageBindingEntries(includeUndefined)]; } @@ -689,7 +714,7 @@ const [kLimitInfoKeys, kLimitInfoDefaults, kLimitInfoData] = 'maxVertexAttributes': [, 16, 16], 'maxVertexBufferArrayStride': [, 2048, 2048], 'maxInterStageShaderComponents': [, 60, 60], - 'maxInterStageShaderVariables': [, 16, 16], + 'maxInterStageShaderVariables': [, 16, 15], 'maxColorAttachments': [, 8, 4], 'maxColorAttachmentBytesPerSample': [, 32, 32], @@ -789,4 +814,11 @@ export const kFeatureNameInfo = 'float32-filterable': {} }; /** List of all GPUFeatureName values. */ -export const kFeatureNames = keysOf(kFeatureNameInfo); \ No newline at end of file +export const kFeatureNames = keysOf(kFeatureNameInfo); + +/** List of all known WGSL language features */ +export const kKnownWGSLLanguageFeatures = [ +'readonly_and_readwrite_storage_textures', +'packed_4x8_integer_dot_product', +'unrestricted_pointer_parameters', +'pointer_composite_access']; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/createBindGroup.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/createBindGroup.spec.js new file mode 100644 index 0000000000..63cc277088 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/createBindGroup.spec.js @@ -0,0 +1,178 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Tests that, in compat mode, the dimension of a view is compatible with a texture's textureBindingViewDimension. +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { kTextureDimensions, kTextureViewDimensions } from '../../../capability_info.js'; +import { + effectiveViewDimensionForTexture, + getTextureDimensionFromView } from +'../../../util/texture/base.js'; +import { CompatibilityTest } from '../../compatibility_test.js'; + +export const g = makeTestGroup(CompatibilityTest); + +function isTextureBindingViewDimensionCompatibleWithDimension( +dimension = '2d', +textureBindingViewDimension = '2d') +{ + return getTextureDimensionFromView(textureBindingViewDimension) === dimension; +} + +function isValidViewDimensionForDimension( +dimension, +depthOrArrayLayers, +viewDimension) +{ + if (viewDimension === undefined) { + return true; + } + + switch (dimension) { + case '1d': + return viewDimension === '1d'; + case '2d': + case undefined: + switch (viewDimension) { + case undefined: + case '2d': + case '2d-array': + return true; + case 'cube': + return depthOrArrayLayers === 6; + case 'cube-array': + return depthOrArrayLayers % 6 === 0; + default: + return false; + } + break; + case '3d': + return viewDimension === '3d'; + } +} + +function isValidDimensionForDepthOrArrayLayers( +dimension, +depthOrArrayLayers) +{ + switch (dimension) { + case '1d': + return depthOrArrayLayers === 1; + default: + return true; + } +} + +function isValidViewDimensionForDepthOrArrayLayers( +viewDimension, +depthOrArrayLayers) +{ + switch (viewDimension) { + case '2d': + return depthOrArrayLayers === 1; + case 'cube': + return depthOrArrayLayers === 6; + case 'cube-array': + return depthOrArrayLayers % 6 === 0; + default: + return true; + } + return viewDimension === 'cube'; +} + +function getEffectiveTextureBindingViewDimension( +dimension, +depthOrArrayLayers, +textureBindingViewDimension) +{ + if (textureBindingViewDimension) { + return textureBindingViewDimension; + } + + switch (dimension) { + case '1d': + return '1d'; + case '2d': + case undefined: + return depthOrArrayLayers > 1 ? '2d-array' : '2d'; + break; + case '3d': + return '3d'; + } +} + +g.test('viewDimension_matches_textureBindingViewDimension'). +desc( + ` + Tests that, in compat mode, the dimension of a view is compatible with a texture's textureBindingViewDimension + when used as a TEXTURE_BINDING. + ` +). +params((u) => +u // +.combine('dimension', [...kTextureDimensions, undefined]). +combine('textureBindingViewDimension', [...kTextureViewDimensions, undefined]). +combine('viewDimension', [...kTextureViewDimensions, undefined]). +combine('depthOrArrayLayers', [1, 2, 6]). +filter( + ({ dimension, textureBindingViewDimension, depthOrArrayLayers, viewDimension }) => + textureBindingViewDimension !== 'cube-array' && + viewDimension !== 'cube-array' && + isTextureBindingViewDimensionCompatibleWithDimension( + dimension, + textureBindingViewDimension + ) && + isValidViewDimensionForDimension(dimension, depthOrArrayLayers, viewDimension) && + isValidViewDimensionForDepthOrArrayLayers( + textureBindingViewDimension, + depthOrArrayLayers + ) && + isValidDimensionForDepthOrArrayLayers(dimension, depthOrArrayLayers) +) +). +fn((t) => { + const { dimension, textureBindingViewDimension, viewDimension, depthOrArrayLayers } = t.params; + + const texture = t.device.createTexture({ + size: [1, 1, depthOrArrayLayers], + format: 'rgba8unorm', + usage: GPUTextureUsage.TEXTURE_BINDING, + ...(dimension && { dimension }), + ...(textureBindingViewDimension && { textureBindingViewDimension }) + }); // MAINTENANCE_TODO: remove cast once textureBindingViewDimension is added to IDL + t.trackForCleanup(texture); + + const effectiveTextureBindingViewDimension = getEffectiveTextureBindingViewDimension( + dimension, + texture.depthOrArrayLayers, + textureBindingViewDimension + ); + + const effectiveViewDimension = getEffectiveTextureBindingViewDimension( + dimension, + texture.depthOrArrayLayers, + viewDimension + ); + + const layout = t.device.createBindGroupLayout({ + entries: [ + { + binding: 0, + visibility: GPUShaderStage.COMPUTE, + texture: { + viewDimension: effectiveViewDimensionForTexture(texture, viewDimension) + } + }] + + }); + + const resource = texture.createView({ dimension: viewDimension }); + const shouldError = effectiveTextureBindingViewDimension !== effectiveViewDimension; + + t.expectValidationError(() => { + t.device.createBindGroup({ + layout, + entries: [{ binding: 0, resource }] + }); + }, shouldError); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/createBindGroupLayout.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/createBindGroupLayout.spec.js new file mode 100644 index 0000000000..b6d9057cd0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/createBindGroupLayout.spec.js @@ -0,0 +1,34 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Tests that, in compat mode, you can not create a bind group layout with unsupported storage texture formats. +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { kCompatModeUnsupportedStorageTextureFormats } from '../../../format_info.js'; +import { CompatibilityTest } from '../../compatibility_test.js'; + +export const g = makeTestGroup(CompatibilityTest); + +g.test('unsupportedStorageTextureFormats'). +desc( + ` + Tests that, in compat mode, you can not create a bind group layout with unsupported storage texture formats. + ` +). +params((u) => u.combine('format', kCompatModeUnsupportedStorageTextureFormats)). +fn((t) => { + const { format } = t.params; + + t.expectValidationError(() => { + t.device.createBindGroupLayout({ + entries: [ + { + binding: 0, + visibility: GPUShaderStage.COMPUTE, + storageTexture: { + format + } + }] + + }); + }, true); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/encoding/cmds/copyTextureToBuffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/encoding/cmds/copyTextureToBuffer.spec.js index 30db0b1a40..dd9bb594ed 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/encoding/cmds/copyTextureToBuffer.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/encoding/cmds/copyTextureToBuffer.spec.js @@ -19,16 +19,17 @@ beforeAllSubcases((t) => { fn((t) => { const { format } = t.params; - const { blockWidth, blockHeight, bytesPerBlock } = kTextureFormatInfo[format]; + const info = kTextureFormatInfo[format]; + const textureSize = [info.blockWidth, info.blockHeight, 1]; const texture = t.device.createTexture({ - size: [blockWidth, blockHeight, 1], + size: textureSize, format, usage: GPUTextureUsage.COPY_SRC }); t.trackForCleanup(texture); - const bytesPerRow = align(bytesPerBlock, 256); + const bytesPerRow = align(info.color.bytes, 256); const buffer = t.device.createBuffer({ size: bytesPerRow, @@ -37,7 +38,7 @@ fn((t) => { t.trackForCleanup(buffer); const encoder = t.device.createCommandEncoder(); - encoder.copyTextureToBuffer({ texture }, { buffer, bytesPerRow }, [blockWidth, blockHeight, 1]); + encoder.copyTextureToBuffer({ texture }, { buffer, bytesPerRow }, textureSize); t.expectGPUError('validation', () => { encoder.finish(); }); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/encoding/cmds/copyTextureToTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/encoding/cmds/copyTextureToTexture.spec.js new file mode 100644 index 0000000000..07c16b940f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/encoding/cmds/copyTextureToTexture.spec.js @@ -0,0 +1,94 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Tests limitations of copyTextureToTextures in compat mode. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { + kAllTextureFormats, + kCompressedTextureFormats, + kTextureFormatInfo } from +'../../../../../format_info.js'; +import { CompatibilityTest } from '../../../../compatibility_test.js'; + +export const g = makeTestGroup(CompatibilityTest); + +g.test('compressed'). +desc(`Tests that you can not call copyTextureToTexture with compressed textures in compat mode.`). +params((u) => u.combine('format', kCompressedTextureFormats)). +beforeAllSubcases((t) => { + const { format } = t.params; + t.selectDeviceOrSkipTestCase([kTextureFormatInfo[format].feature]); +}). +fn((t) => { + const { format } = t.params; + + const { blockWidth, blockHeight } = kTextureFormatInfo[format]; + + const srcTexture = t.device.createTexture({ + size: [blockWidth, blockHeight, 1], + format, + usage: GPUTextureUsage.COPY_SRC + }); + t.trackForCleanup(srcTexture); + + const dstTexture = t.device.createTexture({ + size: [blockWidth, blockHeight, 1], + format, + usage: GPUTextureUsage.COPY_DST + }); + t.trackForCleanup(dstTexture); + + const encoder = t.device.createCommandEncoder(); + encoder.copyTextureToTexture({ texture: srcTexture }, { texture: dstTexture }, [ + blockWidth, + blockHeight, + 1] + ); + t.expectGPUError('validation', () => { + encoder.finish(); + }); +}); + +g.test('multisample'). +desc(`Test that you can not call copyTextureToTexture with multisample textures in compat mode.`). +params((u) => +u. +beginSubcases(). +combine('format', kAllTextureFormats). +filter(({ format }) => { + const info = kTextureFormatInfo[format]; + return info.multisample && !info.feature; +}) +). +fn((t) => { + const { format } = t.params; + const { blockWidth, blockHeight } = kTextureFormatInfo[format]; + + t.skipIfTextureFormatNotSupported(format); + + const srcTexture = t.device.createTexture({ + size: [blockWidth, blockHeight, 1], + format, + sampleCount: 4, + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT + }); + t.trackForCleanup(srcTexture); + + const dstTexture = t.device.createTexture({ + size: [blockWidth, blockHeight, 1], + format, + sampleCount: 4, + usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT + }); + t.trackForCleanup(dstTexture); + + const encoder = t.device.createCommandEncoder(); + encoder.copyTextureToTexture({ texture: srcTexture }, { texture: dstTexture }, [ + blockWidth, + blockHeight, + 1] + ); + t.expectGPUError('validation', () => { + encoder.finish(); + }); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/render_pipeline/depth_stencil_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/render_pipeline/depth_stencil_state.spec.js new file mode 100644 index 0000000000..d2d997aaa4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/render_pipeline/depth_stencil_state.spec.js @@ -0,0 +1,53 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Tests that depthBiasClamp must be zero in compat mode. +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { CompatibilityTest } from '../../../compatibility_test.js'; + +export const g = makeTestGroup(CompatibilityTest); + +g.test('depthBiasClamp'). +desc('Tests that depthBiasClamp must be zero in compat mode.'). +params((u) => +u // +.combine('depthBiasClamp', [undefined, 0, 0.1, 1]). +combine('async', [false, true]) +). +fn((t) => { + const { depthBiasClamp, async } = t.params; + + const module = t.device.createShaderModule({ + code: ` + @vertex fn vs() -> @builtin(position) vec4f { + return vec4f(0); + } + + @fragment fn fs() -> @location(0) vec4f { + return vec4f(0); + } + ` + }); + + const pipelineDescriptor = { + layout: 'auto', + vertex: { + module, + entryPoint: 'vs' + }, + fragment: { + module, + entryPoint: 'fs', + targets: [{ format: 'rgba8unorm' }] + }, + depthStencil: { + format: 'depth24plus', + depthWriteEnabled: true, + depthCompare: 'always', + ...(depthBiasClamp !== undefined && { depthBiasClamp }) + } + }; + + const success = !depthBiasClamp; + t.doCreateRenderPipelineTest(async, success, pipelineDescriptor); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/render_pipeline/shader_module.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/render_pipeline/shader_module.spec.js index 5218456a84..a35d0199c8 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/render_pipeline/shader_module.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/render_pipeline/shader_module.spec.js @@ -3,6 +3,7 @@ **/export const description = ` Tests limitations of createRenderPipeline related to shader modules in compat mode. `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { kCompatModeUnsupportedStorageTextureFormats } from '../../../../format_info.js'; import { CompatibilityTest } from '../../../compatibility_test.js'; export const g = makeTestGroup(CompatibilityTest); @@ -71,4 +72,210 @@ fn((t) => { () => t.device.createRenderPipeline(pipelineDescriptor), !isValid ); +}); + +g.test('sample_index'). +desc( + ` +Tests that you can not create a render pipeline with a shader module that uses sample_index in compat mode. + +- Test that a pipeline with a shader that uses sample_index fails. +- Test that a pipeline that references a module that has a shader that uses sample_index + but the pipeline does not reference that shader succeeds. + ` +). +params((u) => +u.combine('entryPoint', ['fsWithoutSampleIndexUsage', 'fsWithSampleIndexUsage']) +). +fn((t) => { + const { entryPoint } = t.params; + + const module = t.device.createShaderModule({ + code: ` + @vertex fn vs() -> @builtin(position) vec4f { + return vec4f(1); + } + @fragment fn fsWithoutSampleIndexUsage() -> @location(0) vec4f { + return vec4f(0); + } + @fragment fn fsWithSampleIndexUsage(@builtin(sample_index) sampleIndex: u32) -> @location(0) vec4f { + _ = sampleIndex; + return vec4f(0); + } + ` + }); + + const pipelineDescriptor = { + layout: 'auto', + vertex: { + module, + entryPoint: 'vs' + }, + fragment: { + module, + entryPoint, + targets: [ + { + format: 'rgba8unorm' + }] + + }, + multisample: { + count: 4 + } + }; + + const isValid = entryPoint === 'fsWithoutSampleIndexUsage'; + t.expectGPUError( + 'validation', + () => t.device.createRenderPipeline(pipelineDescriptor), + !isValid + ); +}); + +g.test('interpolate'). +desc( + ` +Tests that you can not create a render pipeline with a shader module that uses interpolate(linear) nor interpolate(...,sample) in compat mode. + +- Test that a pipeline with a shader that uses interpolate(linear) or interpolate(sample) fails. +- Test that a pipeline that references a module that has a shader that uses interpolate(linear/sample) + but the pipeline does not reference that shader succeeds. + ` +). +params((u) => +u. +combine('interpolate', [ +'', +'@interpolate(linear)', +'@interpolate(linear, sample)', +'@interpolate(perspective, sample)'] +). +combine('entryPoint', [ +'fsWithoutInterpolationUsage', +'fsWithInterpolationUsage1', +'fsWithInterpolationUsage2', +'fsWithInterpolationUsage3'] +) +). +fn((t) => { + const { entryPoint, interpolate } = t.params; + + const module = t.device.createShaderModule({ + code: ` + struct Vertex { + @builtin(position) pos: vec4f, + @location(0) ${interpolate} color : vec4f, + }; + @vertex fn vs() -> Vertex { + var v: Vertex; + v.pos = vec4f(1); + v.color = vec4f(1); + return v; + } + @fragment fn fsWithoutInterpolationUsage() -> @location(0) vec4f { + return vec4f(1); + } + @fragment fn fsWithInterpolationUsage1(v: Vertex) -> @location(0) vec4f { + return vec4f(1); + } + @fragment fn fsWithInterpolationUsage2(v: Vertex) -> @location(0) vec4f { + return v.pos; + } + @fragment fn fsWithInterpolationUsage3(v: Vertex) -> @location(0) vec4f { + return v.color; + } + ` + }); + + const pipelineDescriptor = { + layout: 'auto', + vertex: { + module, + entryPoint: 'vs' + }, + fragment: { + module, + entryPoint, + targets: [ + { + format: 'rgba8unorm' + }] + + } + }; + + const isValid = entryPoint === 'fsWithoutInterpolationUsage' || interpolate === ''; + t.expectGPUError( + 'validation', + () => t.device.createRenderPipeline(pipelineDescriptor), + !isValid + ); +}); + +g.test('unsupportedStorageTextureFormats,computePipeline'). +desc( + ` +Tests that you can not create a compute pipeline with unsupported storage texture formats in compat mode. + ` +). +params((u) => +u // +.combine('format', kCompatModeUnsupportedStorageTextureFormats). +combine('async', [false, true]) +). +fn((t) => { + const { format, async } = t.params; + + const module = t.device.createShaderModule({ + code: ` + @group(0) @binding(0) var s: texture_storage_2d<${format}, read>; + @compute @workgroup_size(1) fn cs() { + _ = textureLoad(s, vec2u(0)); + } + ` + }); + + const pipelineDescriptor = { + layout: 'auto', + compute: { + module, + entryPoint: 'cs' + } + }; + t.doCreateComputePipelineTest(async, false, pipelineDescriptor); +}); + +g.test('unsupportedStorageTextureFormats,renderPipeline'). +desc( + ` +Tests that you can not create a render pipeline with unsupported storage texture formats in compat mode. + ` +). +params((u) => +u // +.combine('format', kCompatModeUnsupportedStorageTextureFormats). +combine('async', [false, true]) +). +fn((t) => { + const { format, async } = t.params; + + const module = t.device.createShaderModule({ + code: ` + @group(0) @binding(0) var s: texture_storage_2d<${format}, read>; + @vertex fn vs() -> @builtin(position) vec4f { + _ = textureLoad(s, vec2u(0)); + return vec4f(0); + } + ` + }); + + const pipelineDescriptor = { + layout: 'auto', + vertex: { + module, + entryPoint: 'vs' + } + }; + t.doCreateRenderPipelineTest(async, false, pipelineDescriptor); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/texture/createTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/texture/createTexture.spec.js index c767301b17..65bc50e072 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/texture/createTexture.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/compat/api/validation/texture/createTexture.spec.js @@ -2,7 +2,12 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` Tests that you can not use bgra8unorm-srgb in compat mode. -`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +Tests that textureBindingViewDimension must compatible with texture dimension +`; +import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { kTextureDimensions, kTextureViewDimensions } from '../../../../capability_info.js'; +import { kColorTextureFormats, kCompatModeUnsupportedStorageTextureFormats, kTextureFormatInfo } from '../../../../format_info.js'; +import { getTextureDimensionFromView } from '../../../../util/texture/base.js'; import { CompatibilityTest } from '../../../compatibility_test.js'; export const g = makeTestGroup(CompatibilityTest); @@ -38,4 +43,130 @@ fn((t) => { }), true ); +}); + +g.test('invalidTextureBindingViewDimension'). +desc( + `Tests that you can not specify a textureBindingViewDimension that is incompatible with the texture's dimension.` +). +params((u) => +u // +.combine('dimension', kTextureDimensions). +combine('textureBindingViewDimension', kTextureViewDimensions) +). +fn((t) => { + const { dimension, textureBindingViewDimension } = t.params; + const depthOrArrayLayers = textureBindingViewDimension === '1d' || textureBindingViewDimension === '2d' ? 1 : 6; + const shouldError = getTextureDimensionFromView(textureBindingViewDimension) !== dimension; + t.expectGPUError( + 'validation', + () => { + const texture = t.device.createTexture({ + size: [1, 1, depthOrArrayLayers], + format: 'rgba8unorm', + usage: GPUTextureUsage.TEXTURE_BINDING, + dimension, + textureBindingViewDimension + }); // MAINTENANCE_TODO: remove cast once textureBindingViewDimension is added to IDL + t.trackForCleanup(texture); + }, + shouldError + ); +}); + +g.test('depthOrArrayLayers_incompatible_with_textureBindingViewDimension'). +desc( + `Tests + * if textureBindingViewDimension is '2d' then depthOrArrayLayers must be 1 + * if textureBindingViewDimension is 'cube' then depthOrArrayLayers must be 6 + ` +). +params((u) => +u // +.combine('textureBindingViewDimension', ['2d', 'cube']). +combine('depthOrArrayLayers', [1, 3, 6, 12]) +). +fn((t) => { + const { textureBindingViewDimension, depthOrArrayLayers } = t.params; + const shouldError = + textureBindingViewDimension === '2d' && depthOrArrayLayers !== 1 || + textureBindingViewDimension === 'cube' && depthOrArrayLayers !== 6; + t.expectGPUError( + 'validation', + () => { + const texture = t.device.createTexture({ + size: [1, 1, depthOrArrayLayers], + format: 'rgba8unorm', + usage: GPUTextureUsage.TEXTURE_BINDING, + textureBindingViewDimension + }); // MAINTENANCE_TODO: remove cast once textureBindingViewDimension is added to IDL + t.trackForCleanup(texture); + }, + shouldError + ); +}); + +g.test('format_reinterpretation'). +desc( + ` + Tests that you can not request different view formats when creating a texture. + For example, rgba8unorm can not be viewed as rgba8unorm-srgb + ` +). +params((u) => +u // +.combine('format', kColorTextureFormats). +filter( + ({ format }) => + !!kTextureFormatInfo[format].baseFormat && + kTextureFormatInfo[format].baseFormat !== format +) +). +beforeAllSubcases((t) => { + const info = kTextureFormatInfo[t.params.format]; + t.skipIfTextureFormatNotSupported(t.params.format); + t.selectDeviceOrSkipTestCase(info.feature); +}). +fn((t) => { + const { format } = t.params; + const info = kTextureFormatInfo[format]; + + const formatPairs = [ + { format, viewFormats: [info.baseFormat] }, + { format: info.baseFormat, viewFormats: [format] }, + { format, viewFormats: [format, info.baseFormat] }, + { format: info.baseFormat, viewFormats: [format, info.baseFormat] }]; + + for (const { format, viewFormats } of formatPairs) { + t.expectGPUError( + 'validation', + () => { + const texture = t.device.createTexture({ + size: [info.blockWidth, info.blockHeight], + format, + viewFormats, + usage: GPUTextureUsage.TEXTURE_BINDING + }); + t.trackForCleanup(texture); + }, + true + ); + } +}); + +g.test('unsupportedStorageTextureFormats'). +desc(`Tests that you can not create unsupported storage texture formats in compat mode.`). +params((u) => u.combine('format', kCompatModeUnsupportedStorageTextureFormats)). +fn((t) => { + const { format } = t.params; + t.expectGPUError( + 'validation', + () => + t.device.createTexture({ + size: [1, 1, 1], + format, + usage: GPUTextureUsage.STORAGE_BINDING + }), + true + ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/constants.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/constants.js index b8dbfcd9a4..1a01173428 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/constants.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/constants.js @@ -59,4 +59,7 @@ export const GPUConst = { }; export const kMaxUnsignedLongValue = 4294967295; -export const kMaxUnsignedLongLongValue = Number.MAX_SAFE_INTEGER; \ No newline at end of file +export const kMaxUnsignedLongLongValue = Number.MAX_SAFE_INTEGER; + +export const kInterpolationSampling = ['center', 'centroid', 'sample']; +export const kInterpolationType = ['perspective', 'linear', 'flat']; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/format_info.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/format_info.js index 5ba96b741b..d59a73dcdd 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/format_info.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/format_info.js @@ -1,6 +1,6 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { keysOf } from '../common/util/data_tables.js';import { assert } from '../common/util/util.js'; +**/import { keysOf } from '../common/util/data_tables.js';import { assert, unreachable } from '../common/util/util.js'; import { align } from './util/math.js'; @@ -13,25 +13,26 @@ import { align } from './util/math.js'; * `formatTableWithDefaults`. This ensures keys are never missing, always explicitly `undefined`. * * All top-level keys must be defined here, or they won't be exposed at all. + * Documentation is also written here; this makes it propagate through to the end types. */ const kFormatUniversalDefaults = { + /** Texel block width. */ blockWidth: undefined, + /** Texel block height. */ blockHeight: undefined, color: undefined, depth: undefined, stencil: undefined, colorRender: undefined, + /** Whether the format can be used in a multisample texture. */ multisample: undefined, + /** Optional feature required to use this format, or `undefined` if none. */ feature: undefined, + /** The base format for srgb formats. Specified on both srgb and equivalent non-srgb formats. */ baseFormat: undefined, - sampleType: undefined, - copySrc: undefined, - copyDst: undefined, - bytesPerBlock: undefined, - renderable: false, - renderTargetPixelByteCost: undefined, - renderTargetComponentAlignment: undefined + /** @deprecated Use `.color.bytes`, `.depth.bytes`, or `.stencil.bytes`. */ + bytesPerBlock: undefined // IMPORTANT: // Add new top-level keys both here and in TextureFormatInfo_TypeCheck. @@ -67,382 +68,506 @@ function formatTableWithDefaults({ /** "plain color formats", plus rgb9e5ufloat. */ const kRegularTextureFormatInfo = formatTableWithDefaults({ - defaults: { blockWidth: 1, blockHeight: 1, copySrc: true, copyDst: true }, + defaults: { blockWidth: 1, blockHeight: 1 }, table: { // plain, 8 bits per component r8unorm: { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 1 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 1 + }, colorRender: { blend: true, resolve: true, byteCost: 1, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, r8snorm: { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 1 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 1 + }, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, r8uint: { - color: { type: 'uint', copySrc: true, copyDst: true, storage: false, bytes: 1 }, + color: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 1 + }, colorRender: { blend: false, resolve: false, byteCost: 1, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, r8sint: { - color: { type: 'sint', copySrc: true, copyDst: true, storage: false, bytes: 1 }, + color: { + type: 'sint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 1 + }, colorRender: { blend: false, resolve: false, byteCost: 1, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg8unorm: { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 2 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 2 + }, colorRender: { blend: true, resolve: true, byteCost: 2, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg8snorm: { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 2 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 2 + }, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg8uint: { - color: { type: 'uint', copySrc: true, copyDst: true, storage: false, bytes: 2 }, + color: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 2 + }, colorRender: { blend: false, resolve: false, byteCost: 2, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg8sint: { - color: { type: 'sint', copySrc: true, copyDst: true, storage: false, bytes: 2 }, + color: { + type: 'sint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 2 + }, colorRender: { blend: false, resolve: false, byteCost: 2, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgba8unorm: { - color: { type: 'float', copySrc: true, copyDst: true, storage: true, bytes: 4 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: true, resolve: true, byteCost: 8, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, baseFormat: 'rgba8unorm', - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, 'rgba8unorm-srgb': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 4 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: true, resolve: true, byteCost: 8, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, baseFormat: 'rgba8unorm', - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgba8snorm: { - color: { type: 'float', copySrc: true, copyDst: true, storage: true, bytes: 4 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 4 + }, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgba8uint: { - color: { type: 'uint', copySrc: true, copyDst: true, storage: true, bytes: 4 }, + color: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: false, resolve: false, byteCost: 4, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgba8sint: { - color: { type: 'sint', copySrc: true, copyDst: true, storage: true, bytes: 4 }, + color: { + type: 'sint', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: false, resolve: false, byteCost: 4, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, bgra8unorm: { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 4 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: true, resolve: true, byteCost: 8, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, baseFormat: 'bgra8unorm', - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, 'bgra8unorm-srgb': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 4 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: true, resolve: true, byteCost: 8, alignment: 1 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, baseFormat: 'bgra8unorm', - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, // plain, 16 bits per component r16uint: { - color: { type: 'uint', copySrc: true, copyDst: true, storage: false, bytes: 2 }, + color: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 2 + }, colorRender: { blend: false, resolve: false, byteCost: 2, alignment: 2 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, r16sint: { - color: { type: 'sint', copySrc: true, copyDst: true, storage: false, bytes: 2 }, + color: { + type: 'sint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 2 + }, colorRender: { blend: false, resolve: false, byteCost: 2, alignment: 2 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, r16float: { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 2 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 2 + }, colorRender: { blend: true, resolve: true, byteCost: 2, alignment: 2 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg16uint: { - color: { type: 'uint', copySrc: true, copyDst: true, storage: false, bytes: 4 }, + color: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: false, resolve: false, byteCost: 4, alignment: 2 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg16sint: { - color: { type: 'sint', copySrc: true, copyDst: true, storage: false, bytes: 4 }, + color: { + type: 'sint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: false, resolve: false, byteCost: 4, alignment: 2 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg16float: { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 4 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: true, resolve: true, byteCost: 4, alignment: 2 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgba16uint: { - color: { type: 'uint', copySrc: true, copyDst: true, storage: true, bytes: 8 }, + color: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 8 + }, colorRender: { blend: false, resolve: false, byteCost: 8, alignment: 2 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgba16sint: { - color: { type: 'sint', copySrc: true, copyDst: true, storage: true, bytes: 8 }, + color: { + type: 'sint', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 8 + }, colorRender: { blend: false, resolve: false, byteCost: 8, alignment: 2 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgba16float: { - color: { type: 'float', copySrc: true, copyDst: true, storage: true, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 8 + }, colorRender: { blend: true, resolve: true, byteCost: 8, alignment: 2 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, // plain, 32 bits per component r32uint: { - color: { type: 'uint', copySrc: true, copyDst: true, storage: true, bytes: 4 }, + color: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: true, + bytes: 4 + }, colorRender: { blend: false, resolve: false, byteCost: 4, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, r32sint: { - color: { type: 'sint', copySrc: true, copyDst: true, storage: true, bytes: 4 }, + color: { + type: 'sint', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: true, + bytes: 4 + }, colorRender: { blend: false, resolve: false, byteCost: 4, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, r32float: { - color: { type: 'unfilterable-float', copySrc: true, copyDst: true, storage: true, bytes: 4 }, + color: { + type: 'unfilterable-float', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: true, + bytes: 4 + }, colorRender: { blend: false, resolve: false, byteCost: 4, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg32uint: { - color: { type: 'uint', copySrc: true, copyDst: true, storage: true, bytes: 8 }, + color: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 8 + }, colorRender: { blend: false, resolve: false, byteCost: 8, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg32sint: { - color: { type: 'sint', copySrc: true, copyDst: true, storage: true, bytes: 8 }, + color: { + type: 'sint', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 8 + }, colorRender: { blend: false, resolve: false, byteCost: 8, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg32float: { - color: { type: 'unfilterable-float', copySrc: true, copyDst: true, storage: true, bytes: 8 }, + color: { + type: 'unfilterable-float', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 8 + }, colorRender: { blend: false, resolve: false, byteCost: 8, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgba32uint: { - color: { type: 'uint', copySrc: true, copyDst: true, storage: true, bytes: 16 }, + color: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 16 + }, colorRender: { blend: false, resolve: false, byteCost: 16, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgba32sint: { - color: { type: 'sint', copySrc: true, copyDst: true, storage: true, bytes: 16 }, + color: { + type: 'sint', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 16 + }, colorRender: { blend: false, resolve: false, byteCost: 16, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgba32float: { - color: { type: 'unfilterable-float', copySrc: true, copyDst: true, storage: true, bytes: 16 }, + color: { + type: 'unfilterable-float', + copySrc: true, + copyDst: true, + storage: true, + readWriteStorage: false, + bytes: 16 + }, colorRender: { blend: false, resolve: false, byteCost: 16, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, // plain, mixed component width, 32 bits per texel rgb10a2uint: { - color: { type: 'uint', copySrc: true, copyDst: true, storage: false, bytes: 4 }, + color: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: false, resolve: false, byteCost: 8, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rgb10a2unorm: { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 4 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 4 + }, colorRender: { blend: true, resolve: true, byteCost: 8, alignment: 4 }, - renderable: true, - get renderTargetComponentAlignment() {return this.colorRender.alignment;}, - get renderTargetPixelByteCost() {return this.colorRender.byteCost;}, multisample: true, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} }, rg11b10ufloat: { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 4 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 4 + }, multisample: false, - get sampleType() {return this.color.type;}, - get bytesPerBlock() {return this.color.bytes;}, - renderTargetPixelByteCost: 8, - renderTargetComponentAlignment: 4 + get bytesPerBlock() {return this.color.bytes;} }, // packed rgb9e5ufloat: { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 4 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 4 + }, multisample: false, - get sampleType() {return this.color.type;}, get bytesPerBlock() {return this.color.bytes;} } } @@ -452,24 +577,39 @@ const kRegularTextureFormatInfo = formatTableWithDefaults({ // because one aspect can be sized and one can be unsized. This should be cleaned up, but is kept // this way during a migration phase. const kSizedDepthStencilFormatInfo = formatTableWithDefaults({ - defaults: { blockWidth: 1, blockHeight: 1, multisample: true, copySrc: true, renderable: true }, + defaults: { blockWidth: 1, blockHeight: 1, multisample: true }, table: { stencil8: { - stencil: { type: 'uint', copySrc: true, copyDst: true, storage: false, bytes: 1 }, - sampleType: 'uint', - copyDst: true, + stencil: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 1 + }, bytesPerBlock: 1 }, depth16unorm: { - depth: { type: 'depth', copySrc: true, copyDst: true, storage: false, bytes: 2 }, - sampleType: 'depth', - copyDst: true, + depth: { + type: 'depth', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 2 + }, bytesPerBlock: 2 }, depth32float: { - depth: { type: 'depth', copySrc: true, copyDst: false, storage: false, bytes: 4 }, - sampleType: 'depth', - copyDst: false, + depth: { + type: 'depth', + copySrc: true, + copyDst: false, + storage: false, + readWriteStorage: false, + bytes: 4 + }, bytesPerBlock: 4 } } @@ -478,28 +618,51 @@ const kUnsizedDepthStencilFormatInfo = formatTableWithDefaults({ defaults: { blockWidth: 1, blockHeight: 1, multisample: true }, table: { depth24plus: { - depth: { type: 'depth', copySrc: false, copyDst: false, storage: false, bytes: undefined }, - copySrc: false, - copyDst: false, - sampleType: 'depth', - renderable: true + depth: { + type: 'depth', + copySrc: false, + copyDst: false, + storage: false, + readWriteStorage: false, + bytes: undefined + } }, 'depth24plus-stencil8': { - depth: { type: 'depth', copySrc: false, copyDst: false, storage: false, bytes: undefined }, - stencil: { type: 'uint', copySrc: true, copyDst: true, storage: false, bytes: 1 }, - copySrc: false, - copyDst: false, - sampleType: 'depth', - renderable: true + depth: { + type: 'depth', + copySrc: false, + copyDst: false, + storage: false, + readWriteStorage: false, + bytes: undefined + }, + stencil: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 1 + } }, 'depth32float-stencil8': { - depth: { type: 'depth', copySrc: true, copyDst: false, storage: false, bytes: 4 }, - stencil: { type: 'uint', copySrc: true, copyDst: true, storage: false, bytes: 1 }, - feature: 'depth32float-stencil8', - copySrc: false, - copyDst: false, - sampleType: 'depth', - renderable: true + depth: { + type: 'depth', + copySrc: true, + copyDst: false, + storage: false, + readWriteStorage: false, + bytes: 4 + }, + stencil: { + type: 'uint', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 1 + }, + feature: 'depth32float-stencil8' } } }); @@ -509,79 +672,174 @@ const kBCTextureFormatInfo = formatTableWithDefaults({ blockWidth: 4, blockHeight: 4, multisample: false, - feature: 'texture-compression-bc', - sampleType: 'float', - copySrc: true, - copyDst: true + feature: 'texture-compression-bc' }, table: { 'bc1-rgba-unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 8 + }, baseFormat: 'bc1-rgba-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'bc1-rgba-unorm-srgb': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 8 + }, baseFormat: 'bc1-rgba-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'bc2-rgba-unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'bc2-rgba-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'bc2-rgba-unorm-srgb': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'bc2-rgba-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'bc3-rgba-unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'bc3-rgba-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'bc3-rgba-unorm-srgb': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'bc3-rgba-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'bc4-r-unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 8 + }, get bytesPerBlock() {return this.color.bytes;} }, 'bc4-r-snorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 8 + }, get bytesPerBlock() {return this.color.bytes;} }, 'bc5-rg-unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, get bytesPerBlock() {return this.color.bytes;} }, 'bc5-rg-snorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, get bytesPerBlock() {return this.color.bytes;} }, 'bc6h-rgb-ufloat': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, get bytesPerBlock() {return this.color.bytes;} }, 'bc6h-rgb-float': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, get bytesPerBlock() {return this.color.bytes;} }, 'bc7-rgba-unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'bc7-rgba-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'bc7-rgba-unorm-srgb': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'bc7-rgba-unorm', get bytesPerBlock() {return this.color.bytes;} } @@ -593,60 +851,127 @@ const kETC2TextureFormatInfo = formatTableWithDefaults({ blockWidth: 4, blockHeight: 4, multisample: false, - feature: 'texture-compression-etc2', - sampleType: 'float', - copySrc: true, - copyDst: true + feature: 'texture-compression-etc2' }, table: { 'etc2-rgb8unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 8 + }, baseFormat: 'etc2-rgb8unorm', get bytesPerBlock() {return this.color.bytes;} }, 'etc2-rgb8unorm-srgb': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 8 + }, baseFormat: 'etc2-rgb8unorm', get bytesPerBlock() {return this.color.bytes;} }, 'etc2-rgb8a1unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 8 + }, baseFormat: 'etc2-rgb8a1unorm', get bytesPerBlock() {return this.color.bytes;} }, 'etc2-rgb8a1unorm-srgb': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 8 + }, baseFormat: 'etc2-rgb8a1unorm', get bytesPerBlock() {return this.color.bytes;} }, 'etc2-rgba8unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'etc2-rgba8unorm', get bytesPerBlock() {return this.color.bytes;} }, 'etc2-rgba8unorm-srgb': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'etc2-rgba8unorm', get bytesPerBlock() {return this.color.bytes;} }, 'eac-r11unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 8 + }, get bytesPerBlock() {return this.color.bytes;} }, 'eac-r11snorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 8 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 8 + }, get bytesPerBlock() {return this.color.bytes;} }, 'eac-rg11unorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, get bytesPerBlock() {return this.color.bytes;} }, 'eac-rg11snorm': { - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, get bytesPerBlock() {return this.color.bytes;} } } @@ -655,23 +980,34 @@ const kETC2TextureFormatInfo = formatTableWithDefaults({ const kASTCTextureFormatInfo = formatTableWithDefaults({ defaults: { multisample: false, - feature: 'texture-compression-astc', - sampleType: 'float', - copySrc: true, - copyDst: true + feature: 'texture-compression-astc' }, table: { 'astc-4x4-unorm': { blockWidth: 4, blockHeight: 4, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-4x4-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-4x4-unorm-srgb': { blockWidth: 4, blockHeight: 4, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-4x4-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -679,14 +1015,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-5x4-unorm': { blockWidth: 5, blockHeight: 4, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-5x4-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-5x4-unorm-srgb': { blockWidth: 5, blockHeight: 4, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-5x4-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -694,14 +1044,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-5x5-unorm': { blockWidth: 5, blockHeight: 5, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-5x5-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-5x5-unorm-srgb': { blockWidth: 5, blockHeight: 5, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-5x5-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -709,14 +1073,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-6x5-unorm': { blockWidth: 6, blockHeight: 5, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-6x5-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-6x5-unorm-srgb': { blockWidth: 6, blockHeight: 5, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-6x5-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -724,14 +1102,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-6x6-unorm': { blockWidth: 6, blockHeight: 6, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-6x6-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-6x6-unorm-srgb': { blockWidth: 6, blockHeight: 6, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-6x6-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -739,14 +1131,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-8x5-unorm': { blockWidth: 8, blockHeight: 5, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-8x5-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-8x5-unorm-srgb': { blockWidth: 8, blockHeight: 5, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-8x5-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -754,14 +1160,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-8x6-unorm': { blockWidth: 8, blockHeight: 6, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-8x6-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-8x6-unorm-srgb': { blockWidth: 8, blockHeight: 6, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-8x6-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -769,14 +1189,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-8x8-unorm': { blockWidth: 8, blockHeight: 8, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-8x8-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-8x8-unorm-srgb': { blockWidth: 8, blockHeight: 8, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-8x8-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -784,14 +1218,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-10x5-unorm': { blockWidth: 10, blockHeight: 5, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-10x5-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-10x5-unorm-srgb': { blockWidth: 10, blockHeight: 5, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-10x5-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -799,14 +1247,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-10x6-unorm': { blockWidth: 10, blockHeight: 6, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-10x6-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-10x6-unorm-srgb': { blockWidth: 10, blockHeight: 6, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-10x6-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -814,14 +1276,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-10x8-unorm': { blockWidth: 10, blockHeight: 8, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-10x8-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-10x8-unorm-srgb': { blockWidth: 10, blockHeight: 8, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-10x8-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -829,14 +1305,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-10x10-unorm': { blockWidth: 10, blockHeight: 10, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-10x10-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-10x10-unorm-srgb': { blockWidth: 10, blockHeight: 10, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-10x10-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -844,14 +1334,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-12x10-unorm': { blockWidth: 12, blockHeight: 10, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-12x10-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-12x10-unorm-srgb': { blockWidth: 12, blockHeight: 10, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-12x10-unorm', get bytesPerBlock() {return this.color.bytes;} }, @@ -859,14 +1363,28 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({ 'astc-12x12-unorm': { blockWidth: 12, blockHeight: 12, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-12x12-unorm', get bytesPerBlock() {return this.color.bytes;} }, 'astc-12x12-unorm-srgb': { blockWidth: 12, blockHeight: 12, - color: { type: 'float', copySrc: true, copyDst: true, storage: false, bytes: 16 }, + color: { + type: 'float', + copySrc: true, + copyDst: true, + storage: false, + readWriteStorage: false, + bytes: 16 + }, baseFormat: 'astc-12x12-unorm', get bytesPerBlock() {return this.color.bytes;} } @@ -921,13 +1439,6 @@ export const kAllTextureFormats = keysOf(kAllTextureFormatInfo); export const kRenderableColorTextureFormats = kRegularTextureFormats.filter( (v) => kColorTextureFormatInfo[v].colorRender ); -assert( - kRenderableColorTextureFormats.every( - (f) => - kAllTextureFormatInfo[f].renderTargetComponentAlignment !== undefined && - kAllTextureFormatInfo[f].renderTargetPixelByteCost !== undefined - ) -); /** Per-GPUTextureFormat-per-aspect info. */ @@ -940,6 +1451,8 @@ assert( + + /** Per GPUTextureFormat-per-aspect info for color aspects. */ @@ -962,7 +1475,6 @@ assert( * This is not actually the type of values in kTextureFormatInfo; that type is fully const * so that it can be narrowed very precisely at usage sites by the compiler. * This type exists only as a type check on the inferred type of kTextureFormatInfo. - * Documentation is also written here, but not actually visible to the IDE. */ @@ -990,24 +1502,6 @@ assert( - - - - - - - - - - - - - - - - - - @@ -1043,10 +1537,6 @@ const kTextureFormatInfo_TypeCheck = kTextureFormatInfo; -/** List of all GPUTextureFormat values. */ -// MAINTENANCE_TODO: dedup with kAllTextureFormats -export const kTextureFormats = keysOf(kAllTextureFormatInfo); - /** Valid GPUTextureFormats for `copyExternalImageToTexture`, by spec. */ export const kValidTextureFormatsForCopyE2T = [ 'r8unorm', @@ -1169,6 +1659,35 @@ aspect) return resolved; } +/** + * @returns the sample type of the specified aspect of the specified format. + */ +export function sampleTypeForFormatAndAspect( +format, +aspect) +{ + const info = kTextureFormatInfo[format]; + if (info.color) { + assert(aspect === 'all', `color format ${format} used with aspect ${aspect}`); + return info.color.type; + } else if (info.depth && info.stencil) { + if (aspect === 'depth-only') { + return info.depth.type; + } else if (aspect === 'stencil-only') { + return info.stencil.type; + } else { + unreachable(`depth-stencil format ${format} used with aspect ${aspect}`); + } + } else if (info.depth) { + assert(aspect !== 'stencil-only', `depth-only format ${format} used with aspect ${aspect}`); + return info.depth.type; + } else if (info.stencil) { + assert(aspect !== 'depth-only', `stencil-only format ${format} used with aspect ${aspect}`); + return info.stencil.type; + } + unreachable(); +} + /** * Gets all copyable aspects for copies between texture and buffer for specified depth/stencil format and copy type, by spec. */ @@ -1229,8 +1748,12 @@ format) * * This function may need to be generalized to use `baseFormat` from `kTextureFormatInfo`. */ -export function viewCompatible(a, b) { - return a === b || a + '-srgb' === b || b + '-srgb' === a; +export function viewCompatible( +compatibilityMode, +a, +b) +{ + return compatibilityMode ? a === b : a === b || a + '-srgb' === b || b + '-srgb' === a; } export function getFeaturesForFormats( @@ -1250,7 +1773,29 @@ export function isCompressedTextureFormat(format) { return format in kCompressedTextureFormatInfo; } -export const kFeaturesForFormats = getFeaturesForFormats(kTextureFormats); +export const kCompatModeUnsupportedStorageTextureFormats = [ +'rg32float', +'rg32sint', +'rg32uint']; + + +export function isTextureFormatUsableAsStorageFormat( +format, +isCompatibilityMode) +{ + if (isCompatibilityMode) { + if (kCompatModeUnsupportedStorageTextureFormats.indexOf(format) >= 0) { + return false; + } + } + return !!kTextureFormatInfo[format].color?.storage; +} + +export function isRegularTextureFormat(format) { + return format in kRegularTextureFormatInfo; +} + +export const kFeaturesForFormats = getFeaturesForFormats(kAllTextureFormats); /** * Given an array of texture formats return the number of bytes per sample. diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/gpu_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/gpu_test.js index 2b589b9316..0354abdbe7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/gpu_test.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/gpu_test.js @@ -9,6 +9,7 @@ '../common/framework/fixture.js'; import { globalTestConfig } from '../common/framework/test_config.js'; +import { getGPU } from '../common/util/navigator_gpu.js'; import { assert, makeValueTestVariant, @@ -20,15 +21,22 @@ import { unreachable } from '../common/util/util.js'; -import { getDefaultLimits, kQueryTypeInfo } from './capability_info.js'; +import { + getDefaultLimits, + + kQueryTypeInfo } from + +'./capability_info.js'; + import { kTextureFormatInfo, kEncodableTextureFormats, resolvePerAspectFormat, - isCompressedTextureFormat } from + isCompressedTextureFormat, + isTextureFormatUsableAsStorageFormat } from './format_info.js'; import { makeBufferWithContents } from './util/buffer.js'; import { checkElementsEqual, checkElementsBetween } from './util/check_contents.js'; @@ -52,7 +60,7 @@ import { textureContentIsOKByT2B } from './util/texture/texture_ok.js'; import { createTextureFromTexelView, createTextureFromTexelViews } from './util/texture.js'; -import { reifyOrigin3D } from './util/unions.js'; +import { reifyExtent3D, reifyOrigin3D } from './util/unions.js'; const devicePool = new DevicePool(); @@ -245,6 +253,56 @@ export class GPUTestSubcaseBatchState extends SubcaseBatchState { } } } + + skipIfTextureFormatNotUsableAsStorageTexture(...formats) { + for (const format of formats) { + if (format && !isTextureFormatUsableAsStorageFormat(format, this.isCompatibility)) { + this.skip(`Texture with ${format} is not usable as a storage texture`); + } + } + } + + /** + * Skips test if the given interpolation type or sampling is not supported. + */ + skipIfInterpolationTypeOrSamplingNotSupported({ + type, + sampling + + + + }) { + if (this.isCompatibility) { + this.skipIf( + type === 'linear', + 'interpolation type linear is not supported in compatibility mode' + ); + this.skipIf( + sampling === 'sample', + 'interpolation type linear is not supported in compatibility mode' + ); + } + } + + /** Skips this test case if the `langFeature` is *not* supported. */ + skipIfLanguageFeatureNotSupported(langFeature) { + if (!this.hasLanguageFeature(langFeature)) { + this.skip(`WGSL language feature '${langFeature}' is not supported`); + } + } + + /** Skips this test case if the `langFeature` is supported. */ + skipIfLanguageFeatureSupported(langFeature) { + if (this.hasLanguageFeature(langFeature)) { + this.skip(`WGSL language feature '${langFeature}' is supported`); + } + } + + /** returns true iff the `langFeature` is supported */ + hasLanguageFeature(langFeature) { + const lf = getGPU(this.recorder).wgslLanguageFeatures; + return lf !== undefined && lf.has(langFeature); + } } /** @@ -420,6 +478,26 @@ export class GPUTestBase extends Fixture { } } + /** Skips this test case if the `langFeature` is *not* supported. */ + skipIfLanguageFeatureNotSupported(langFeature) { + if (!this.hasLanguageFeature(langFeature)) { + this.skip(`WGSL language feature '${langFeature}' is not supported`); + } + } + + /** Skips this test case if the `langFeature` is supported. */ + skipIfLanguageFeatureSupported(langFeature) { + if (this.hasLanguageFeature(langFeature)) { + this.skip(`WGSL language feature '${langFeature}' is supported`); + } + } + + /** returns true iff the `langFeature` is supported */ + hasLanguageFeature(langFeature) { + const lf = getGPU(this.rec).wgslLanguageFeatures; + return lf !== undefined && lf.has(langFeature); + } + /** * Expect a GPUBuffer's contents to pass the provided check. * @@ -730,7 +808,8 @@ export class GPUTestBase extends Fixture { slice = 0, layout, generateWarningOnly = false, - checkElementsBetweenFn = (act, [a, b]) => checkElementsBetween(act, [(i) => a[i], (i) => b[i]]) + checkElementsBetweenFn = (act, [a, b]) => + checkElementsBetween(act, [(i) => a[i], (i) => b[i]]) @@ -757,24 +836,32 @@ export class GPUTestBase extends Fixture { /** * Emulate a texture to buffer copy by using a compute shader - * to load texture value of a single pixel and write to a storage buffer. - * For sample count == 1, the buffer contains only one value of the sample. - * For sample count > 1, the buffer contains (N = sampleCount) values sorted + * to load texture values of a subregion of a 2d texture and write to a storage buffer. + * For sample count == 1, the buffer contains extent[0] * extent[1] of the sample. + * For sample count > 1, the buffer contains extent[0] * extent[1] * (N = sampleCount) values sorted * in the order of their sample index [0, sampleCount - 1] * * This can be useful when the texture to buffer copy is not available to the texture format * e.g. (depth24plus), or when the texture is multisampled. * - * MAINTENANCE_TODO: extend to read multiple pixels with given origin and size. + * MAINTENANCE_TODO: extend texture dimension to 1d and 3d. * * @returns storage buffer containing the copied value from the texture. */ - copySinglePixelTextureToBufferUsingComputePass( + copy2DTextureToBufferUsingComputePass( type, componentCount, textureView, - sampleCount) + sampleCount = 1, + extent_ = [1, 1, 1], + origin_ = [0, 0, 0]) { + const origin = reifyOrigin3D(origin_); + const extent = reifyExtent3D(extent_); + const width = extent.width; + const height = extent.height; + const kWorkgroupSizeX = 8; + const kWorkgroupSizeY = 8; const textureSrcCode = sampleCount === 1 ? `@group(0) @binding(0) var src: texture_2d<${type}>;` : @@ -787,13 +874,24 @@ export class GPUTestBase extends Fixture { ${textureSrcCode} @group(0) @binding(1) var dst : Buffer; - @compute @workgroup_size(1) fn main() { - var coord = vec2(0, 0); - for (var sampleIndex = 0; sampleIndex < ${sampleCount}; + struct Params { + origin: vec2u, + extent: vec2u, + }; + @group(0) @binding(2) var params : Params; + + @compute @workgroup_size(${kWorkgroupSizeX}, ${kWorkgroupSizeY}, 1) fn main(@builtin(global_invocation_id) id : vec3u) { + let boundary = params.origin + params.extent; + let coord = params.origin + id.xy; + if (any(coord >= boundary)) { + return; + } + let offset = (id.x + id.y * params.extent.x) * ${componentCount} * ${sampleCount}; + for (var sampleIndex = 0u; sampleIndex < ${sampleCount}; sampleIndex = sampleIndex + 1) { - let o = sampleIndex * ${componentCount}; - let v = textureLoad(src, coord, sampleIndex); - for (var component = 0; component < ${componentCount}; component = component + 1) { + let o = offset + sampleIndex * ${componentCount}; + let v = textureLoad(src, coord.xy, sampleIndex); + for (var component = 0u; component < ${componentCount}; component = component + 1) { dst.data[o + component] = v[component]; } } @@ -810,11 +908,16 @@ export class GPUTestBase extends Fixture { }); const storageBuffer = this.device.createBuffer({ - size: sampleCount * type.size * componentCount, + size: sampleCount * type.size * componentCount * width * height, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC }); this.trackForCleanup(storageBuffer); + const uniformBuffer = this.makeBufferWithContents( + new Uint32Array([origin.x, origin.y, width, height]), + GPUBufferUsage.UNIFORM + ); + const uniformBindGroup = this.device.createBindGroup({ layout: computePipeline.getBindGroupLayout(0), entries: [ @@ -827,6 +930,12 @@ export class GPUTestBase extends Fixture { resource: { buffer: storageBuffer } + }, + { + binding: 2, + resource: { + buffer: uniformBuffer + } }] }); @@ -835,7 +944,11 @@ export class GPUTestBase extends Fixture { const pass = encoder.beginComputePass(); pass.setPipeline(computePipeline); pass.setBindGroup(0, uniformBindGroup); - pass.dispatchWorkgroups(1); + pass.dispatchWorkgroups( + Math.floor((width + kWorkgroupSizeX - 1) / kWorkgroupSizeX), + Math.floor((height + kWorkgroupSizeY - 1) / kWorkgroupSizeY), + 1 + ); pass.end(); this.device.queue.submit([encoder.finish()]); @@ -1081,11 +1194,17 @@ export class GPUTest extends GPUTestBase { this.mismatchedProvider = await this.sharedState.acquireMismatchedProvider(); } + /** GPUAdapter that the device was created from. */ + get adapter() { + assert(this.provider !== undefined, 'internal error: DeviceProvider missing'); + return this.provider.adapter; + } + /** * GPUDevice for the test to use. */ get device() { - assert(this.provider !== undefined, 'internal error: GPUDevice missing?'); + assert(this.provider !== undefined, 'internal error: DeviceProvider missing'); return this.provider.device; } @@ -1238,6 +1357,8 @@ export class GPUTest extends GPUTestBase { + + @@ -1246,8 +1367,23 @@ const s_deviceToResourcesMap = new WeakMap(); /** * Gets a (cached) pipeline to render a texture to an rgba8unorm texture */ -function getPipelineToRenderTextureToRGB8UnormTexture(device) { +function getPipelineToRenderTextureToRGB8UnormTexture( +device, +texture, +isCompatibility) +{ if (!s_deviceToResourcesMap.has(device)) { + s_deviceToResourcesMap.set(device, { + pipelineByPipelineType: new Map() + }); + } + + const { pipelineByPipelineType } = s_deviceToResourcesMap.get(device); + const pipelineType = + isCompatibility && texture.depthOrArrayLayers > 1 ? '2d-array' : '2d'; + if (!pipelineByPipelineType.get(pipelineType)) { + const [textureType, layerCode] = + pipelineType === '2d' ? ['texture_2d', ''] : ['texture_2d_array', ', uni.baseArrayLayer']; const module = device.createShaderModule({ code: ` struct VSOutput { @@ -1255,6 +1391,10 @@ function getPipelineToRenderTextureToRGB8UnormTexture(device) { @location(0) texcoord: vec2f, }; + struct Uniforms { + baseArrayLayer: u32, + }; + @vertex fn vs( @builtin(vertex_index) vertexIndex : u32 ) -> VSOutput { @@ -1275,10 +1415,11 @@ function getPipelineToRenderTextureToRGB8UnormTexture(device) { } @group(0) @binding(0) var ourSampler: sampler; - @group(0) @binding(1) var ourTexture: texture_2d; + @group(0) @binding(1) var ourTexture: ${textureType}; + @group(0) @binding(2) var uni: Uniforms; @fragment fn fs(fsInput: VSOutput) -> @location(0) vec4f { - return textureSample(ourTexture, ourSampler, fsInput.texcoord); + return textureSample(ourTexture, ourSampler, fsInput.texcoord${layerCode}); } ` }); @@ -1294,10 +1435,10 @@ function getPipelineToRenderTextureToRGB8UnormTexture(device) { targets: [{ format: 'rgba8unorm' }] } }); - s_deviceToResourcesMap.set(device, { pipeline }); + pipelineByPipelineType.set(pipelineType, pipeline); } - const { pipeline } = s_deviceToResourcesMap.get(device); - return pipeline; + const pipeline = pipelineByPipelineType.get(pipelineType); + return { pipelineType, pipeline }; } @@ -1441,7 +1582,11 @@ Base) // Render every layer of both textures at mipLevel to an rgba8unorm texture // that matches the size of the mipLevel. After each render, copy the // result to a buffer and expect the results from both textures to match. - const pipeline = getPipelineToRenderTextureToRGB8UnormTexture(this.device); + const { pipelineType, pipeline } = getPipelineToRenderTextureToRGB8UnormTexture( + this.device, + actualTexture, + this.isCompatibility + ); const readbackPromisesPerTexturePerLayer = [actualTexture, expectedTexture].map( (texture, ndx) => { const attachmentSize = virtualMipSize('2d', [texture.width, texture.height, 1], mipLevel); @@ -1457,24 +1602,45 @@ Base) const numLayers = texture.depthOrArrayLayers; const readbackPromisesPerLayer = []; + + const uniformBuffer = this.device.createBuffer({ + size: 4, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST + }); + this.trackForCleanup(uniformBuffer); + for (let layer = 0; layer < numLayers; ++layer) { + const viewDescriptor = { + baseMipLevel: mipLevel, + mipLevelCount: 1, + ...(!this.isCompatibility && { + baseArrayLayer: layer, + arrayLayerCount: 1 + }), + dimension: pipelineType + }; + const bindGroup = this.device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries: [ { binding: 0, resource: sampler }, { binding: 1, - resource: texture.createView({ - baseMipLevel: mipLevel, - mipLevelCount: 1, - baseArrayLayer: layer, - arrayLayerCount: 1, - dimension: '2d' - }) - }] + resource: texture.createView(viewDescriptor) + }, + ...(pipelineType === '2d-array' ? + [ + { + binding: 2, + resource: { buffer: uniformBuffer } + }] : + + [])] }); + this.device.queue.writeBuffer(uniformBuffer, 0, new Uint32Array([layer])); + const encoder = this.device.createCommandEncoder(); const pass = encoder.beginRenderPass({ colorAttachments: [ diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/constructable.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/constructable.spec.js new file mode 100644 index 0000000000..7104b2e812 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/constructable.spec.js @@ -0,0 +1,54 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Test that constructable WebGPU objects are actually constructable. +`;import { makeTestGroup } from './../../common/framework/test_group.js'; +import { IDLTest } from './idl_test.js'; + +export const g = makeTestGroup(IDLTest); + +g.test('gpu_errors'). +desc('tests that GPUErrors are constructable'). +params((u) => +u.combine('errorType', [ +'GPUInternalError', +'GPUOutOfMemoryError', +'GPUValidationError'] +) +). +fn((t) => { + const { errorType } = t.params; + const Ctor = globalThis[errorType]; + const msg = 'this is a test'; + const error = new Ctor(msg); + t.expect(error.message === msg); +}); + +const pipelineErrorOptions = [ +{ reason: 'validation' }, +{ reason: 'internal' }]; + + +g.test('pipeline_errors'). +desc('tests that GPUPipelineError is constructable'). +params((u) => +u // +.combine('msg', [undefined, 'some msg']). +combine('options', pipelineErrorOptions) +). +fn((t) => { + const { msg, options } = t.params; + const error = new GPUPipelineError(msg, options); + const expectedMsg = msg || ''; + t.expect(error.message === expectedMsg); + t.expect(error.reason === options.reason); +}); + +g.test('uncaptured_error_event'). +desc('tests that GPUUncapturedErrorEvent is constructable'). +fn((t) => { + const msg = 'this is a test'; + const error = new GPUValidationError(msg); + const event = new GPUUncapturedErrorEvent('uncapturedError', { error }); + t.expect(event.error === error); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.http.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.http.html deleted file mode 100644 index 94a814d005..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.http.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - WebGPU exposed items (non-HTTPS) - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.https.html deleted file mode 100644 index 8d421b7020..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.https.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - WebGPU exposed items (HTTPS) - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/listing.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/listing.js index 7632956de5..147b11bccf 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/listing.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/listing.js @@ -1,4 +1,4 @@ -// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings.ts. +// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings_and_webworkers.ts. export const listing = [ { @@ -248,6 +248,15 @@ export const listing = [ "single_buffer" ] }, + { + "file": [ + "api", + "operation", + "memory_sync", + "texture", + "readonly_depth_stencil" + ] + }, { "file": [ "api", @@ -375,6 +384,14 @@ export const listing = [ "vertex_only_render_pipeline" ] }, + { + "file": [ + "api", + "operation", + "rendering", + "3d_texture_slices" + ] + }, { "file": [ "api", @@ -495,6 +512,22 @@ export const listing = [ "compilation_info" ] }, + { + "file": [ + "api", + "operation", + "storage_texture", + "read_only" + ] + }, + { + "file": [ + "api", + "operation", + "storage_texture", + "read_write" + ] + }, { "file": [ "api", @@ -641,6 +674,15 @@ export const listing = [ "maxBindGroups" ] }, + { + "file": [ + "api", + "validation", + "capability_checks", + "limits", + "maxBindGroupsPlusVertexBuffers" + ] + }, { "file": [ "api", @@ -1441,6 +1483,14 @@ export const listing = [ "primitive_state" ] }, + { + "file": [ + "api", + "validation", + "render_pipeline", + "resource_compatibility" + ] + }, { "file": [ "api", @@ -1577,6 +1627,22 @@ export const listing = [ "rg11b10ufloat_renderable" ] }, + { + "file": [ + "compat", + "api", + "validation", + "createBindGroup" + ] + }, + { + "file": [ + "compat", + "api", + "validation", + "createBindGroupLayout" + ] + }, { "file": [ "compat", @@ -1587,6 +1653,16 @@ export const listing = [ "copyTextureToBuffer" ] }, + { + "file": [ + "compat", + "api", + "validation", + "encoding", + "cmds", + "copyTextureToTexture" + ] + }, { "file": [ "compat", @@ -1597,6 +1673,15 @@ export const listing = [ "pipeline_bind_group_compat" ] }, + { + "file": [ + "compat", + "api", + "validation", + "render_pipeline", + "depth_stencil_state" + ] + }, { "file": [ "compat", @@ -1660,6 +1745,17 @@ export const listing = [ "flags" ] }, + { + "file": [ + "idl", + "constructable" + ] + }, + { + "file": [ + "print_environment" + ] + }, { "file": [ "shader" @@ -1673,6 +1769,56 @@ export const listing = [ ], "readme": "Tests that check the result of valid shader execution." }, + { + "file": [ + "shader", + "execution", + "expression", + "access", + "array", + "index" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "access", + "matrix", + "index" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "access", + "structure", + "index" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "access", + "vector", + "components" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "access", + "vector", + "index" + ] + }, { "file": [ "shader", @@ -1709,6 +1855,24 @@ export const listing = [ "af_matrix_addition" ] }, + { + "file": [ + "shader", + "execution", + "expression", + "binary", + "af_matrix_matrix_multiplication" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "binary", + "af_matrix_scalar_multiplication" + ] + }, { "file": [ "shader", @@ -1718,6 +1882,15 @@ export const listing = [ "af_matrix_subtraction" ] }, + { + "file": [ + "shader", + "execution", + "expression", + "binary", + "af_matrix_vector_multiplication" + ] + }, { "file": [ "shader", @@ -1745,6 +1918,24 @@ export const listing = [ "af_subtraction" ] }, + { + "file": [ + "shader", + "execution", + "expression", + "binary", + "ai_arithmetic" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "binary", + "ai_comparison" + ] + }, { "file": [ "shader", @@ -2367,6 +2558,26 @@ export const listing = [ "dot" ] }, + { + "file": [ + "shader", + "execution", + "expression", + "call", + "builtin", + "dot4I8Packed" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "call", + "builtin", + "dot4U8Packed" + ] + }, { "file": [ "shader", @@ -2717,6 +2928,46 @@ export const listing = [ "pack4x8unorm" ] }, + { + "file": [ + "shader", + "execution", + "expression", + "call", + "builtin", + "pack4xI8" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "call", + "builtin", + "pack4xI8Clamp" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "call", + "builtin", + "pack4xU8" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "call", + "builtin", + "pack4xU8Clamp" + ] + }, { "file": [ "shader", @@ -2904,7 +3155,7 @@ export const listing = [ "expression", "call", "builtin", - "textureDimension" + "textureDimensions" ] }, { @@ -3114,7 +3365,7 @@ export const listing = [ "expression", "call", "builtin", - "workgroupBarrier" + "unpack4xI8" ] }, { @@ -3122,8 +3373,9 @@ export const listing = [ "shader", "execution", "expression", - "unary", - "af_arithmetic" + "call", + "builtin", + "unpack4xU8" ] }, { @@ -3131,8 +3383,9 @@ export const listing = [ "shader", "execution", "expression", - "unary", - "af_assignment" + "call", + "builtin", + "workgroupBarrier" ] }, { @@ -3140,8 +3393,9 @@ export const listing = [ "shader", "execution", "expression", - "unary", - "bool_conversion" + "call", + "builtin", + "workgroupUniformLoad" ] }, { @@ -3149,8 +3403,9 @@ export const listing = [ "shader", "execution", "expression", - "unary", - "bool_logical" + "call", + "user", + "ptr_params" ] }, { @@ -3158,8 +3413,8 @@ export const listing = [ "shader", "execution", "expression", - "unary", - "f16_arithmetic" + "constructor", + "non_zero" ] }, { @@ -3167,8 +3422,8 @@ export const listing = [ "shader", "execution", "expression", - "unary", - "f16_conversion" + "constructor", + "zero_value" ] }, { @@ -3176,8 +3431,7 @@ export const listing = [ "shader", "execution", "expression", - "unary", - "f32_arithmetic" + "precedence" ] }, { @@ -3186,7 +3440,7 @@ export const listing = [ "execution", "expression", "unary", - "f32_conversion" + "address_of_and_indirection" ] }, { @@ -3195,7 +3449,7 @@ export const listing = [ "execution", "expression", "unary", - "i32_arithmetic" + "af_arithmetic" ] }, { @@ -3204,7 +3458,7 @@ export const listing = [ "execution", "expression", "unary", - "i32_complement" + "af_assignment" ] }, { @@ -3213,7 +3467,7 @@ export const listing = [ "execution", "expression", "unary", - "i32_conversion" + "ai_arithmetic" ] }, { @@ -3222,7 +3476,7 @@ export const listing = [ "execution", "expression", "unary", - "u32_complement" + "ai_assignment" ] }, { @@ -3231,21 +3485,120 @@ export const listing = [ "execution", "expression", "unary", - "u32_conversion" + "ai_complement" ] }, { "file": [ "shader", "execution", - "float_parse" + "expression", + "unary", + "bool_conversion" ] }, { "file": [ "shader", "execution", - "flow_control", + "expression", + "unary", + "bool_logical" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "unary", + "f16_arithmetic" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "unary", + "f16_conversion" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "unary", + "f32_arithmetic" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "unary", + "f32_conversion" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "unary", + "i32_arithmetic" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "unary", + "i32_complement" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "unary", + "i32_conversion" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "unary", + "u32_complement" + ] + }, + { + "file": [ + "shader", + "execution", + "expression", + "unary", + "u32_conversion" + ] + }, + { + "file": [ + "shader", + "execution", + "float_parse" + ] + }, + { + "file": [ + "shader", + "execution", + "flow_control", "call" ] }, @@ -3321,6 +3674,13 @@ export const listing = [ "while" ] }, + { + "file": [ + "shader", + "execution", + "memory_layout" + ] + }, { "file": [ "shader", @@ -3353,6 +3713,14 @@ export const listing = [ "coherence" ] }, + { + "file": [ + "shader", + "execution", + "memory_model", + "texture_intra_invocation_coherence" + ] + }, { "file": [ "shader", @@ -3385,93 +3753,856 @@ export const listing = [ { "file": [ "shader", - "execution", - "shader_io", - "compute_builtins" + "execution", + "shader_io", + "compute_builtins" + ] + }, + { + "file": [ + "shader", + "execution", + "shader_io", + "fragment_builtins" + ] + }, + { + "file": [ + "shader", + "execution", + "shader_io", + "shared_structs" + ] + }, + { + "file": [ + "shader", + "execution", + "shader_io", + "user_io" + ] + }, + { + "file": [ + "shader", + "execution", + "shader_io", + "workgroup_size" + ] + }, + { + "file": [ + "shader", + "execution", + "shadow" + ] + }, + { + "file": [ + "shader", + "execution", + "stage" + ] + }, + { + "file": [ + "shader", + "execution", + "statement", + "compound" + ] + }, + { + "file": [ + "shader", + "execution", + "statement", + "discard" + ] + }, + { + "file": [ + "shader", + "execution", + "statement", + "increment_decrement" + ] + }, + { + "file": [ + "shader", + "execution", + "zero_init" + ] + }, + { + "file": [ + "shader", + "regression" + ], + "readme": "One-off tests that reproduce shader bugs found in implementations to prevent the bugs from\nappearing again." + }, + { + "file": [ + "shader", + "validation" + ], + "readme": "Positive and negative tests for all the validation rules of the shading language." + }, + { + "file": [ + "shader", + "validation", + "const_assert", + "const_assert" + ] + }, + { + "file": [ + "shader", + "validation", + "decl", + "compound_statement" + ] + }, + { + "file": [ + "shader", + "validation", + "decl", + "const" + ] + }, + { + "file": [ + "shader", + "validation", + "decl", + "context_dependent_resolution" + ] + }, + { + "file": [ + "shader", + "validation", + "decl", + "let" + ] + }, + { + "file": [ + "shader", + "validation", + "decl", + "override" + ] + }, + { + "file": [ + "shader", + "validation", + "decl", + "ptr_spelling" + ] + }, + { + "file": [ + "shader", + "validation", + "decl", + "var" + ] + }, + { + "file": [ + "shader", + "validation", + "decl", + "var_access_mode" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "access", + "vector" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "binary", + "add_sub_mul" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "binary", + "and_or_xor" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "binary", + "bitwise_shift" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "binary", + "comparison" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "binary", + "div_rem" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "abs" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "acos" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "acosh" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "all" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "any" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "arrayLength" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "asin" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "asinh" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "atan" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "atan2" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "atanh" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "atomics" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "barriers" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "bitcast" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "ceil" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "clamp" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "cos" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "cosh" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "countLeadingZeros" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "countOneBits" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "countTrailingZeros" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "cross" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "degrees" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "derivatives" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "determinant" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "distance" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "dot4I8Packed" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "dot4U8Packed" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "exp" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "exp2" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "extractBits" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "faceForward" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "firstLeadingBit" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "firstTrailingBit" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "floor" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "fract" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "frexp" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "insertBits" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "inverseSqrt" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "length" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "log" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "log2" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "max" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "min" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "modf" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "normalize" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "pack2x16snorm" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "pack2x16unorm" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "pack4x8snorm" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "pack4x8unorm" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "pack4xI8" + ] + }, + { + "file": [ + "shader", + "validation", + "expression", + "call", + "builtin", + "pack4xI8Clamp" ] }, { "file": [ "shader", - "execution", - "shader_io", - "shared_structs" + "validation", + "expression", + "call", + "builtin", + "pack4xU8" ] }, { "file": [ "shader", - "execution", - "shadow" + "validation", + "expression", + "call", + "builtin", + "pack4xU8Clamp" ] }, { "file": [ "shader", - "execution", - "statement", - "increment_decrement" + "validation", + "expression", + "call", + "builtin", + "quantizeToF16" ] }, { "file": [ "shader", - "execution", - "zero_init" + "validation", + "expression", + "call", + "builtin", + "radians" ] }, { "file": [ "shader", - "regression" - ], - "readme": "One-off tests that reproduce shader bugs found in implementations to prevent the bugs from\nappearing again." + "validation", + "expression", + "call", + "builtin", + "reflect" + ] }, { "file": [ "shader", - "validation" - ], - "readme": "Positive and negative tests for all the validation rules of the shading language." + "validation", + "expression", + "call", + "builtin", + "reverseBits" + ] }, { "file": [ "shader", "validation", - "const_assert", - "const_assert" + "expression", + "call", + "builtin", + "round" ] }, { "file": [ "shader", "validation", - "decl", - "const" + "expression", + "call", + "builtin", + "saturate" ] }, { "file": [ "shader", "validation", - "decl", - "override" + "expression", + "call", + "builtin", + "select" ] }, { "file": [ "shader", "validation", - "decl", - "ptr_spelling" + "expression", + "call", + "builtin", + "sign" ] }, { "file": [ "shader", "validation", - "decl", - "var_access_mode" + "expression", + "call", + "builtin", + "sin" ] }, { @@ -3479,8 +4610,9 @@ export const listing = [ "shader", "validation", "expression", - "access", - "vector" + "call", + "builtin", + "sinh" ] }, { @@ -3488,8 +4620,9 @@ export const listing = [ "shader", "validation", "expression", - "binary", - "bitwise_shift" + "call", + "builtin", + "smoothstep" ] }, { @@ -3499,7 +4632,7 @@ export const listing = [ "expression", "call", "builtin", - "abs" + "sqrt" ] }, { @@ -3509,7 +4642,7 @@ export const listing = [ "expression", "call", "builtin", - "acos" + "step" ] }, { @@ -3519,7 +4652,7 @@ export const listing = [ "expression", "call", "builtin", - "acosh" + "tan" ] }, { @@ -3529,7 +4662,7 @@ export const listing = [ "expression", "call", "builtin", - "asin" + "tanh" ] }, { @@ -3539,7 +4672,7 @@ export const listing = [ "expression", "call", "builtin", - "asinh" + "textureGather" ] }, { @@ -3549,7 +4682,7 @@ export const listing = [ "expression", "call", "builtin", - "atan" + "textureGatherCompare" ] }, { @@ -3559,7 +4692,7 @@ export const listing = [ "expression", "call", "builtin", - "atan2" + "textureLoad" ] }, { @@ -3569,7 +4702,7 @@ export const listing = [ "expression", "call", "builtin", - "atanh" + "textureSample" ] }, { @@ -3579,7 +4712,7 @@ export const listing = [ "expression", "call", "builtin", - "atomics" + "textureSampleBaseClampToEdge" ] }, { @@ -3589,7 +4722,7 @@ export const listing = [ "expression", "call", "builtin", - "bitcast" + "textureSampleBias" ] }, { @@ -3599,7 +4732,7 @@ export const listing = [ "expression", "call", "builtin", - "ceil" + "textureSampleCompare" ] }, { @@ -3609,7 +4742,7 @@ export const listing = [ "expression", "call", "builtin", - "clamp" + "textureSampleCompareLevel" ] }, { @@ -3619,7 +4752,7 @@ export const listing = [ "expression", "call", "builtin", - "cos" + "textureSampleGrad" ] }, { @@ -3629,7 +4762,7 @@ export const listing = [ "expression", "call", "builtin", - "cosh" + "textureSampleLevel" ] }, { @@ -3639,7 +4772,7 @@ export const listing = [ "expression", "call", "builtin", - "degrees" + "textureStore" ] }, { @@ -3649,7 +4782,7 @@ export const listing = [ "expression", "call", "builtin", - "exp" + "trunc" ] }, { @@ -3659,7 +4792,7 @@ export const listing = [ "expression", "call", "builtin", - "exp2" + "unpack2x16float" ] }, { @@ -3669,7 +4802,7 @@ export const listing = [ "expression", "call", "builtin", - "inverseSqrt" + "unpack2x16snorm" ] }, { @@ -3679,7 +4812,7 @@ export const listing = [ "expression", "call", "builtin", - "length" + "unpack2x16unorm" ] }, { @@ -3689,7 +4822,7 @@ export const listing = [ "expression", "call", "builtin", - "log" + "unpack4x8snorm" ] }, { @@ -3699,7 +4832,7 @@ export const listing = [ "expression", "call", "builtin", - "log2" + "unpack4x8unorm" ] }, { @@ -3709,7 +4842,7 @@ export const listing = [ "expression", "call", "builtin", - "modf" + "unpack4xI8" ] }, { @@ -3719,7 +4852,7 @@ export const listing = [ "expression", "call", "builtin", - "radians" + "unpack4xU8" ] }, { @@ -3729,7 +4862,7 @@ export const listing = [ "expression", "call", "builtin", - "round" + "workgroupUniformLoad" ] }, { @@ -3737,9 +4870,7 @@ export const listing = [ "shader", "validation", "expression", - "call", - "builtin", - "saturate" + "overload_resolution" ] }, { @@ -3747,9 +4878,7 @@ export const listing = [ "shader", "validation", "expression", - "call", - "builtin", - "sign" + "precedence" ] }, { @@ -3757,9 +4886,8 @@ export const listing = [ "shader", "validation", "expression", - "call", - "builtin", - "sin" + "unary", + "address_of_and_indirection" ] }, { @@ -3767,9 +4895,8 @@ export const listing = [ "shader", "validation", "expression", - "call", - "builtin", - "sinh" + "unary", + "arithmetic_negation" ] }, { @@ -3777,9 +4904,8 @@ export const listing = [ "shader", "validation", "expression", - "call", - "builtin", - "sqrt" + "unary", + "bitwise_complement" ] }, { @@ -3787,9 +4913,24 @@ export const listing = [ "shader", "validation", "expression", - "call", - "builtin", - "tan" + "unary", + "logical_negation" + ] + }, + { + "file": [ + "shader", + "validation", + "extension", + "pointer_composite_access" + ] + }, + { + "file": [ + "shader", + "validation", + "extension", + "readonly_and_readwrite_storage_textures" ] }, { @@ -3848,6 +4989,14 @@ export const listing = [ "break" ] }, + { + "file": [ + "shader", + "validation", + "parse", + "break_if" + ] + }, { "file": [ "shader", @@ -3864,6 +5013,14 @@ export const listing = [ "comments" ] }, + { + "file": [ + "shader", + "validation", + "parse", + "compound" + ] + }, { "file": [ "shader", @@ -3880,6 +5037,14 @@ export const listing = [ "const_assert" ] }, + { + "file": [ + "shader", + "validation", + "parse", + "continuing" + ] + }, { "file": [ "shader", @@ -3936,6 +5101,14 @@ export const listing = [ "pipeline_stage" ] }, + { + "file": [ + "shader", + "validation", + "parse", + "requires" + ] + }, { "file": [ "shader", @@ -3944,6 +5117,14 @@ export const listing = [ "semicolon" ] }, + { + "file": [ + "shader", + "validation", + "parse", + "shadow_builtins" + ] + }, { "file": [ "shader", @@ -3952,6 +5133,14 @@ export const listing = [ "source" ] }, + { + "file": [ + "shader", + "validation", + "parse", + "statement_behavior" + ] + }, { "file": [ "shader", @@ -4032,6 +5221,14 @@ export const listing = [ "invariant" ] }, + { + "file": [ + "shader", + "validation", + "shader_io", + "layout_constraints" + ] + }, { "file": [ "shader", @@ -4064,6 +5261,30 @@ export const listing = [ "alias" ] }, + { + "file": [ + "shader", + "validation", + "types", + "array" + ] + }, + { + "file": [ + "shader", + "validation", + "types", + "atomics" + ] + }, + { + "file": [ + "shader", + "validation", + "types", + "matrix" + ] + }, { "file": [ "shader", @@ -4072,6 +5293,14 @@ export const listing = [ "struct" ] }, + { + "file": [ + "shader", + "validation", + "types", + "textures" + ] + }, { "file": [ "shader", @@ -4088,6 +5317,13 @@ export const listing = [ "uniformity" ] }, + { + "file": [ + "util", + "texture", + "color_space_conversions" + ] + }, { "file": [ "util", diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/multisample_info.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/multisample_info.js new file mode 100644 index 0000000000..5473d4ca74 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/multisample_info.js @@ -0,0 +1,75 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ /* Data used for multisample tests */const samplePositionToFragmentPosition = (pos) => +pos.map((v) => v / 16); +const samplePositionsToFragmentPositions = ( +positions) => +positions.map(samplePositionToFragmentPosition); + +// These are sample positions based on a 16x16 grid with 0,0 at the top left. +// For example 8,8 would be a fragment coordinate of 0.5, 0.5 +// Based on: https://learn.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels +const kMultisamplingTables = new Map([ +[1, samplePositionsToFragmentPositions([[8, 8]])], +[ +2, +samplePositionsToFragmentPositions([ +[4, 4], +[12, 12]] +)], + +[ +4, +samplePositionsToFragmentPositions([ +[6, 2], +[14, 6], +[2, 10], +[10, 14]] +)], + +[ +8, +samplePositionsToFragmentPositions([ +[9, 5], +[7, 11], +[13, 9], +[5, 3], +[3, 13], +[1, 7], +[11, 15], +[15, 1]] +)], + +[ +16, +samplePositionsToFragmentPositions([ +[9, 9], +[7, 5], +[5, 10], +[12, 7], + +[3, 6], +[10, 13], +[13, 11], +[11, 3], + +[6, 14], +[8, 1], +[4, 2], +[2, 12], + +[0, 8], +[15, 4], +[14, 15], +[1, 0]] +)]] + +); + +/** + * For a given sampleCount returns an array of 2d fragment offsets + * where each offset is between 0 and 1. + */ +export function getMultisampleFragmentOffsets(sampleCount) { + return kMultisamplingTables.get(sampleCount); +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/print_environment.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/print_environment.spec.js new file mode 100644 index 0000000000..83ef03afd3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/print_environment.spec.js @@ -0,0 +1,70 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` + +Examples of writing CTS tests with various features. + +Start here when looking for examples of basic framework usage. +`;import { getResourcePath } from '../common/framework/resources.js'; +import { globalTestConfig } from '../common/framework/test_config.js'; +import { makeTestGroup } from '../common/framework/test_group.js'; +import { getDefaultRequestAdapterOptions } from '../common/util/navigator_gpu.js'; + +import { GPUTest } from './gpu_test.js'; + +export const g = makeTestGroup(GPUTest); + +/** console.log is disallowed by WPT. Work around it when we're not in WPT. */ +function consoleLogIfNotWPT(x) { + if (!('step_timeout' in globalThis)) { + const cons = console; + cons.log(x); + } +} + +g.test('info'). +desc( + `Test which prints what global scope (e.g. worker type) it's running in. +Typically, tests will check for the presence of the feature they need (like HTMLCanvasElement) +and skip if it's not available. + +Run this test under various configurations to see different results +(Window, worker scopes, Node, etc.) + +NOTE: If your test runtime elides logs when tests pass, you won't see the prints from this test +in the logs. On non-WPT runtimes, it will also print to the console with console.log. +WPT disallows console.log and doesn't support logs on passing tests, so this does nothing on WPT.` +). +fn(async (t) => { + const adapterInfo = await t.adapter.requestAdapterInfo(); + + const info = JSON.stringify( + { + globalScope: Object.getPrototypeOf(globalThis).constructor.name, + globalTestConfig, + baseResourcePath: getResourcePath(''), + defaultRequestAdapterOptions: getDefaultRequestAdapterOptions(), + adapterInfo, + userAgent: navigator.userAgent + }, + // Flatten objects with prototype chains into plain objects, using `for..in`. (Otherwise, + // properties from the prototype chain will be ignored and things will print as `{}`.) + (_key, value) => { + if (value === undefined || value === null) return null; + if (typeof value !== 'object') return value; + + const valueObj = value; + return Object.fromEntries( + function* () { + for (const key in valueObj) { + yield [key, valueObj[key]]; + } + }() + ); + }, + 2 + ); + + t.info(info); + consoleLogIfNotWPT(info); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/array/index.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/array/index.spec.js new file mode 100644 index 0000000000..8a1c0c2fc0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/array/index.spec.js @@ -0,0 +1,354 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for array indexing expressions +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { + False, + True, + Type, + + array, + f32, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { align } from '../../../../../util/math.js'; + +import { allInputSources, basicExpressionBuilder, run } from '../../expression.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('concrete_scalar'). +specURL('https://www.w3.org/TR/WGSL/#array-access-expr'). +desc(`Test indexing of an array of concrete scalars`). +params((u) => +u. +combine( + 'inputSource', + // 'uniform' address space requires array stride to be multiple of 16 bytes + allInputSources.filter((s) => s !== 'uniform') +). +combine('elementType', ['i32', 'u32', 'f32', 'f16']). +combine('indexType', ['i32', 'u32']) +). +beforeAllSubcases((t) => { + if (t.params.elementType === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.elementType]; + const indexType = Type[t.params.indexType]; + const cases = [ + { + input: [ + array( + /* 0 */elementType.create(10), + /* 1 */elementType.create(11), + /* 2 */elementType.create(12) + ), + indexType.create(0)], + + expected: elementType.create(10) + }, + { + input: [ + array( + /* 0 */elementType.create(20), + /* 1 */elementType.create(21), + /* 2 */elementType.create(22) + ), + indexType.create(1)], + + expected: elementType.create(21) + }, + { + input: [ + array( + /* 0 */elementType.create(30), + /* 1 */elementType.create(31), + /* 2 */elementType.create(32) + ), + indexType.create(2)], + + expected: elementType.create(32) + }]; + + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}[${ops[1]}]`), + [Type.array(3, elementType), indexType], + elementType, + t.params, + cases + ); +}); + +g.test('bool'). +specURL('https://www.w3.org/TR/WGSL/#array-access-expr'). +desc(`Test indexing of an array of booleans`). +params((u) => +u. +combine( + 'inputSource', + // 'uniform' address space requires array stride to be multiple of 16 bytes + allInputSources.filter((s) => s !== 'uniform') +). +combine('indexType', ['i32', 'u32']) +). +fn(async (t) => { + const indexType = Type[t.params.indexType]; + const cases = [ + { + input: [array(True, False, True), indexType.create(0)], + expected: True + }, + { + input: [array(True, False, True), indexType.create(1)], + expected: False + }, + { + input: [array(True, False, True), indexType.create(2)], + expected: True + }]; + + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}[${ops[1]}]`), + [Type.array(3, Type.bool), indexType], + Type.bool, + t.params, + cases + ); +}); + +g.test('abstract_scalar'). +specURL('https://www.w3.org/TR/WGSL/#array-access-expr'). +desc(`Test indexing of an array of scalars`). +params((u) => +u. +combine('elementType', ['abstract-int', 'abstract-float']). +combine('indexType', ['i32', 'u32']) +). +fn(async (t) => { + const elementType = Type[t.params.elementType]; + const indexType = Type[t.params.indexType]; + const cases = [ + { + input: [ + array( + /* 0 */elementType.create(0x10_00000000), + /* 1 */elementType.create(0x11_00000000), + /* 2 */elementType.create(0x12_00000000) + ), + indexType.create(0)], + + expected: f32(0x10) + }, + { + input: [ + array( + /* 0 */elementType.create(0x20_00000000), + /* 1 */elementType.create(0x21_00000000), + /* 2 */elementType.create(0x22_00000000) + ), + indexType.create(1)], + + expected: f32(0x21) + }, + { + input: [ + array( + /* 0 */elementType.create(0x30_00000000), + /* 1 */elementType.create(0x31_00000000), + /* 2 */elementType.create(0x32_00000000) + ), + indexType.create(2)], + + expected: f32(0x32) + }]; + + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}[${ops[1]}] / 0x100000000`), + [Type.array(3, elementType), indexType], + Type.f32, + { inputSource: 'const' }, + cases + ); +}); + +g.test('runtime_sized'). +specURL('https://www.w3.org/TR/WGSL/#array-access-expr'). +desc(`Test indexing of a runtime sized array`). +params((u) => +u. +combine('elementType', [ +'i32', +'u32', +'f32', +'f16', +'vec4i', +'vec2u', +'vec3f', +'vec2h'] +). +combine('indexType', ['i32', 'u32']) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(Type[t.params.elementType]).kind === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const elementType = Type[t.params.elementType]; + const valueArrayType = Type.array(0, elementType); + const indexType = Type[t.params.indexType]; + const indexArrayType = Type.array(0, indexType); + + const wgsl = ` +${scalarTypeOf(elementType).kind === 'f16' ? 'enable f16;' : ''} + +@group(0) @binding(0) var input_values : ${valueArrayType}; +@group(0) @binding(1) var input_indices : ${indexArrayType}; +@group(0) @binding(2) var output : ${valueArrayType}; + +@compute @workgroup_size(16) +fn main(@builtin(local_invocation_index) invocation_id : u32) { + let index = input_indices[invocation_id]; + output[invocation_id] = input_values[index]; +} +`; + + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ code: wgsl }), + entryPoint: 'main' + } + }); + + const values = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]; + const indices = [9, 0, 14, 10, 12, 4, 15, 3, 5, 6, 11, 2, 8, 13, 7, 1]; + + const inputValues = values.map((i) => elementType.create(i)); + const inputIndices = indices.map((i) => indexType.create(i)); + const expected = indices.map((i) => inputValues[i]); + + const bufferSize = (arr) => { + let offset = 0; + let alignment = 0; + for (const value of arr) { + alignment = Math.max(alignment, value.type.alignment); + offset = align(offset, value.type.alignment) + value.type.size; + } + return align(offset, alignment); + }; + + const toArray = (arr) => { + const array = new Uint8Array(bufferSize(arr)); + let offset = 0; + for (const value of arr) { + offset = align(offset, value.type.alignment); + value.copyTo(array, offset); + offset += value.type.size; + } + return array; + }; + + const inputArrayBuffer = t.makeBufferWithContents(toArray(inputValues), GPUBufferUsage.STORAGE); + const inputIndexBuffer = t.makeBufferWithContents( + toArray(inputIndices), + GPUBufferUsage.STORAGE + ); + const outputBuffer = t.device.createBuffer({ + size: bufferSize(expected), + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC + }); + + const bindGroup = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { binding: 0, resource: { buffer: inputArrayBuffer } }, + { binding: 1, resource: { buffer: inputIndexBuffer } }, + { binding: 2, resource: { buffer: outputBuffer } }] + + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bindGroup); + pass.dispatchWorkgroups(1); + pass.end(); + t.queue.submit([encoder.finish()]); + + t.expectGPUBufferValuesEqual(outputBuffer, toArray(expected)); +}); + +g.test('vector'). +specURL('https://www.w3.org/TR/WGSL/#array-access-expr'). +desc(`Test indexing of an array of vectors`). +params((u) => +u. +combine('inputSource', allInputSources). +expand('elementType', (t) => +t.inputSource === 'uniform' ? +['vec4i', 'vec4u', 'vec4f'] : +['vec4i', 'vec4u', 'vec4f', 'vec4h'] +). +combine('indexType', ['i32', 'u32']) +). +beforeAllSubcases((t) => { + if (t.params.elementType === 'vec4h') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.elementType]; + const indexType = Type[t.params.indexType]; + const cases = [ + { + input: [ + array( + /* 0 */elementType.create([0x10, 0x11, 0x12, 0x13]), + /* 1 */elementType.create([0x14, 0x15, 0x16, 0x17]), + /* 2 */elementType.create([0x18, 0x19, 0x1a, 0x1b]) + ), + indexType.create(0)], + + expected: elementType.create([0x10, 0x11, 0x12, 0x13]) + }, + { + input: [ + array( + /* 0 */elementType.create([0x20, 0x21, 0x22, 0x23]), + /* 1 */elementType.create([0x24, 0x25, 0x26, 0x27]), + /* 2 */elementType.create([0x28, 0x29, 0x2a, 0x2b]) + ), + indexType.create(1)], + + expected: elementType.create([0x24, 0x25, 0x26, 0x27]) + }, + { + input: [ + array( + /* 0 */elementType.create([0x30, 0x31, 0x32, 0x33]), + /* 1 */elementType.create([0x34, 0x35, 0x36, 0x37]), + /* 2 */elementType.create([0x38, 0x39, 0x3a, 0x3b]) + ), + indexType.create(2)], + + expected: elementType.create([0x38, 0x39, 0x3a, 0x3b]) + }]; + + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}[${ops[1]}]`), + [Type.array(3, elementType), indexType], + elementType, + t.params, + cases + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/matrix/index.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/matrix/index.spec.js new file mode 100644 index 0000000000..0f44f06305 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/matrix/index.spec.js @@ -0,0 +1,200 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for matrix indexing expressions +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { + MatrixValue, + + Type, + abstractFloat, + f32, + vec } from +'../../../../../util/conversion.js'; + +import { allInputSources, basicExpressionBuilder, run } from '../../expression.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('concrete_float_column'). +specURL('https://www.w3.org/TR/WGSL/#matrix-access-expr'). +desc(`Test indexing a column vector from a concrete matrix`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('elementType', ['f32', 'f16']). +combine('indexType', ['i32', 'u32']). +combine('columns', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +beforeAllSubcases((t) => { + if (t.params.elementType === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.elementType]; + const indexType = Type[t.params.indexType]; + const matrixType = Type.mat(t.params.columns, t.params.rows, elementType); + const columnType = Type.vec(t.params.rows, elementType); + const elements = []; + for (let c = 0; c < t.params.columns; c++) { + const column = []; + for (let r = 0; r < t.params.rows; r++) { + column.push(elementType.create((c + 1) * 10 + (r + 1))); + } + elements.push(column); + } + const vector = new MatrixValue(elements); + const cases = []; + for (let c = 0; c < t.params.columns; c++) { + cases.push({ + input: [vector, indexType.create(c)], + expected: vec(...elements[c]) + }); + } + + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}[${ops[1]}]`), + [matrixType, indexType], + columnType, + t.params, + cases + ); +}); + +g.test('concrete_float_element'). +specURL('https://www.w3.org/TR/WGSL/#matrix-access-expr'). +desc(`Test indexing a single element from a concrete matrix`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('elementType', ['f32', 'f16']). +combine('indexType', ['i32', 'u32']). +combine('columns', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +beforeAllSubcases((t) => { + if (t.params.elementType === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.elementType]; + const indexType = Type[t.params.indexType]; + const matrixType = Type.mat(t.params.columns, t.params.rows, elementType); + const columnValues = []; + for (let c = 0; c < t.params.columns; c++) { + const column = []; + for (let r = 0; r < t.params.rows; r++) { + column.push(elementType.create((c + 1) * 10 + (r + 1))); + } + columnValues.push(column); + } + const matrix = new MatrixValue(columnValues); + const cases = []; + for (let c = 0; c < t.params.columns; c++) { + for (let r = 0; r < t.params.rows; r++) { + cases.push({ + input: [matrix, indexType.create(c), indexType.create(r)], + expected: columnValues[c][r] + }); + } + } + + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}[${ops[1]}][${ops[2]}]`), + [matrixType, indexType, indexType], + elementType, + t.params, + cases + ); +}); + +g.test('abstract_float_column'). +specURL('https://www.w3.org/TR/WGSL/#matrix-access-expr'). +desc(`Test indexing a column vector from a abstract-float matrix`). +params((u) => +u. +combine('indexType', ['i32', 'u32']). +combine('columns', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +fn(async (t) => { + const indexType = Type[t.params.indexType]; + const matrixType = Type.mat(t.params.columns, t.params.rows, Type.abstractFloat); + const vecfColumnType = Type.vec(t.params.rows, Type.f32); + const values = []; + for (let c = 0; c < t.params.columns; c++) { + const column = []; + for (let r = 0; r < t.params.rows; r++) { + column.push((c + 1) * 10 + (r + 1)); + } + values.push(column); + } + const matrix = new MatrixValue( + values.map((column) => column.map((v) => abstractFloat(v * 0x100000000))) + ); + const cases = []; + for (let c = 0; c < t.params.columns; c++) { + cases.push({ + input: [matrix, indexType.create(c)], + expected: vec(...values[c].map((v) => f32(v))) + }); + } + + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}[${ops[1]}] / 0x100000000`), + [matrixType, indexType], + vecfColumnType, + { inputSource: 'const' }, + cases + ); +}); + +g.test('abstract_float_element'). +specURL('https://www.w3.org/TR/WGSL/#matrix-access-expr'). +desc(`Test indexing a single element from a abstract-float matrix`). +params((u) => +u. +combine('indexType', ['i32', 'u32']). +combine('columns', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +fn(async (t) => { + const indexType = Type[t.params.indexType]; + const matrixType = Type.mat(t.params.columns, t.params.rows, Type.abstractFloat); + const values = []; + for (let c = 0; c < t.params.columns; c++) { + const column = []; + for (let r = 0; r < t.params.rows; r++) { + column.push((c + 1) * 10 + (r + 1)); + } + values.push(column); + } + const matrix = new MatrixValue( + values.map((column) => column.map((v) => abstractFloat(v * 0x100000000))) + ); + const cases = []; + for (let c = 0; c < t.params.columns; c++) { + for (let r = 0; r < t.params.rows; r++) { + cases.push({ + input: [matrix, indexType.create(c), indexType.create(r)], + expected: f32(values[c][r]) + }); + } + } + + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}[${ops[1]}][${ops[2]}] / 0x100000000`), + [matrixType, indexType, indexType], + Type.f32, + { inputSource: 'const' }, + cases + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/structure/index.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/structure/index.spec.js new file mode 100644 index 0000000000..bf07397364 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/structure/index.spec.js @@ -0,0 +1,508 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for structure member accessing expressions +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { Type, u32 } from '../../../../../util/conversion.js'; +import { align } from '../../../../../util/math.js'; +import { toComparator } from '../../expectation.js'; +import { structLayout, structStride } from '../../expression.js'; + +export const g = makeTestGroup(GPUTest); + +const kMemberTypes = [ +['bool'], +['u32'], +['vec3f'], +['i32', 'u32'], +['i32', 'f16', 'vec4i', 'mat3x2f'], +['bool', 'u32', 'f16', 'vec3f', 'vec2i'], +['i32', 'u32', 'f32', 'f16', 'vec3f', 'vec4i']]; + + +const kMemberTypesNoBool = kMemberTypes.filter((tys) => !tys.includes('bool')); + +async function run( +t, +wgsl, +expected, +input, +inputSource) +{ + const outputBufferSize = structStride( + expected.map((v) => v.type), + 'storage_rw' + ); + + const outputBuffer = t.device.createBuffer({ + size: outputBufferSize, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE + }); + + const bindGroupEntries = [ + { + binding: 0, + resource: { buffer: outputBuffer } + }]; + + + if (input !== null) { + let inputData; + if (input instanceof Array) { + const inputTypes = input.map((v) => v.type); + const inputBufferSize = structStride(inputTypes, inputSource); + inputData = new Uint8Array(inputBufferSize); + structLayout(inputTypes, inputSource, (m) => { + input[m.index].copyTo(inputData, m.offset); + }); + } else { + inputData = new Uint8Array(input); + } + + const inputBuffer = t.makeBufferWithContents( + inputData, + GPUBufferUsage.COPY_SRC | ( + inputSource === 'uniform' ? GPUBufferUsage.UNIFORM : GPUBufferUsage.STORAGE) + ); + + bindGroupEntries.push({ + binding: 1, + resource: { buffer: inputBuffer } + }); + } + + // build the shader module + const module = t.device.createShaderModule({ code: wgsl }); + + // build the pipeline + const pipeline = await t.device.createComputePipelineAsync({ + layout: 'auto', + compute: { module, entryPoint: 'main' } + }); + + // build the bind group + const group = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: bindGroupEntries + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, group); + pass.dispatchWorkgroups(1); + pass.end(); + + t.queue.submit([encoder.finish()]); + + const checkExpectation = (outputData) => { + // The list of expectation failures + const errs = []; + + let offset = 0; + for (let i = 0; i < expected.length; i++) { + offset = align(offset, expected[i].type.alignment); + const got = expected[i].type.read(outputData, offset); + const cmp = toComparator(expected[i]).compare(got); + if (!cmp.matched) { + errs.push(`result ${i}:) + returned: ${cmp.got} + expected: ${cmp.expected}`); + } + offset += expected[i].type.size; + } + + return errs.length > 0 ? new Error(errs.join('\n\n')) : undefined; + }; + + t.expectGPUBufferValuesPassCheck(outputBuffer, checkExpectation, { + type: Uint8Array, + typedLength: outputBufferSize + }); +} + +g.test('buffer'). +specURL('https://www.w3.org/TR/WGSL/#struct-access-expr'). +desc(`Test accessing of a value structure in a storage or uniform buffer`). +params((u) => +u. +combine('member_types', kMemberTypesNoBool). +combine('inputSource', ['uniform', 'storage']). +beginSubcases(). +expand('member_index', (t) => t.member_types.map((_, i) => i)) +). +beforeAllSubcases((t) => { + if (t.params.member_types.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const values = t.params.member_types.map((ty, i) => Type[ty].create(i)); + const expected = values[t.params.member_index]; + + await run( + t, + ` +${t.params.member_types.includes('f16') ? 'enable f16;' : ''} + +@group(0) @binding(0) var output : ${expected.type}; +@group(0) @binding(1) var<${t.params.inputSource}> input : MyStruct; + +struct MyStruct { + ${t.params.member_types.map((ty, i) => ` member_${i} : ${ty},`).join('\n')} +}; + +@workgroup_size(1) @compute +fn main() { + output = input.member_${t.params.member_index}; +} +`, + /* expected */[expected], + /* input */values, + /* inputSource */t.params.inputSource === 'uniform' ? 'uniform' : 'storage_r' + ); +}); + +g.test('buffer_align'). +specURL('https://www.w3.org/TR/WGSL/#struct-access-expr'). +desc( + `Test accessing of a value structure in a storage buffer that has members using the @align attribute` +). +params((u) => +u. +beginSubcases(). +combine('member_index', [0, 1, 2]). +combine('alignments', [ +[1, 1, 1], +[4, 4, 4], +[4, 8, 16], +[8, 4, 16], +[8, 16, 4]] +) +). +fn(async (t) => { + const memberTypes = ['i32', 'u32', 'f32']; + const values = memberTypes.map((ty, i) => Type[ty].create(i)); + const expected = values[t.params.member_index]; + const input = new Uint8Array(64); + let offset = 4; // pre : i32 + for (let i = 0; i < 3; i++) { + offset = align(offset, t.params.alignments[i]); + values[i].copyTo(input, offset); + offset += values[i].type.size; + } + await run( + t, + ` +@group(0) @binding(0) var output : ${expected.type}; +@group(0) @binding(1) var input : MyStruct; + +struct MyStruct { + pre : i32, + @align(${t.params.alignments[0]}) member_0 : ${memberTypes[0]}, + @align(${t.params.alignments[1]}) member_1 : ${memberTypes[1]}, + @align(${t.params.alignments[2]}) member_2 : ${memberTypes[2]}, + post : i32, +}; + +@workgroup_size(1) @compute +fn main() { +output = input.member_${t.params.member_index}; +} +`, + /* expected */[expected], + /* input */input, + /* inputSource */'storage_r' + ); +}); + +g.test('buffer_size'). +specURL('https://www.w3.org/TR/WGSL/#struct-access-expr'). +desc( + `Test accessing of a value structure in a storage buffer that has members using the @size attribute` +). +params((u) => +u. +beginSubcases(). +combine('member_index', [0, 1, 2]). +combine('sizes', [ +[4, 4, 4], +[4, 8, 16], +[8, 4, 16], +[8, 16, 4]] +) +). +fn(async (t) => { + const memberTypes = ['i32', 'u32', 'f32']; + const values = memberTypes.map((ty, i) => Type[ty].create(i)); + const expected = values[t.params.member_index]; + const input = new Uint8Array(64); + let offset = 4; // pre : i32 + for (let i = 0; i < 3; i++) { + offset = align(offset, values[i].type.alignment); + values[i].copyTo(input, offset); + offset += t.params.sizes[i]; + } + await run( + t, + ` +@group(0) @binding(0) var output : ${expected.type}; +@group(0) @binding(1) var input : MyStruct; + +struct MyStruct { + pre : i32, + @size(${t.params.sizes[0]}) member_0 : ${memberTypes[0]}, + @size(${t.params.sizes[1]}) member_1 : ${memberTypes[1]}, + @size(${t.params.sizes[2]}) member_2 : ${memberTypes[2]}, + post : i32, +}; + +@workgroup_size(1) @compute +fn main() { +output = input.member_${t.params.member_index}; +} +`, + /* expected */[expected], + /* input */input, + /* inputSource */'storage_r' + ); +}); + +g.test('buffer_pointer'). +specURL('https://www.w3.org/TR/WGSL/#struct-access-expr'). +desc(`Test accessing of a value structure via a pointer to a storage or uniform buffer`). +params((u) => +u. +combine('member_types', kMemberTypesNoBool). +combine('inputSource', ['uniform', 'storage']). +beginSubcases(). +expand('member_index', (t) => t.member_types.map((_, i) => i)) +). +beforeAllSubcases((t) => { + if (t.params.member_types.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const values = t.params.member_types.map((ty, i) => Type[ty].create(i)); + const expected = values[t.params.member_index]; + + await run( + t, + ` +${t.params.member_types.includes('f16') ? 'enable f16;' : ''} + +@group(0) @binding(0) var output : ${expected.type}; +@group(0) @binding(1) var<${t.params.inputSource}> input : MyStruct; + +struct MyStruct { + ${t.params.member_types.map((ty, i) => ` member_${i} : ${ty},`).join('\n')} +}; + +@workgroup_size(1) @compute +fn main() { + let ptr = &input; + output = (*ptr).member_${t.params.member_index}; +} +`, + /* expected */[expected], + /* input */values, + /* inputSource */t.params.inputSource === 'uniform' ? 'uniform' : 'storage_r' + ); +}); + +g.test('let'). +specURL('https://www.w3.org/TR/WGSL/#struct-access-expr'). +desc(`Test accessing of a let structure`). +params((u) => +u. +combine('member_types', kMemberTypes). +beginSubcases(). +expand('member_index', (t) => t.member_types.map((_, i) => i)) +). +beforeAllSubcases((t) => { + if (t.params.member_types.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const memberType = Type[t.params.member_types[t.params.member_index]]; + const values = t.params.member_types.map((ty, i) => Type[ty].create(i)); + const expected = + memberType === Type.bool ? + u32(values[t.params.member_index].value === true ? 1 : 0) : + values[t.params.member_index]; + + await run( + t, + ` +${t.params.member_types.includes('f16') ? 'enable f16;' : ''} + +@group(0) @binding(0) var output : ${expected.type}; + +struct MyStruct { + ${t.params.member_types.map((ty, i) => ` member_${i} : ${ty},`).join('\n')} +}; + +@workgroup_size(1) @compute +fn main() { + let s = MyStruct(${values.map((v) => v.wgsl()).join(', ')}); + let v = s.member_${t.params.member_index}; + output = ${memberType === Type.bool ? `select(0u, 1u, v)` : 'v'}; +} +`, + /* expected */[expected], + /* input */null, + /* inputSource */'const' + ); +}); + +g.test('param'). +specURL('https://www.w3.org/TR/WGSL/#struct-access-expr'). +desc(`Test accessing of a parameter structure`). +params((u) => +u. +combine('member_types', kMemberTypes). +beginSubcases(). +expand('member_index', (t) => t.member_types.map((_, i) => i)) +). +beforeAllSubcases((t) => { + if (t.params.member_types.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const memberType = Type[t.params.member_types[t.params.member_index]]; + const values = t.params.member_types.map((ty, i) => Type[ty].create(i)); + const expected = + memberType === Type.bool ? + u32(values[t.params.member_index].value === true ? 1 : 0) : + values[t.params.member_index]; + + await run( + t, + ` +${t.params.member_types.includes('f16') ? 'enable f16;' : ''} + +@group(0) @binding(0) var output : ${expected.type}; + +struct MyStruct { + ${t.params.member_types.map((ty, i) => ` member_${i} : ${ty},`).join('\n')} +}; + +fn f(s : MyStruct) -> ${t.params.member_types[t.params.member_index]} { + return s.member_${t.params.member_index}; +} + +@workgroup_size(1) @compute +fn main() { + let v = f(MyStruct(${values.map((v) => v.wgsl()).join(', ')})); + output = ${memberType === Type.bool ? `select(0u, 1u, v)` : 'v'}; +} +`, + /* expected */[expected], + /* input */null, + /* inputSource */'const' + ); +}); + +g.test('const'). +specURL('https://www.w3.org/TR/WGSL/#struct-access-expr'). +desc(`Test accessing of a const value structure`). +params((u) => +u. +combine('member_types', kMemberTypes). +beginSubcases(). +expand('member_index', (t) => t.member_types.map((_, i) => i)) +). +beforeAllSubcases((t) => { + if (t.params.member_types.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const memberType = Type[t.params.member_types[t.params.member_index]]; + const values = t.params.member_types.map((ty, i) => Type[ty].create(i)); + const expected = + memberType === Type.bool ? + u32(values[t.params.member_index].value === true ? 1 : 0) : + values[t.params.member_index]; + + await run( + t, + ` +${t.params.member_types.includes('f16') ? 'enable f16;' : ''} + +@group(0) @binding(0) var output : ${expected.type}; + +struct MyStruct { + ${t.params.member_types.map((ty, i) => ` member_${i} : ${ty},`).join('\n')} +}; + +const S = MyStruct(${values.map((v) => v.wgsl()).join(', ')}); + +@workgroup_size(1) @compute +fn main() { + let v = S.member_${t.params.member_index}; + output = ${memberType === Type.bool ? `select(0u, 1u, v)` : 'v'}; +} +`, + /* expected */[expected], + /* input */null, + /* inputSource */'const' + ); +}); + +g.test('const_nested'). +specURL('https://www.w3.org/TR/WGSL/#struct-access-expr'). +desc(`Test accessing of a const value structure nested in another structure`). +params((u) => +u. +combine('member_types', kMemberTypes). +beginSubcases(). +expand('member_index', (t) => t.member_types.map((_, i) => i)) +). +beforeAllSubcases((t) => { + if (t.params.member_types.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const memberType = Type[t.params.member_types[t.params.member_index]]; + const values = t.params.member_types.map((ty, i) => Type[ty].create(i)); + const expected = + memberType === Type.bool ? + u32(values[t.params.member_index].value === true ? 1 : 0) : + values[t.params.member_index]; + + await run( + t, + ` +${t.params.member_types.includes('f16') ? 'enable f16;' : ''} + +@group(0) @binding(0) var output : ${expected.type}; + +struct MyStruct { + ${t.params.member_types.map((ty, i) => ` member_${i} : ${ty},`).join('\n')} +}; + +struct Outer { + pre : i32, + inner : MyStruct, + post : i32, +} + +const S = Outer(10, MyStruct(${values.map((v) => v.wgsl()).join(', ')}), 20); + +@workgroup_size(1) @compute +fn main() { + let v = S.inner.member_${t.params.member_index}; + output = ${memberType === Type.bool ? `select(0u, 1u, v)` : 'v'}; +} +`, + /* expected */[expected], + /* input */null, + /* inputSource */'const' + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/vector/components.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/vector/components.spec.js new file mode 100644 index 0000000000..9a62033a25 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/vector/components.spec.js @@ -0,0 +1,118 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for vector component selection expressions +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { Type, VectorValue, f32 } from '../../../../../util/conversion.js'; +import { allInputSources, basicExpressionBuilder, run } from '../../expression.js'; + +export const g = makeTestGroup(GPUTest); + +/** @returns the full permutation of component indices used to component select a vector of width 'n' */ +function indices(n) { + const out = []; + for (let width = 1; width < n; width++) { + let generate = (swizzle) => { + out.push(swizzle); + }; + for (let i = 0; i < width; i++) { + const next = generate; + generate = (swizzle) => { + for (let j = 0; j < width; j++) { + next([...swizzle, j]); + } + }; + } + generate([]); + } + return out; +} + +g.test('concrete_scalar'). +specURL('https://www.w3.org/TR/WGSL/#vector-access-expr'). +desc(`Test vector component selection of concrete vectors`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('elementType', ['i32', 'u32', 'f32', 'f16', 'bool']). +combine('width', [2, 3, 4]). +combine('components', ['rgba', 'xyzw']). +beginSubcases(). +expand('indices', (u) => indices(u.width)) +). +beforeAllSubcases((t) => { + if (t.params.elementType === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.elementType]; + const vectorType = Type.vec(t.params.width, elementType); + const elementValues = + t.params.elementType === 'bool' ? (i) => i & 1 : (i) => (i + 1) * 10; + const elements = []; + for (let i = 0; i < t.params.width; i++) { + elements.push(elementType.create(elementValues(i))); + } + const result = (() => { + if (t.params.indices.length === 1) { + return { type: elementType, value: elementType.create(elementValues(0)) }; + } else { + const vec = Type.vec(t.params.indices.length, elementType); + return { type: vec, value: vec.create(t.params.indices.map((i) => elementValues(i))) }; + } + })(); + + const components = t.params.indices.map((i) => t.params.components[i]).join(''); + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}.${components}`), + [vectorType], + result.type, + t.params, + [{ input: [new VectorValue(elements)], expected: result.value }] + ); +}); + +g.test('abstract_scalar'). +specURL('https://www.w3.org/TR/WGSL/#vector-access-expr'). +desc(`Test vector component selection of abstract numeric vectors`). +params((u) => +u. +combine('elementType', ['abstract-int', 'abstract-float']). +combine('width', [2, 3, 4]). +combine('components', ['rgba', 'xyzw']). +beginSubcases(). +expand('indices', (u) => indices(u.width)) +). +fn(async (t) => { + const elementType = Type[t.params.elementType]; + const vectorType = Type.vec(t.params.width, elementType); + const elementValues = (i) => (i + 1) * 0x100000000; + const elements = []; + for (let i = 0; i < t.params.width; i++) { + elements.push(elementType.create(elementValues(i))); + } + const result = (() => { + if (t.params.indices.length === 1) { + return { type: Type.f32, value: f32(elementValues(0) / 0x100000000) }; + } else { + const vec = Type.vec(t.params.indices.length, Type.f32); + return { + type: vec, + value: vec.create(t.params.indices.map((i) => elementValues(i) / 0x100000000)) + }; + } + })(); + + const components = t.params.indices.map((i) => t.params.components[i]).join(''); + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}.${components} / 0x100000000`), + [vectorType], + result.type, + { inputSource: 'const' }, + [{ input: [new VectorValue(elements)], expected: result.value }] + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/vector/index.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/vector/index.spec.js new file mode 100644 index 0000000000..d969f543b6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/access/vector/index.spec.js @@ -0,0 +1,87 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for vector indexing expressions +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { Type, VectorValue, f32 } from '../../../../../util/conversion.js'; + +import { allInputSources, basicExpressionBuilder, run } from '../../expression.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('concrete_scalar'). +specURL('https://www.w3.org/TR/WGSL/#vector-access-expr'). +desc(`Test indexing of concrete vectors`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('elementType', ['i32', 'u32', 'f32', 'f16', 'bool']). +combine('indexType', ['i32', 'u32']). +combine('width', [2, 3, 4]) +). +beforeAllSubcases((t) => { + if (t.params.elementType === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.elementType]; + const indexType = Type[t.params.indexType]; + const vectorType = Type.vec(t.params.width, elementType); + const elements = []; + for (let i = 0; i < t.params.width; i++) { + if (t.params.elementType === 'bool') { + elements.push(elementType.create(i & 1)); + } else { + elements.push(elementType.create((i + 1) * 10)); + } + } + const vector = new VectorValue(elements); + const cases = []; + for (let i = 0; i < t.params.width; i++) { + cases.push({ input: [vector, indexType.create(i)], expected: elements[i] }); + } + + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}[${ops[1]}]`), + [vectorType, indexType], + elementType, + t.params, + cases + ); +}); + +g.test('abstract_scalar'). +specURL('https://www.w3.org/TR/WGSL/#vector-access-expr'). +desc(`Test indexing of abstract numeric vectors`). +params((u) => +u. +combine('elementType', ['abstract-int', 'abstract-float']). +combine('indexType', ['i32', 'u32']). +combine('width', [2, 3, 4]) +). +fn(async (t) => { + const elementType = Type[t.params.elementType]; + const indexType = Type[t.params.indexType]; + const vectorType = Type.vec(t.params.width, elementType); + const elements = []; + for (let i = 0; i < t.params.width; i++) { + elements.push(elementType.create((i + 1) * 0x100000000)); + } + const vector = new VectorValue(elements); + const cases = []; + for (let i = 0; i < t.params.width; i++) { + cases.push({ input: [vector, indexType.create(i)], expected: f32(i + 1) }); + } + + await run( + t, + basicExpressionBuilder((ops) => `${ops[0]}[${ops[1]}] / 0x100000000`), + [vectorType, indexType], + Type.f32, + { inputSource: 'const' }, + cases + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_addition.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_addition.cache.js new file mode 100644 index 0000000000..402fd1add8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_addition.cache.js @@ -0,0 +1,54 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF64Range, sparseVectorF64Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const additionVectorScalarInterval = (v, s) => { + return FP.abstract.toVector(v.map((e) => FP.abstract.additionInterval(e, s))); +}; + +const additionScalarVectorInterval = (s, v) => { + return FP.abstract.toVector(v.map((e) => FP.abstract.additionInterval(s, e))); +}; + +const scalar_cases = { + ['scalar']: () => { + return FP.abstract.generateScalarPairToIntervalCases( + sparseScalarF64Range(), + sparseScalarF64Range(), + 'finite', + FP.abstract.additionInterval + ); + } +}; + +const vector_scalar_cases = [2, 3, 4]. +map((dim) => ({ + [`vec${dim}_scalar`]: () => { + return FP.abstract.generateVectorScalarToVectorCases( + sparseVectorF64Range(dim), + sparseScalarF64Range(), + 'finite', + additionVectorScalarInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +map((dim) => ({ + [`scalar_vec${dim}`]: () => { + return FP.abstract.generateScalarVectorToVectorCases( + sparseScalarF64Range(), + sparseVectorF64Range(dim), + 'finite', + additionScalarVectorInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/af_addition', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_addition.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_addition.spec.js index c03c90b773..75fc6688c2 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_addition.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_addition.spec.js @@ -1,70 +1,17 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` -Execution Tests for non-matrix AbstractFloat addition expression +Execution Tests for non-matrix abstract-float addition expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF64Range, sparseVectorF64Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { onlyConstInputSource, run } from '../expression.js'; -import { abstractBinary } from './binary.js'; - -const additionVectorScalarInterval = (v, s) => { - return FP.abstract.toVector(v.map((e) => FP.abstract.additionInterval(e, s))); -}; - -const additionScalarVectorInterval = (s, v) => { - return FP.abstract.toVector(v.map((e) => FP.abstract.additionInterval(s, e))); -}; +import { d } from './af_addition.cache.js'; +import { abstractFloatBinary } from './binary.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = { - ['scalar']: () => { - return FP.abstract.generateScalarPairToIntervalCases( - sparseF64Range(), - sparseF64Range(), - 'finite', - FP.abstract.additionInterval - ); - } -}; - -const vector_scalar_cases = [2, 3, 4]. -map((dim) => ({ - [`vec${dim}_scalar`]: () => { - return FP.abstract.generateVectorScalarToVectorCases( - sparseVectorF64Range(dim), - sparseF64Range(), - 'finite', - additionVectorScalarInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -map((dim) => ({ - [`scalar_vec${dim}`]: () => { - return FP.abstract.generateScalarVectorToVectorCases( - sparseF64Range(), - sparseVectorF64Range(dim), - 'finite', - additionScalarVectorInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/af_addition', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -78,9 +25,9 @@ fn(async (t) => { const cases = await d.get('scalar'); await run( t, - abstractBinary('+'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBinary('+'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -101,9 +48,9 @@ fn(async (t) => { const cases = await d.get('scalar'); // Using vectorize to generate vector cases based on scalar cases await run( t, - abstractBinary('+'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBinary('+'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -123,9 +70,9 @@ fn(async (t) => { const cases = await d.get(`vec${dim}_scalar`); await run( t, - abstractBinary('+'), - [TypeVec(dim, TypeAbstractFloat), TypeAbstractFloat], - TypeVec(dim, TypeAbstractFloat), + abstractFloatBinary('+'), + [Type.vec(dim, Type.abstractFloat), Type.abstractFloat], + Type.vec(dim, Type.abstractFloat), t.params, cases ); @@ -145,9 +92,9 @@ fn(async (t) => { const cases = await d.get(`scalar_vec${dim}`); await run( t, - abstractBinary('+'), - [TypeAbstractFloat, TypeVec(dim, TypeAbstractFloat)], - TypeVec(dim, TypeAbstractFloat), + abstractFloatBinary('+'), + [Type.abstractFloat, Type.vec(dim, Type.abstractFloat)], + Type.vec(dim, Type.abstractFloat), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_comparison.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_comparison.cache.js new file mode 100644 index 0000000000..382c8f59dd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_comparison.cache.js @@ -0,0 +1,90 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { anyOf } from '../../../../util/compare.js';import { abstractFloat, bool } from '../../../../util/conversion.js';import { flushSubnormalNumberF64, vectorF64Range } from '../../../../util/math.js'; + +import { makeCaseCache } from '../case_cache.js'; + +/** + * @returns a test case for the provided left hand & right hand values and truth function. + * Handles quantization and subnormals. + */ +function makeCase( +lhs, +rhs, +truthFunc) +{ + // Subnormal float values may be flushed at any time. + // https://www.w3.org/TR/WGSL/#floating-point-evaluation + const af_lhs = abstractFloat(lhs); + const af_rhs = abstractFloat(rhs); + const lhs_options = new Set([af_lhs, abstractFloat(flushSubnormalNumberF64(lhs))]); + const rhs_options = new Set([af_rhs, abstractFloat(flushSubnormalNumberF64(rhs))]); + const expected = []; + lhs_options.forEach((l) => { + rhs_options.forEach((r) => { + const result = bool(truthFunc(l, r)); + if (!expected.includes(result)) { + expected.push(result); + } + }); + }); + + return { input: [af_lhs, af_rhs], expected: anyOf(...expected) }; +} + +export const d = makeCaseCache('binary/af_logical', { + equals: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value === rhs.value; + }; + + return vectorF64Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + not_equals: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value !== rhs.value; + }; + + return vectorF64Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + less_than: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value < rhs.value; + }; + + return vectorF64Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + less_equals: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value <= rhs.value; + }; + + return vectorF64Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + greater_than: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value > rhs.value; + }; + + return vectorF64Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + greater_equals: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value >= rhs.value; + }; + + return vectorF64Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_comparison.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_comparison.spec.js index 3d80b3ec6d..3b1033a26e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_comparison.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_comparison.spec.js @@ -1,110 +1,17 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` -Execution Tests for the AbstractFloat comparison operations +Execution Tests for the abstract-float comparison operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { anyOf } from '../../../../util/compare.js'; -import { - abstractFloat, - bool, - - TypeAbstractFloat, - TypeBool } from -'../../../../util/conversion.js'; -import { flushSubnormalNumberF64, vectorF64Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; +import { d } from './af_comparison.cache.js'; import { binary } from './binary.js'; export const g = makeTestGroup(GPUTest); -/** - * @returns a test case for the provided left hand & right hand values and truth function. - * Handles quantization and subnormals. - */ -function makeCase( -lhs, -rhs, -truthFunc) -{ - // Subnormal float values may be flushed at any time. - // https://www.w3.org/TR/WGSL/#floating-point-evaluation - const af_lhs = abstractFloat(lhs); - const af_rhs = abstractFloat(rhs); - const lhs_options = new Set([af_lhs, abstractFloat(flushSubnormalNumberF64(lhs))]); - const rhs_options = new Set([af_rhs, abstractFloat(flushSubnormalNumberF64(rhs))]); - const expected = []; - lhs_options.forEach((l) => { - rhs_options.forEach((r) => { - const result = bool(truthFunc(l, r)); - if (!expected.includes(result)) { - expected.push(result); - } - }); - }); - - return { input: [af_lhs, af_rhs], expected: anyOf(...expected) }; -} - -export const d = makeCaseCache('binary/af_logical', { - equals: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value === rhs.value; - }; - - return vectorF64Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - not_equals: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value !== rhs.value; - }; - - return vectorF64Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - less_than: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value < rhs.value; - }; - - return vectorF64Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - less_equals: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value <= rhs.value; - }; - - return vectorF64Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - greater_than: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value > rhs.value; - }; - - return vectorF64Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - greater_equals: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value >= rhs.value; - }; - - return vectorF64Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - } -}); - g.test('equals'). specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). desc( @@ -120,7 +27,14 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const cases = await d.get('equals'); - await run(t, binary('=='), [TypeAbstractFloat, TypeAbstractFloat], TypeBool, t.params, cases); + await run( + t, + binary('=='), + [Type.abstractFloat, Type.abstractFloat], + Type.bool, + t.params, + cases + ); }); g.test('not_equals'). @@ -138,7 +52,14 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const cases = await d.get('not_equals'); - await run(t, binary('!='), [TypeAbstractFloat, TypeAbstractFloat], TypeBool, t.params, cases); + await run( + t, + binary('!='), + [Type.abstractFloat, Type.abstractFloat], + Type.bool, + t.params, + cases + ); }); g.test('less_than'). @@ -156,7 +77,7 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const cases = await d.get('less_than'); - await run(t, binary('<'), [TypeAbstractFloat, TypeAbstractFloat], TypeBool, t.params, cases); + await run(t, binary('<'), [Type.abstractFloat, Type.abstractFloat], Type.bool, t.params, cases); }); g.test('less_equals'). @@ -174,7 +95,14 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const cases = await d.get('less_equals'); - await run(t, binary('<='), [TypeAbstractFloat, TypeAbstractFloat], TypeBool, t.params, cases); + await run( + t, + binary('<='), + [Type.abstractFloat, Type.abstractFloat], + Type.bool, + t.params, + cases + ); }); g.test('greater_than'). @@ -192,7 +120,7 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const cases = await d.get('greater_than'); - await run(t, binary('>'), [TypeAbstractFloat, TypeAbstractFloat], TypeBool, t.params, cases); + await run(t, binary('>'), [Type.abstractFloat, Type.abstractFloat], Type.bool, t.params, cases); }); g.test('greater_equals'). @@ -210,5 +138,12 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const cases = await d.get('greater_equals'); - await run(t, binary('>='), [TypeAbstractFloat, TypeAbstractFloat], TypeBool, t.params, cases); + await run( + t, + binary('>='), + [Type.abstractFloat, Type.abstractFloat], + Type.bool, + t.params, + cases + ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_division.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_division.cache.js new file mode 100644 index 0000000000..0eca9ce46c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_division.cache.js @@ -0,0 +1,57 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF64Range, sparseVectorF64Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const divisionVectorScalarInterval = (v, s) => { + // division has an ulp accuracy, so abstract is only expected to be as accurate as f32 + return FP.abstract.toVector(v.map((e) => FP.f32.divisionInterval(e, s))); +}; + +const divisionScalarVectorInterval = (s, v) => { + // division has an ulp accuracy, so abstract is only expected to be as accurate as f32 + return FP.abstract.toVector(v.map((e) => FP.f32.divisionInterval(s, e))); +}; + +const scalar_cases = { + ['scalar']: () => { + return FP.abstract.generateScalarPairToIntervalCases( + sparseScalarF64Range(), + sparseScalarF64Range(), + 'finite', + // division has an ulp accuracy, so abstract is only expected to be as accurate as f32 + FP.f32.divisionInterval + ); + } +}; + +const vector_scalar_cases = [2, 3, 4]. +map((dim) => ({ + [`vec${dim}_scalar`]: () => { + return FP.abstract.generateVectorScalarToVectorCases( + sparseVectorF64Range(dim), + sparseScalarF64Range(), + 'finite', + divisionVectorScalarInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +map((dim) => ({ + [`scalar_vec${dim}`]: () => { + return FP.abstract.generateScalarVectorToVectorCases( + sparseScalarF64Range(), + sparseVectorF64Range(dim), + 'finite', + divisionScalarVectorInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/af_division', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_division.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_division.spec.js index 34d5d7b836..495706ef5d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_division.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_division.spec.js @@ -1,70 +1,17 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` -Execution Tests for non-matrix AbstractFloat division expression +Execution Tests for non-matrix abstract-float division expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF64Range, sparseVectorF64Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { onlyConstInputSource, run } from '../expression.js'; -import { abstractBinary } from './binary.js'; - -const divisionVectorScalarInterval = (v, s) => { - return FP.abstract.toVector(v.map((e) => FP.abstract.divisionInterval(e, s))); -}; - -const divisionScalarVectorInterval = (s, v) => { - return FP.abstract.toVector(v.map((e) => FP.abstract.divisionInterval(s, e))); -}; +import { d } from './af_division.cache.js'; +import { abstractFloatBinary } from './binary.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = { - ['scalar']: () => { - return FP.abstract.generateScalarPairToIntervalCases( - sparseF64Range(), - sparseF64Range(), - 'finite', - FP.abstract.divisionInterval - ); - } -}; - -const vector_scalar_cases = [2, 3, 4]. -map((dim) => ({ - [`vec${dim}_scalar`]: () => { - return FP.abstract.generateVectorScalarToVectorCases( - sparseVectorF64Range(dim), - sparseF64Range(), - 'finite', - divisionVectorScalarInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -map((dim) => ({ - [`scalar_vec${dim}`]: () => { - return FP.abstract.generateScalarVectorToVectorCases( - sparseF64Range(), - sparseVectorF64Range(dim), - 'finite', - divisionScalarVectorInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/af_division', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -78,9 +25,9 @@ fn(async (t) => { const cases = await d.get('scalar'); await run( t, - abstractBinary('/'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBinary('/'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -101,9 +48,9 @@ fn(async (t) => { const cases = await d.get('scalar'); // Using vectorize to generate vector cases based on scalar cases await run( t, - abstractBinary('/'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBinary('/'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -123,9 +70,9 @@ fn(async (t) => { const cases = await d.get(`vec${dim}_scalar`); await run( t, - abstractBinary('/'), - [TypeVec(dim, TypeAbstractFloat), TypeAbstractFloat], - TypeVec(dim, TypeAbstractFloat), + abstractFloatBinary('/'), + [Type.vec(dim, Type.abstractFloat), Type.abstractFloat], + Type.vec(dim, Type.abstractFloat), t.params, cases ); @@ -145,9 +92,9 @@ fn(async (t) => { const cases = await d.get(`scalar_vec${dim}`); await run( t, - abstractBinary('/'), - [TypeAbstractFloat, TypeVec(dim, TypeAbstractFloat)], - TypeVec(dim, TypeAbstractFloat), + abstractFloatBinary('/'), + [Type.abstractFloat, Type.vec(dim, Type.abstractFloat)], + Type.vec(dim, Type.abstractFloat), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_addition.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_addition.cache.js new file mode 100644 index 0000000000..18fe33ac5e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_addition.cache.js @@ -0,0 +1,26 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF64Range } from '../../../../util/math.js';import { selectNCases } from '../case.js'; +import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR +const mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].map((rows) => ({ + [`mat${cols}x${rows}`]: () => { + return selectNCases( + 'binary/af_matrix_addition', + 50, + FP.abstract.generateMatrixPairToMatrixCases( + sparseMatrixF64Range(cols, rows), + sparseMatrixF64Range(cols, rows), + 'finite', + FP.abstract.additionMatrixMatrixInterval + ) + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/af_matrix_addition', mat_cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_addition.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_addition.spec.js index 6fc50ca540..132fe4244e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_addition.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_addition.spec.js @@ -1,37 +1,17 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` -Execution Tests for matrix AbstractFloat addition expressions +Execution Tests for matrix abstract-float addition expressions `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeMat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseMatrixF64Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { onlyConstInputSource, run } from '../expression.js'; -import { abstractBinary } from './binary.js'; +import { d } from './af_matrix_addition.cache.js'; +import { abstractFloatBinary } from './binary.js'; export const g = makeTestGroup(GPUTest); -// Cases: matCxR -const mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].map((rows) => ({ - [`mat${cols}x${rows}`]: () => { - return FP.abstract.generateMatrixPairToMatrixCases( - sparseMatrixF64Range(cols, rows), - sparseMatrixF64Range(cols, rows), - 'finite', - FP.abstract.additionMatrixMatrixInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/af_matrix_addition', mat_cases); - g.test('matrix'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -52,9 +32,9 @@ fn(async (t) => { const cases = await d.get(`mat${cols}x${rows}`); await run( t, - abstractBinary('+'), - [TypeMat(cols, rows, TypeAbstractFloat), TypeMat(cols, rows, TypeAbstractFloat)], - TypeMat(cols, rows, TypeAbstractFloat), + abstractFloatBinary('+'), + [Type.mat(cols, rows, Type.abstractFloat), Type.mat(cols, rows, Type.abstractFloat)], + Type.mat(cols, rows, Type.abstractFloat), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication.cache.js new file mode 100644 index 0000000000..a313cea992 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication.cache.js @@ -0,0 +1,29 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF64Range } from '../../../../util/math.js';import { selectNCases } from '../case.js'; +import { makeCaseCache } from '../case_cache.js'; + +// Cases: matKxR_matCxK +const mat_mat_cases = [2, 3, 4]. +flatMap((k) => +[2, 3, 4].flatMap((cols) => +[2, 3, 4].map((rows) => ({ + [`mat${k}x${rows}_mat${cols}x${k}`]: () => { + return selectNCases( + 'binary/af_matrix_matrix_multiplication', + 10, + FP.abstract.generateMatrixPairToMatrixCases( + sparseMatrixF64Range(k, rows), + sparseMatrixF64Range(cols, k), + 'finite', + // Matrix-matrix multiplication has an inherited accuracy, so abstract is only expected to be as accurate as f32 + FP.f32.multiplicationMatrixMatrixInterval + ) + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/af_matrix_matrix_multiplication', mat_mat_cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication.spec.js new file mode 100644 index 0000000000..27889a2a4f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_matrix_multiplication.spec.js @@ -0,0 +1,45 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for matrix-matrix AbstractFloat multiplication expression +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { Type } from '../../../../util/conversion.js'; +import { onlyConstInputSource, run } from '../expression.js'; + +import { d } from './af_matrix_matrix_multiplication.cache.js'; +import { abstractFloatBinary } from './binary.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('matrix_matrix'). +specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). +desc( + ` +Expression: x * y, where x is a matrix and y is a matrix +Accuracy: Correctly rounded +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('common_dim', [2, 3, 4]). +combine('x_rows', [2, 3, 4]). +combine('y_cols', [2, 3, 4]) +). +fn(async (t) => { + const x_cols = t.params.common_dim; + const x_rows = t.params.x_rows; + const y_cols = t.params.y_cols; + const y_rows = t.params.common_dim; + + const cases = await d.get(`mat${x_cols}x${x_rows}_mat${y_cols}x${y_rows}`); + await run( + t, + abstractFloatBinary('*'), + [Type.mat(x_cols, x_rows, Type.abstractFloat), Type.mat(y_cols, y_rows, Type.abstractFloat)], + Type.mat(y_cols, x_rows, Type.abstractFloat), + t.params, + cases + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication.cache.js new file mode 100644 index 0000000000..db049bd26b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication.cache.js @@ -0,0 +1,49 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF64Range, sparseScalarF64Range } from '../../../../util/math.js';import { selectNCases } from '../case.js'; +import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR_scalar +const mat_scalar_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].map((rows) => ({ + [`mat${cols}x${rows}_scalar`]: () => { + return selectNCases( + 'binary/af_matrix_scalar_multiplication_mat_scalar', + 50, + FP.abstract.generateMatrixScalarToMatrixCases( + sparseMatrixF64Range(cols, rows), + sparseScalarF64Range(), + 'finite', + FP.abstract.multiplicationMatrixScalarInterval + ) + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: scalar_matCxR +const scalar_mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].map((rows) => ({ + [`scalar_mat${cols}x${rows}`]: () => { + return selectNCases( + 'binary/af_matrix_scalar_multiplication_scalar_mat', + 50, + FP.abstract.generateScalarMatrixToMatrixCases( + sparseScalarF64Range(), + sparseMatrixF64Range(cols, rows), + 'finite', + FP.abstract.multiplicationScalarMatrixInterval + ) + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/af_matrix_scalar_multiplication', { + ...mat_scalar_cases, + ...scalar_mat_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication.spec.js new file mode 100644 index 0000000000..78b2b4bcf8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_scalar_multiplication.spec.js @@ -0,0 +1,69 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for matrix-scalar and scalar-matrix AbstractFloat multiplication expression +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { Type } from '../../../../util/conversion.js'; +import { onlyConstInputSource, run } from '../expression.js'; + +import { d } from './af_matrix_scalar_multiplication.cache.js'; +import { abstractFloatBinary } from './binary.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('matrix_scalar'). +specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). +desc( + ` +Expression: x * y, where x is a matrix and y is a scalar +Accuracy: Correctly rounded +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('cols', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +fn(async (t) => { + const cols = t.params.cols; + const rows = t.params.rows; + const cases = await d.get(`mat${cols}x${rows}_scalar`); + await run( + t, + abstractFloatBinary('*'), + [Type.mat(cols, rows, Type.abstractFloat), Type.abstractFloat], + Type.mat(cols, rows, Type.abstractFloat), + t.params, + cases + ); +}); + +g.test('scalar_matrix'). +specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). +desc( + ` +Expression: x * y, where x is a scalar and y is a matrix +Accuracy: Correctly rounded +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('cols', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +fn(async (t) => { + const cols = t.params.cols; + const rows = t.params.rows; + const cases = await d.get(`scalar_mat${cols}x${rows}`); + await run( + t, + abstractFloatBinary('*'), + [Type.abstractFloat, Type.mat(cols, rows, Type.abstractFloat)], + Type.mat(cols, rows, Type.abstractFloat), + t.params, + cases + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_subtraction.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_subtraction.cache.js new file mode 100644 index 0000000000..ca10c79ad1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_subtraction.cache.js @@ -0,0 +1,26 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF64Range } from '../../../../util/math.js';import { selectNCases } from '../case.js'; +import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR +const mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].map((rows) => ({ + [`mat${cols}x${rows}`]: () => { + return selectNCases( + 'binary/af_matrix_subtraction', + 50, + FP.abstract.generateMatrixPairToMatrixCases( + sparseMatrixF64Range(cols, rows), + sparseMatrixF64Range(cols, rows), + 'finite', + FP.abstract.subtractionMatrixMatrixInterval + ) + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/af_matrix_subtraction', mat_cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_subtraction.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_subtraction.spec.js index 09dbcdf692..5a0f0ff8ff 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_subtraction.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_subtraction.spec.js @@ -1,37 +1,17 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` -Execution Tests for matrix AbstractFloat subtraction expression +Execution Tests for matrix abstract-float subtraction expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeMat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseMatrixF64Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { onlyConstInputSource, run } from '../expression.js'; -import { abstractBinary } from './binary.js'; +import { d } from './af_matrix_subtraction.cache.js'; +import { abstractFloatBinary } from './binary.js'; export const g = makeTestGroup(GPUTest); -// Cases: matCxR -const mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].map((rows) => ({ - [`mat${cols}x${rows}`]: () => { - return FP.abstract.generateMatrixPairToMatrixCases( - sparseMatrixF64Range(cols, rows), - sparseMatrixF64Range(cols, rows), - 'finite', - FP.abstract.subtractionMatrixMatrixInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/af_matrix_subtraction', mat_cases); - g.test('matrix'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -52,9 +32,9 @@ fn(async (t) => { const cases = await d.get(`mat${cols}x${rows}`); await run( t, - abstractBinary('-'), - [TypeMat(cols, rows, TypeAbstractFloat), TypeMat(cols, rows, TypeAbstractFloat)], - TypeMat(cols, rows, TypeAbstractFloat), + abstractFloatBinary('-'), + [Type.mat(cols, rows, Type.abstractFloat), Type.mat(cols, rows, Type.abstractFloat)], + Type.mat(cols, rows, Type.abstractFloat), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication.cache.js new file mode 100644 index 0000000000..9f2124652c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication.cache.js @@ -0,0 +1,51 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF64Range, sparseVectorF64Range } from '../../../../util/math.js';import { selectNCases } from '../case.js'; +import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR_vecC +const mat_vec_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].map((rows) => ({ + [`mat${cols}x${rows}_vec${cols}`]: () => { + return selectNCases( + 'binary/af_matrix_vector_multiplication_mat_vec', + 50, + FP.abstract.generateMatrixVectorToVectorCases( + sparseMatrixF64Range(cols, rows), + sparseVectorF64Range(cols), + 'finite', + // Matrix-vector multiplication has an inherited accuracy, so abstract is only expected to be as accurate as f32 + FP.f32.multiplicationMatrixVectorInterval + ) + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: vecR_matCxR +const vec_mat_cases = [2, 3, 4]. +flatMap((rows) => +[2, 3, 4].map((cols) => ({ + [`vec${rows}_mat${cols}x${rows}`]: () => { + return selectNCases( + 'binary/af_matrix_vector_multiplication_vec_mat', + 50, + FP.abstract.generateVectorMatrixToVectorCases( + sparseVectorF64Range(rows), + sparseMatrixF64Range(cols, rows), + 'finite', + // Vector-matrix multiplication has an inherited accuracy, so abstract is only expected to be as accurate as f32 + FP.f32.multiplicationVectorMatrixInterval + ) + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/af_matrix_vector_multiplication', { + ...mat_vec_cases, + ...vec_mat_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication.spec.js new file mode 100644 index 0000000000..9ae17ce0cc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_matrix_vector_multiplication.spec.js @@ -0,0 +1,69 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for matrix-vector and vector-matrix AbstractFloat multiplication expression +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { Type } from '../../../../util/conversion.js'; +import { onlyConstInputSource, run } from '../expression.js'; + +import { d } from './af_matrix_vector_multiplication.cache.js'; +import { abstractFloatBinary } from './binary.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('matrix_vector'). +specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). +desc( + ` +Expression: x * y, where x is a matrix and y is a vector +Accuracy: Correctly rounded +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('cols', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +fn(async (t) => { + const cols = t.params.cols; + const rows = t.params.rows; + const cases = await d.get(`mat${cols}x${rows}_vec${cols}`); + await run( + t, + abstractFloatBinary('*'), + [Type.mat(cols, rows, Type.abstractFloat), Type.vec(cols, Type.abstractFloat)], + Type.vec(rows, Type.abstractFloat), + t.params, + cases + ); +}); + +g.test('vector_matrix'). +specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). +desc( + ` +Expression: x * y, where x is a vector and y is is a matrix +Accuracy: Correctly rounded +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('cols', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +fn(async (t) => { + const cols = t.params.cols; + const rows = t.params.rows; + const cases = await d.get(`vec${rows}_mat${cols}x${rows}`); + await run( + t, + abstractFloatBinary('*'), + [Type.vec(rows, Type.abstractFloat), Type.mat(cols, rows, Type.abstractFloat)], + Type.vec(cols, Type.abstractFloat), + t.params, + cases + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_multiplication.cache.js new file mode 100644 index 0000000000..210aab7752 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_multiplication.cache.js @@ -0,0 +1,54 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF64Range, sparseVectorF64Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const multiplicationVectorScalarInterval = (v, s) => { + return FP.abstract.toVector(v.map((e) => FP.abstract.multiplicationInterval(e, s))); +}; + +const multiplicationScalarVectorInterval = (s, v) => { + return FP.abstract.toVector(v.map((e) => FP.abstract.multiplicationInterval(s, e))); +}; + +const scalar_cases = { + ['scalar']: () => { + return FP.abstract.generateScalarPairToIntervalCases( + sparseScalarF64Range(), + sparseScalarF64Range(), + 'finite', + FP.abstract.multiplicationInterval + ); + } +}; + +const vector_scalar_cases = [2, 3, 4]. +map((dim) => ({ + [`vec${dim}_scalar`]: () => { + return FP.abstract.generateVectorScalarToVectorCases( + sparseVectorF64Range(dim), + sparseScalarF64Range(), + 'finite', + multiplicationVectorScalarInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +map((dim) => ({ + [`scalar_vec${dim}`]: () => { + return FP.abstract.generateScalarVectorToVectorCases( + sparseScalarF64Range(), + sparseVectorF64Range(dim), + 'finite', + multiplicationScalarVectorInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/af_multiplication', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_multiplication.spec.js index 6f8cc65f4e..9a5f7bdb0d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_multiplication.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_multiplication.spec.js @@ -1,70 +1,17 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` -Execution Tests for non-matrix AbstractFloat multiplication expression +Execution Tests for non-matrix abstract-float multiplication expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF64Range, sparseVectorF64Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { onlyConstInputSource, run } from '../expression.js'; -import { abstractBinary } from './binary.js'; - -const multiplicationVectorScalarInterval = (v, s) => { - return FP.abstract.toVector(v.map((e) => FP.abstract.multiplicationInterval(e, s))); -}; - -const multiplicationScalarVectorInterval = (s, v) => { - return FP.abstract.toVector(v.map((e) => FP.abstract.multiplicationInterval(s, e))); -}; +import { d } from './af_multiplication.cache.js'; +import { abstractFloatBinary } from './binary.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = { - ['scalar']: () => { - return FP.abstract.generateScalarPairToIntervalCases( - sparseF64Range(), - sparseF64Range(), - 'finite', - FP.abstract.multiplicationInterval - ); - } -}; - -const vector_scalar_cases = [2, 3, 4]. -map((dim) => ({ - [`vec${dim}_scalar`]: () => { - return FP.abstract.generateVectorScalarToVectorCases( - sparseVectorF64Range(dim), - sparseF64Range(), - 'finite', - multiplicationVectorScalarInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -map((dim) => ({ - [`scalar_vec${dim}`]: () => { - return FP.abstract.generateScalarVectorToVectorCases( - sparseF64Range(), - sparseVectorF64Range(dim), - 'finite', - multiplicationScalarVectorInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/af_multiplication', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -78,9 +25,9 @@ fn(async (t) => { const cases = await d.get('scalar'); await run( t, - abstractBinary('*'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBinary('*'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -101,9 +48,9 @@ fn(async (t) => { const cases = await d.get('scalar'); // Using vectorize to generate vector cases based on scalar cases await run( t, - abstractBinary('*'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBinary('*'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -123,9 +70,9 @@ fn(async (t) => { const cases = await d.get(`vec${dim}_scalar`); await run( t, - abstractBinary('*'), - [TypeVec(dim, TypeAbstractFloat), TypeAbstractFloat], - TypeVec(dim, TypeAbstractFloat), + abstractFloatBinary('*'), + [Type.vec(dim, Type.abstractFloat), Type.abstractFloat], + Type.vec(dim, Type.abstractFloat), t.params, cases ); @@ -145,9 +92,9 @@ fn(async (t) => { const cases = await d.get(`scalar_vec${dim}`); await run( t, - abstractBinary('*'), - [TypeAbstractFloat, TypeVec(dim, TypeAbstractFloat)], - TypeVec(dim, TypeAbstractFloat), + abstractFloatBinary('*'), + [Type.abstractFloat, Type.vec(dim, Type.abstractFloat)], + Type.vec(dim, Type.abstractFloat), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_remainder.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_remainder.cache.js new file mode 100644 index 0000000000..e0e3453553 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_remainder.cache.js @@ -0,0 +1,57 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF64Range, sparseVectorF64Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const remainderVectorScalarInterval = (v, s) => { + // remainder has an inherited accuracy, so abstract is only expected to be as accurate as f32 + return FP.abstract.toVector(v.map((e) => FP.f32.remainderInterval(e, s))); +}; + +const remainderScalarVectorInterval = (s, v) => { + // remainder has an inherited accuracy, so abstract is only expected to be as accurate as f32 + return FP.abstract.toVector(v.map((e) => FP.f32.remainderInterval(s, e))); +}; + +const scalar_cases = { + ['scalar']: () => { + return FP.abstract.generateScalarPairToIntervalCases( + sparseScalarF64Range(), + sparseScalarF64Range(), + 'finite', + // remainder has an inherited accuracy, so abstract is only expected to be as accurate as f32 + FP.f32.remainderInterval + ); + } +}; + +const vector_scalar_cases = [2, 3, 4]. +map((dim) => ({ + [`vec${dim}_scalar`]: () => { + return FP.abstract.generateVectorScalarToVectorCases( + sparseVectorF64Range(dim), + sparseScalarF64Range(), + 'finite', + remainderVectorScalarInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +map((dim) => ({ + [`scalar_vec${dim}`]: () => { + return FP.abstract.generateScalarVectorToVectorCases( + sparseScalarF64Range(), + sparseVectorF64Range(dim), + 'finite', + remainderScalarVectorInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/af_remainder', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_remainder.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_remainder.spec.js index cbb45f45c6..7cbeda971c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_remainder.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_remainder.spec.js @@ -4,67 +4,14 @@ Execution Tests for non-matrix abstract float remainder expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF64Range, sparseVectorF64Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { onlyConstInputSource, run } from '../expression.js'; -import { abstractBinary } from './binary.js'; - -const remainderVectorScalarInterval = (v, s) => { - return FP.abstract.toVector(v.map((e) => FP.abstract.remainderInterval(e, s))); -}; - -const remainderScalarVectorInterval = (s, v) => { - return FP.abstract.toVector(v.map((e) => FP.abstract.remainderInterval(s, e))); -}; +import { d } from './af_remainder.cache.js'; +import { abstractFloatBinary } from './binary.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = { - ['scalar']: () => { - return FP.abstract.generateScalarPairToIntervalCases( - sparseF64Range(), - sparseF64Range(), - 'finite', - FP.abstract.remainderInterval - ); - } -}; - -const vector_scalar_cases = [2, 3, 4]. -map((dim) => ({ - [`vec${dim}_scalar`]: () => { - return FP.abstract.generateVectorScalarToVectorCases( - sparseVectorF64Range(dim), - sparseF64Range(), - 'finite', - remainderVectorScalarInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -map((dim) => ({ - [`scalar_vec${dim}`]: () => { - return FP.abstract.generateScalarVectorToVectorCases( - sparseF64Range(), - sparseVectorF64Range(dim), - 'finite', - remainderScalarVectorInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/af_remainder', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -78,9 +25,9 @@ fn(async (t) => { const cases = await d.get('scalar'); await run( t, - abstractBinary('%'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBinary('%'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -101,9 +48,9 @@ fn(async (t) => { const cases = await d.get('scalar'); // Using vectorize to generate vector cases based on scalar cases await run( t, - abstractBinary('%'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBinary('%'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -123,9 +70,9 @@ fn(async (t) => { const cases = await d.get(`vec${dim}_scalar`); await run( t, - abstractBinary('%'), - [TypeVec(dim, TypeAbstractFloat), TypeAbstractFloat], - TypeVec(dim, TypeAbstractFloat), + abstractFloatBinary('%'), + [Type.vec(dim, Type.abstractFloat), Type.abstractFloat], + Type.vec(dim, Type.abstractFloat), t.params, cases ); @@ -145,9 +92,9 @@ fn(async (t) => { const cases = await d.get(`scalar_vec${dim}`); await run( t, - abstractBinary('%'), - [TypeAbstractFloat, TypeVec(dim, TypeAbstractFloat)], - TypeVec(dim, TypeAbstractFloat), + abstractFloatBinary('%'), + [Type.abstractFloat, Type.vec(dim, Type.abstractFloat)], + Type.vec(dim, Type.abstractFloat), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_subtraction.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_subtraction.cache.js new file mode 100644 index 0000000000..ea2adc302f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_subtraction.cache.js @@ -0,0 +1,54 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF64Range, sparseVectorF64Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const subtractionVectorScalarInterval = (v, s) => { + return FP.abstract.toVector(v.map((e) => FP.abstract.subtractionInterval(e, s))); +}; + +const subtractionScalarVectorInterval = (s, v) => { + return FP.abstract.toVector(v.map((e) => FP.abstract.subtractionInterval(s, e))); +}; + +const scalar_cases = { + ['scalar']: () => { + return FP.abstract.generateScalarPairToIntervalCases( + sparseScalarF64Range(), + sparseScalarF64Range(), + 'finite', + FP.abstract.subtractionInterval + ); + } +}; + +const vector_scalar_cases = [2, 3, 4]. +map((dim) => ({ + [`vec${dim}_scalar`]: () => { + return FP.abstract.generateVectorScalarToVectorCases( + sparseVectorF64Range(dim), + sparseScalarF64Range(), + 'finite', + subtractionVectorScalarInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +map((dim) => ({ + [`scalar_vec${dim}`]: () => { + return FP.abstract.generateScalarVectorToVectorCases( + sparseScalarF64Range(), + sparseVectorF64Range(dim), + 'finite', + subtractionScalarVectorInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/af_subtraction', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_subtraction.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_subtraction.spec.js index 0782cf61be..a3cdd89f21 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_subtraction.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/af_subtraction.spec.js @@ -1,70 +1,17 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` -Execution Tests for non-matrix AbstractFloat subtraction expression +Execution Tests for non-matrix abstract-float subtraction expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF64Range, sparseVectorF64Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { onlyConstInputSource, run } from '../expression.js'; -import { abstractBinary } from './binary.js'; - -const subtractionVectorScalarInterval = (v, s) => { - return FP.abstract.toVector(v.map((e) => FP.abstract.subtractionInterval(e, s))); -}; - -const subtractionScalarVectorInterval = (s, v) => { - return FP.abstract.toVector(v.map((e) => FP.abstract.subtractionInterval(s, e))); -}; +import { d } from './af_subtraction.cache.js'; +import { abstractFloatBinary } from './binary.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = { - ['scalar']: () => { - return FP.abstract.generateScalarPairToIntervalCases( - sparseF64Range(), - sparseF64Range(), - 'finite', - FP.abstract.subtractionInterval - ); - } -}; - -const vector_scalar_cases = [2, 3, 4]. -map((dim) => ({ - [`vec${dim}_scalar`]: () => { - return FP.abstract.generateVectorScalarToVectorCases( - sparseVectorF64Range(dim), - sparseF64Range(), - 'finite', - subtractionVectorScalarInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -map((dim) => ({ - [`scalar_vec${dim}`]: () => { - return FP.abstract.generateScalarVectorToVectorCases( - sparseF64Range(), - sparseVectorF64Range(dim), - 'finite', - subtractionScalarVectorInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/af_subtraction', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -78,9 +25,9 @@ fn(async (t) => { const cases = await d.get('scalar'); await run( t, - abstractBinary('-'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBinary('-'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -101,9 +48,9 @@ fn(async (t) => { const cases = await d.get('scalar'); // Using vectorize to generate vector cases based on scalar cases await run( t, - abstractBinary('-'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBinary('-'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -123,9 +70,9 @@ fn(async (t) => { const cases = await d.get(`vec${dim}_scalar`); await run( t, - abstractBinary('-'), - [TypeVec(dim, TypeAbstractFloat), TypeAbstractFloat], - TypeVec(dim, TypeAbstractFloat), + abstractFloatBinary('-'), + [Type.vec(dim, Type.abstractFloat), Type.abstractFloat], + Type.vec(dim, Type.abstractFloat), t.params, cases ); @@ -145,9 +92,9 @@ fn(async (t) => { const cases = await d.get(`scalar_vec${dim}`); await run( t, - abstractBinary('-'), - [TypeAbstractFloat, TypeVec(dim, TypeAbstractFloat)], - TypeVec(dim, TypeAbstractFloat), + abstractFloatBinary('-'), + [Type.abstractFloat, Type.vec(dim, Type.abstractFloat)], + Type.vec(dim, Type.abstractFloat), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_arithmetic.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_arithmetic.cache.js new file mode 100644 index 0000000000..af9ec7ac62 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_arithmetic.cache.js @@ -0,0 +1,145 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kValue } from '../../../../util/constants.js';import { sparseI64Range, vectorI64Range } from '../../../../util/math.js';import { + generateBinaryToI64Cases, + generateI64VectorBinaryToVectorCases, + generateVectorI64BinaryToVectorCases } from +'../case.js'; +import { makeCaseCache } from '../case_cache.js'; + +function ai_add(x, y) { + const result = x + y; + return !kValue.i64.isOOB(result) ? result : undefined; +} + +function ai_div(x, y) { + if (y === 0n) return undefined; + if (x === kValue.i64.negative.min && y === -1n) return undefined; + const result = x / y; + return !kValue.i64.isOOB(result) ? result : undefined; +} + +function ai_mul(x, y) { + const result = x * y; + return !kValue.i64.isOOB(result) ? result : undefined; +} + +function ai_rem(x, y) { + if (y === 0n) return undefined; + if (x === kValue.i64.negative.min && y === -1n) return undefined; + const result = x % y; + return !kValue.i64.isOOB(result) ? result : undefined; +} + +function ai_sub(x, y) { + const result = x - y; + return !kValue.i64.isOOB(result) ? result : undefined; +} + +export const d = makeCaseCache('binary/ai_arithmetic', { + addition: () => { + return generateBinaryToI64Cases(sparseI64Range(), sparseI64Range(), ai_add); + }, + addition_scalar_vector2: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(2), ai_add); + }, + addition_scalar_vector3: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(3), ai_add); + }, + addition_scalar_vector4: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(4), ai_add); + }, + addition_vector2_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(2), sparseI64Range(), ai_add); + }, + addition_vector3_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(3), sparseI64Range(), ai_add); + }, + addition_vector4_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(4), sparseI64Range(), ai_add); + }, + division: () => { + return generateBinaryToI64Cases(sparseI64Range(), sparseI64Range(), ai_div); + }, + division_scalar_vector2: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(2), ai_div); + }, + division_scalar_vector3: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(3), ai_div); + }, + division_scalar_vector4: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(4), ai_div); + }, + division_vector2_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(2), sparseI64Range(), ai_div); + }, + division_vector3_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(3), sparseI64Range(), ai_div); + }, + division_vector4_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(4), sparseI64Range(), ai_div); + }, + multiplication: () => { + return generateBinaryToI64Cases(sparseI64Range(), sparseI64Range(), ai_mul); + }, + multiplication_scalar_vector2: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(2), ai_mul); + }, + multiplication_scalar_vector3: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(3), ai_mul); + }, + multiplication_scalar_vector4: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(4), ai_mul); + }, + multiplication_vector2_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(2), sparseI64Range(), ai_mul); + }, + multiplication_vector3_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(3), sparseI64Range(), ai_mul); + }, + multiplication_vector4_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(4), sparseI64Range(), ai_mul); + }, + remainder: () => { + return generateBinaryToI64Cases(sparseI64Range(), sparseI64Range(), ai_rem); + }, + remainder_scalar_vector2: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(2), ai_rem); + }, + remainder_scalar_vector3: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(3), ai_rem); + }, + remainder_scalar_vector4: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(4), ai_rem); + }, + remainder_vector2_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(2), sparseI64Range(), ai_rem); + }, + remainder_vector3_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(3), sparseI64Range(), ai_rem); + }, + remainder_vector4_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(4), sparseI64Range(), ai_rem); + }, + subtraction: () => { + return generateBinaryToI64Cases(sparseI64Range(), sparseI64Range(), ai_sub); + }, + subtraction_scalar_vector2: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(2), ai_sub); + }, + subtraction_scalar_vector3: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(3), ai_sub); + }, + subtraction_scalar_vector4: () => { + return generateI64VectorBinaryToVectorCases(sparseI64Range(), vectorI64Range(4), ai_sub); + }, + subtraction_vector2_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(2), sparseI64Range(), ai_sub); + }, + subtraction_vector3_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(3), sparseI64Range(), ai_sub); + }, + subtraction_vector4_scalar: () => { + return generateVectorI64BinaryToVectorCases(vectorI64Range(4), sparseI64Range(), ai_sub); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_arithmetic.spec.js new file mode 100644 index 0000000000..ae85bd2d6f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_arithmetic.spec.js @@ -0,0 +1,303 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for the abstract int arithmetic binary expression operations +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { Type } from '../../../../util/conversion.js'; +import { onlyConstInputSource, run } from '../expression.js'; + +import { d } from './ai_arithmetic.cache.js'; +import { abstractIntBinary } from './binary.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('addition'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x + y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = await d.get('addition'); + await run( + t, + abstractIntBinary('+'), + [Type.abstractInt, Type.abstractInt], + Type.abstractInt, + t.params, + cases + ); +}); + +g.test('addition_scalar_vector'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x + y +` +). +params((u) => +u.combine('inputSource', onlyConstInputSource).combine('vectorize_rhs', [2, 3, 4]) +). +fn(async (t) => { + const vec_size = t.params.vectorize_rhs; + const vec_type = Type.vec(vec_size, Type.abstractInt); + const cases = await d.get(`addition_scalar_vector${vec_size}`); + await run(t, abstractIntBinary('+'), [Type.abstractInt, vec_type], vec_type, t.params, cases); +}); + +g.test('addition_vector_scalar'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x + y +` +). +params((u) => +u.combine('inputSource', onlyConstInputSource).combine('vectorize_lhs', [2, 3, 4]) +). +fn(async (t) => { + const vec_size = t.params.vectorize_lhs; + const vec_type = Type.vec(vec_size, Type.abstractInt); + const cases = await d.get(`addition_vector${vec_size}_scalar`); + await run(t, abstractIntBinary('+'), [vec_type, Type.abstractInt], vec_type, t.params, cases); +}); + +g.test('division'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x / y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = await d.get('division'); + await run( + t, + abstractIntBinary('/'), + [Type.abstractInt, Type.abstractInt], + Type.abstractInt, + t.params, + cases + ); +}); + +g.test('division_scalar_vector'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x / y +` +). +params((u) => +u.combine('inputSource', onlyConstInputSource).combine('vectorize_rhs', [2, 3, 4]) +). +fn(async (t) => { + const vec_size = t.params.vectorize_rhs; + const vec_type = Type.vec(vec_size, Type.abstractInt); + const cases = await d.get(`division_scalar_vector${vec_size}`); + await run(t, abstractIntBinary('/'), [Type.abstractInt, vec_type], vec_type, t.params, cases); +}); + +g.test('division_vector_scalar'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x / y +` +). +params((u) => +u.combine('inputSource', onlyConstInputSource).combine('vectorize_lhs', [2, 3, 4]) +). +fn(async (t) => { + const vec_size = t.params.vectorize_lhs; + const vec_type = Type.vec(vec_size, Type.abstractInt); + const cases = await d.get(`division_vector${vec_size}_scalar`); + await run(t, abstractIntBinary('/'), [vec_type, Type.abstractInt], vec_type, t.params, cases); +}); + +g.test('multiplication'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x * y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = await d.get('multiplication'); + await run( + t, + abstractIntBinary('*'), + [Type.abstractInt, Type.abstractInt], + Type.abstractInt, + t.params, + cases + ); +}); + +g.test('multiplication_scalar_vector'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x * y +` +). +params((u) => +u.combine('inputSource', onlyConstInputSource).combine('vectorize_rhs', [2, 3, 4]) +). +fn(async (t) => { + const vec_size = t.params.vectorize_rhs; + const vec_type = Type.vec(vec_size, Type.abstractInt); + const cases = await d.get(`multiplication_scalar_vector${vec_size}`); + await run(t, abstractIntBinary('*'), [Type.abstractInt, vec_type], vec_type, t.params, cases); +}); + +g.test('multiplication_vector_scalar'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x * y +` +). +params((u) => +u.combine('inputSource', onlyConstInputSource).combine('vectorize_lhs', [2, 3, 4]) +). +fn(async (t) => { + const vec_size = t.params.vectorize_lhs; + const vec_type = Type.vec(vec_size, Type.abstractInt); + const cases = await d.get(`multiplication_vector${vec_size}_scalar`); + await run(t, abstractIntBinary('*'), [vec_type, Type.abstractInt], vec_type, t.params, cases); +}); + +g.test('remainder'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x % y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = await d.get('remainder'); + await run( + t, + abstractIntBinary('%'), + [Type.abstractInt, Type.abstractInt], + Type.abstractInt, + t.params, + cases + ); +}); + +g.test('remainder_scalar_vector'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x % y +` +). +params((u) => +u.combine('inputSource', onlyConstInputSource).combine('vectorize_rhs', [2, 3, 4]) +). +fn(async (t) => { + const vec_size = t.params.vectorize_rhs; + const vec_type = Type.vec(vec_size, Type.abstractInt); + const cases = await d.get(`remainder_scalar_vector${vec_size}`); + await run(t, abstractIntBinary('%'), [Type.abstractInt, vec_type], vec_type, t.params, cases); +}); + +g.test('remainder_vector_scalar'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x % y +` +). +params((u) => +u.combine('inputSource', onlyConstInputSource).combine('vectorize_lhs', [2, 3, 4]) +). +fn(async (t) => { + const vec_size = t.params.vectorize_lhs; + const vec_type = Type.vec(vec_size, Type.abstractInt); + const cases = await d.get(`remainder_vector${vec_size}_scalar`); + await run(t, abstractIntBinary('%'), [vec_type, Type.abstractInt], vec_type, t.params, cases); +}); + +g.test('subtraction'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x - y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = await d.get('subtraction'); + await run( + t, + abstractIntBinary('-'), + [Type.abstractInt, Type.abstractInt], + Type.abstractInt, + t.params, + cases + ); +}); + +g.test('subtraction_scalar_vector'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x - y +` +). +params((u) => +u.combine('inputSource', onlyConstInputSource).combine('vectorize_rhs', [2, 3, 4]) +). +fn(async (t) => { + const vec_size = t.params.vectorize_rhs; + const vec_type = Type.vec(vec_size, Type.abstractInt); + const cases = await d.get(`subtraction_scalar_vector${vec_size}`); + await run(t, abstractIntBinary('-'), [Type.abstractInt, vec_type], vec_type, t.params, cases); +}); + +g.test('subtraction_vector_scalar'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: x - y +` +). +params((u) => +u.combine('inputSource', onlyConstInputSource).combine('vectorize_lhs', [2, 3, 4]) +). +fn(async (t) => { + const vec_size = t.params.vectorize_lhs; + const vec_type = Type.vec(vec_size, Type.abstractInt); + const cases = await d.get(`subtraction_vector${vec_size}_scalar`); + await run(t, abstractIntBinary('-'), [vec_type, Type.abstractInt], vec_type, t.params, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_comparison.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_comparison.spec.js new file mode 100644 index 0000000000..902e1c0000 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/ai_comparison.spec.js @@ -0,0 +1,124 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for the abstract-int comparison expressions +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { bool, abstractInt, Type } from '../../../../util/conversion.js'; +import { vectorI64Range } from '../../../../util/math.js'; + +import { onlyConstInputSource, run } from '../expression.js'; + +import { binary } from './binary.js'; + +export const g = makeTestGroup(GPUTest); + +/** + * @returns a test case for the provided left hand & right hand values and + * expected boolean result. + */ +function makeCase(lhs, rhs, expected_answer) { + return { input: [abstractInt(lhs), abstractInt(rhs)], expected: bool(expected_answer) }; +} + +g.test('equals'). +specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). +desc( + ` +Expression: x == y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = vectorI64Range(2).map((v) => makeCase(v[0], v[1], v[0] === v[1])); + await run(t, binary('=='), [Type.abstractInt, Type.abstractInt], Type.bool, t.params, cases); +}); + +g.test('not_equals'). +specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). +desc( + ` +Expression: x != y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = vectorI64Range(2).map((v) => makeCase(v[0], v[1], v[0] !== v[1])); + await run(t, binary('!='), [Type.abstractInt, Type.abstractInt], Type.bool, t.params, cases); +}); + +g.test('less_than'). +specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). +desc( + ` +Expression: x < y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = vectorI64Range(2).map((v) => makeCase(v[0], v[1], v[0] < v[1])); + await run(t, binary('<'), [Type.abstractInt, Type.abstractInt], Type.bool, t.params, cases); +}); + +g.test('less_equals'). +specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). +desc( + ` +Expression: x <= y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = vectorI64Range(2).map((v) => makeCase(v[0], v[1], v[0] <= v[1])); + await run(t, binary('<='), [Type.abstractInt, Type.abstractInt], Type.bool, t.params, cases); +}); + +g.test('greater_than'). +specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). +desc( + ` +Expression: x > y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = vectorI64Range(2).map((v) => makeCase(v[0], v[1], v[0] > v[1])); + await run(t, binary('>'), [Type.abstractInt, Type.abstractInt], Type.bool, t.params, cases); +}); + +g.test('greater_equals'). +specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). +desc( + ` +Expression: x >= y +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = vectorI64Range(2).map((v) => makeCase(v[0], v[1], v[0] >= v[1])); + await run(t, binary('>='), [Type.abstractInt, Type.abstractInt], Type.bool, t.params, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/binary.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/binary.js index f3f84db87c..1f0329e40b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/binary.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/binary.js @@ -2,7 +2,8 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { basicExpressionBuilder, compoundAssignmentBuilder, -abstractFloatShaderBuilder } from +abstractFloatShaderBuilder, +abstractIntShaderBuilder } from '../expression.js'; /* @returns a ShaderBuilder that evaluates a binary operation */ @@ -16,6 +17,11 @@ export function compoundBinary(op) { } /* @returns a ShaderBuilder that evaluates a binary operation that returns AbstractFloats */ -export function abstractBinary(op) { +export function abstractFloatBinary(op) { return abstractFloatShaderBuilder((values) => `(${values.map((v) => `(${v})`).join(op)})`); +} + +/* @returns a ShaderBuilder that evaluates a binary operation that returns AbstractFloats */ +export function abstractIntBinary(op) { + return abstractIntShaderBuilder((values) => `(${values.map((v) => `(${v})`).join(op)})`); } \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise.spec.js index c442f5cfa4..06ff03bb12 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise.spec.js @@ -3,59 +3,171 @@ **/export const description = ` Execution Tests for the bitwise binary expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { assert } from '../../../../../common/util/util.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { i32, scalarType, u32 } from '../../../../util/conversion.js'; -import { allInputSources, run } from '../expression.js'; +import { + abstractIntBits, + i32Bits, -import { binary, compoundBinary } from './binary.js'; + scalarType, + u32Bits } from +'../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../expression.js'; + +import { abstractIntBinary, binary, compoundBinary } from './binary.js'; export const g = makeTestGroup(GPUTest); -function makeBitwiseOrCases(inputType) { - const V = inputType === 'i32' ? i32 : u32; - const cases = [ - // Static patterns +/** + * Collection of functions and values required to implement bitwise tests for a + * specific scalar type + */ + + + + + + + +const kScalarImpls = { + i32: { + builder: (bits) => { + assert(typeof bits === 'number'); + return i32Bits(bits); + }, + size: 32 + }, + u32: { + builder: (bits) => { + assert(typeof bits === 'number'); + return u32Bits(bits); + }, + size: 32 + }, + 'abstract-int': { + builder: (bits) => { + assert(typeof bits === 'bigint'); + return abstractIntBits(bits); + }, + size: 64 + } +}; + +/** Wrapper for converting from input type strings to the appropriate implementation */ +function scalarImplForInputType(inputType) { + assert(inputType === 'i32' || inputType === 'u32' || inputType === 'abstract-int'); + return kScalarImpls[inputType]; +} + +/** Manually calculated bitwise-or cases used a check that the CTS test is correct */ +const kBitwiseOrStaticPatterns = { + 32: [ + { + input: [0b00000000000000000000000000000000, 0b00000000000000000000000000000000], + expected: 0b00000000000000000000000000000000 + }, + { + input: [0b11111111111111111111111111111111, 0b00000000000000000000000000000000], + expected: 0b11111111111111111111111111111111 + }, + { + input: [0b00000000000000000000000000000000, 0b11111111111111111111111111111111], + expected: 0b11111111111111111111111111111111 + }, { - input: [V(0b00000000000000000000000000000000), V(0b00000000000000000000000000000000)], - expected: V(0b00000000000000000000000000000000) + input: [0b11111111111111111111111111111111, 0b11111111111111111111111111111111], + expected: 0b11111111111111111111111111111111 }, { - input: [V(0b11111111111111111111111111111111), V(0b00000000000000000000000000000000)], - expected: V(0b11111111111111111111111111111111) + input: [0b10100100010010100100010010100100, 0b00000000000000000000000000000000], + expected: 0b10100100010010100100010010100100 }, { - input: [V(0b00000000000000000000000000000000), V(0b11111111111111111111111111111111)], - expected: V(0b11111111111111111111111111111111) + input: [0b00000000000000000000000000000000, 0b10100100010010100100010010100100], + expected: 0b10100100010010100100010010100100 }, { - input: [V(0b11111111111111111111111111111111), V(0b11111111111111111111111111111111)], - expected: V(0b11111111111111111111111111111111) + input: [0b01010010001001010010001001010010, 0b10100100010010100100010010100100], + expected: 0b11110110011011110110011011110110 + }], + + 64: [ + { + input: [ + 0b0000000000000000000000000000000000000000000000000000000000000000n, + 0b0000000000000000000000000000000000000000000000000000000000000000n], + + expected: 0b0000000000000000000000000000000000000000000000000000000000000000n }, { - input: [V(0b10100100010010100100010010100100), V(0b00000000000000000000000000000000)], - expected: V(0b10100100010010100100010010100100) + input: [ + 0b1111111111111111111111111111111111111111111111111111111111111111n, + 0b0000000000000000000000000000000000000000000000000000000000000000n], + + expected: 0b1111111111111111111111111111111111111111111111111111111111111111n }, { - input: [V(0b00000000000000000000000000000000), V(0b10100100010010100100010010100100)], - expected: V(0b10100100010010100100010010100100) + input: [ + 0b0000000000000000000000000000000000000000000000000000000000000000n, + 0b1111111111111111111111111111111111111111111111111111111111111111n], + + expected: 0b1111111111111111111111111111111111111111111111111111111111111111n }, { - input: [V(0b01010010001001010010001001010010), V(0b10100100010010100100010010100100)], - expected: V(0b11110110011011110110011011110110) - }]; + input: [ + 0b1111111111111111111111111111111111111111111111111111111111111111n, + 0b1111111111111111111111111111111111111111111111111111111111111111n], + expected: 0b1111111111111111111111111111111111111111111111111111111111111111n + }, + { + input: [ + 0b1010010001001010010001001010010010100100010010100100010010100100n, + 0b0000000000000000000000000000000000000000000000000000000000000000n], + + expected: 0b1010010001001010010001001010010010100100010010100100010010100100n + }, + { + input: [ + 0b0000000000000000000000000000000000000000000000000000000000000000n, + 0b1010010001001010010001001010010010100100010010100100010010100100n], + + expected: 0b1010010001001010010001001010010010100100010010100100010010100100n + }, + { + input: [ + 0b0101001000100101001000100101001010100100010010100100010010100100n, + 0b1010010001001010010001001010010010100100010010100100010010100100n], + + expected: 0b1111011001101111011001101111011010100100010010100100010010100100n + }] + +}; + +/** @returns a set of bitwise-or cases for the specific input type */ +function makeBitwiseOrCases(inputType) { + const impl = scalarImplForInputType(inputType); + const indices = + impl.size === 64 ? [...Array(impl.size).keys()].map(BigInt) : [...Array(impl.size).keys()]; + + return [ + ...kBitwiseOrStaticPatterns[impl.size].map((c) => { + return { + input: c.input.map(impl.builder), + expected: impl.builder(c.expected) + }; + }), // Permute all combinations of a single bit being set for the LHS and RHS - for (let i = 0; i < 32; i++) { - const lhs = 1 << i; - for (let j = 0; j < 32; j++) { - const rhs = 1 << j; - cases.push({ - input: [V(lhs), V(rhs)], - expected: V(lhs | rhs) - }); - } - } - return cases; + ...indices.flatMap((i) => { + const lhs = typeof i === 'bigint' ? 1n << i : 1 << i; + return indices.map((j) => { + const rhs = typeof j === 'bigint' ? 1n << j : 1 << j; + assert(typeof lhs === typeof rhs); + const result = typeof lhs === 'bigint' ? lhs | rhs : lhs | rhs; + return { input: [impl.builder(lhs), impl.builder(rhs)], expected: impl.builder(result) }; + }); + })]; + } g.test('bitwise_or'). @@ -63,22 +175,25 @@ specURL('https://www.w3.org/TR/WGSL/#bit-expr'). desc( ` e1 | e2: T -T is i32, u32, vecN, or vecN +T is i32, u32, abstractInt, vecN, vecN, or vecN Bitwise-or. Component-wise when T is a vector. ` ). params((u) => u. -combine('type', ['i32', 'u32']). +combine('type', ['i32', 'u32', 'abstract-int']). combine('inputSource', allInputSources). combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { + t.skipIf( + t.params.type === 'abstract-int' && !onlyConstInputSource.includes(t.params.inputSource) + ); const type = scalarType(t.params.type); const cases = makeBitwiseOrCases(t.params.type); - - await run(t, binary('|'), [type, type], type, t.params, cases); + const builder = t.params.type === 'abstract-int' ? abstractIntBinary('|') : binary('|'); + await run(t, builder, [type, type], type, t.params, cases); }); g.test('bitwise_or_compound'). @@ -104,59 +219,137 @@ fn(async (t) => { await run(t, compoundBinary('|='), [type, type], type, t.params, cases); }); -function makeBitwiseAndCases(inputType) { - const V = inputType === 'i32' ? i32 : u32; - const cases = [ - // Static patterns +/** Manually calculated bitwise-and cases used a check that the CTS test is correct */ +const kBitwiseAndStaticPatterns = { + 32: [ + { + input: [0b00000000000000000000000000000000, 0b00000000000000000000000000000000], + expected: 0b00000000000000000000000000000000 + }, + { + input: [0b11111111111111111111111111111111, 0b00000000000000000000000000000000], + expected: 0b00000000000000000000000000000000 + }, { - input: [V(0b00000000000000000000000000000000), V(0b00000000000000000000000000000000)], - expected: V(0b00000000000000000000000000000000) + input: [0b00000000000000000000000000000000, 0b11111111111111111111111111111111], + expected: 0b00000000000000000000000000000000 }, { - input: [V(0b11111111111111111111111111111111), V(0b00000000000000000000000000000000)], - expected: V(0b00000000000000000000000000000000) + input: [0b11111111111111111111111111111111, 0b11111111111111111111111111111111], + expected: 0b11111111111111111111111111111111 }, { - input: [V(0b00000000000000000000000000000000), V(0b11111111111111111111111111111111)], - expected: V(0b00000000000000000000000000000000) + input: [0b10100100010010100100010010100100, 0b00000000000000000000000000000000], + expected: 0b00000000000000000000000000000000 }, { - input: [V(0b11111111111111111111111111111111), V(0b11111111111111111111111111111111)], - expected: V(0b11111111111111111111111111111111) + input: [0b10100100010010100100010010100100, 0b11111111111111111111111111111111], + expected: 0b10100100010010100100010010100100 }, { - input: [V(0b10100100010010100100010010100100), V(0b00000000000000000000000000000000)], - expected: V(0b00000000000000000000000000000000) + input: [0b00000000000000000000000000000000, 0b10100100010010100100010010100100], + expected: 0b00000000000000000000000000000000 }, { - input: [V(0b10100100010010100100010010100100), V(0b11111111111111111111111111111111)], - expected: V(0b10100100010010100100010010100100) + input: [0b11111111111111111111111111111111, 0b10100100010010100100010010100100], + expected: 0b10100100010010100100010010100100 }, { - input: [V(0b00000000000000000000000000000000), V(0b10100100010010100100010010100100)], - expected: V(0b00000000000000000000000000000000) + input: [0b01010010001001010010001001010010, 0b01011011101101011011101101011011], + expected: 0b01010010001001010010001001010010 + }], + + 64: [ + { + input: [ + 0b0000000000000000000000000000000000000000000000000000000000000000n, + 0b0000000000000000000000000000000000000000000000000000000000000000n], + + expected: 0b0000000000000000000000000000000000000000000000000000000000000000n }, { - input: [V(0b11111111111111111111111111111111), V(0b10100100010010100100010010100100)], - expected: V(0b10100100010010100100010010100100) + input: [ + 0b1111111111111111111111111111111111111111111111111111111111111111n, + 0b0000000000000000000000000000000000000000000000000000000000000000n], + + expected: 0b0000000000000000000000000000000000000000000000000000000000000000n + }, + { + input: [ + 0b0000000000000000000000000000000000000000000000000000000000000000n, + 0b1111111111111111111111111111111111111111111111111111111111111111n], + + expected: 0b0000000000000000000000000000000000000000000000000000000000000000n }, { - input: [V(0b01010010001001010010001001010010), V(0b01011011101101011011101101011011)], - expected: V(0b01010010001001010010001001010010) - }]; + input: [ + 0b1111111111111111111111111111111111111111111111111111111111111111n, + 0b1111111111111111111111111111111111111111111111111111111111111111n], + expected: 0b1111111111111111111111111111111111111111111111111111111111111111n + }, + { + input: [ + 0b1010010001001010010001001010010010100100010010100100010010100100n, + 0b0000000000000000000000000000000000000000000000000000000000000000n], + + expected: 0b0000000000000000000000000000000000000000000000000000000000000000n + }, + { + input: [ + 0b1010010001001010010001001010010010100100010010100100010010100100n, + 0b1111111111111111111111111111111111111111111111111111111111111111n], + + expected: 0b1010010001001010010001001010010010100100010010100100010010100100n + }, + { + input: [ + 0b0000000000000000000000000000000000000000000000000000000000000000n, + 0b1010010001001010010001001010010010100100010010100100010010100100n], + + expected: 0b0000000000000000000000000000000000000000000000000000000000000000n + }, + { + input: [ + 0b1111111111111111111111111111111111111111111111111111111111111111n, + 0b1010010001001010010001001010010010100100010010100100010010100100n], + + expected: 0b1010010001001010010001001010010010100100010010100100010010100100n + }, + { + input: [ + 0b0101001000100101001000100101001001010010001001010010001001010010n, + 0b0101101110110101101110110101101101011011101101011011101101011011n], + + expected: 0b0101001000100101001000100101001001010010001001010010001001010010n + }] + +}; + +/** @returns a set of bitwise-or cases for the specific input type */ +function makeBitwiseAndCases(inputType) { + const impl = scalarImplForInputType(inputType); + const indices = + impl.size === 64 ? [...Array(impl.size).keys()].map(BigInt) : [...Array(impl.size).keys()]; + + return [ + ...kBitwiseAndStaticPatterns[impl.size].map((c) => { + return { + input: c.input.map(impl.builder), + expected: impl.builder(c.expected) + }; + }), // Permute all combinations of a single bit being set for the LHS and all but one bit set for the RHS - for (let i = 0; i < 32; i++) { - const lhs = 1 << i; - for (let j = 0; j < 32; j++) { - const rhs = 0xffffffff ^ 1 << j; - cases.push({ - input: [V(lhs), V(rhs)], - expected: V(lhs & rhs) - }); - } - } - return cases; + ...indices.flatMap((i) => { + const lhs = typeof i === 'bigint' ? 1n << i : 1 << i; + return indices.map((j) => { + const rhs = typeof j === 'bigint' ? 0xffffffffffffffffn ^ 1n << j : 0xffffffff ^ 1 << j; + assert(typeof lhs === typeof rhs); + const result = typeof lhs === 'bigint' ? lhs & rhs : lhs & rhs; + return { input: [impl.builder(lhs), impl.builder(rhs)], expected: impl.builder(result) }; + }); + })]; + } g.test('bitwise_and'). @@ -164,21 +357,25 @@ specURL('https://www.w3.org/TR/WGSL/#bit-expr'). desc( ` e1 & e2: T -T is i32, u32, vecN, or vecN +T is i32, u32, AbstractInt, vecN, vecN, or vecN Bitwise-and. Component-wise when T is a vector. ` ). params((u) => u. -combine('type', ['i32', 'u32']). +combine('type', ['i32', 'u32', 'abstract-int']). combine('inputSource', allInputSources). combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { + t.skipIf( + t.params.type === 'abstract-int' && !onlyConstInputSource.includes(t.params.inputSource) + ); const type = scalarType(t.params.type); const cases = makeBitwiseAndCases(t.params.type); - await run(t, binary('&'), [type, type], type, t.params, cases); + const builder = t.params.type === 'abstract-int' ? abstractIntBinary('&') : binary('&'); + await run(t, builder, [type, type], type, t.params, cases); }); g.test('bitwise_and_compound'). @@ -203,59 +400,137 @@ fn(async (t) => { await run(t, compoundBinary('&='), [type, type], type, t.params, cases); }); -function makeBitwiseExcluseOrCases(inputType) { - const V = inputType === 'i32' ? i32 : u32; - const cases = [ - // Static patterns +/** Manually calculated bitwise-or cases used a check that the CTS test is correct */ +const kBitwiseExclusiveOrStaticPatterns = { + 32: [ + { + input: [0b00000000000000000000000000000000, 0b00000000000000000000000000000000], + expected: 0b00000000000000000000000000000000 + }, + { + input: [0b11111111111111111111111111111111, 0b00000000000000000000000000000000], + expected: 0b11111111111111111111111111111111 + }, + { + input: [0b00000000000000000000000000000000, 0b11111111111111111111111111111111], + expected: 0b11111111111111111111111111111111 + }, + { + input: [0b11111111111111111111111111111111, 0b11111111111111111111111111111111], + expected: 0b00000000000000000000000000000000 + }, + { + input: [0b10100100010010100100010010100100, 0b00000000000000000000000000000000], + expected: 0b10100100010010100100010010100100 + }, + { + input: [0b10100100010010100100010010100100, 0b11111111111111111111111111111111], + expected: 0b01011011101101011011101101011011 + }, + { + input: [0b00000000000000000000000000000000, 0b10100100010010100100010010100100], + expected: 0b10100100010010100100010010100100 + }, + { + input: [0b11111111111111111111111111111111, 0b10100100010010100100010010100100], + expected: 0b01011011101101011011101101011011 + }, + { + input: [0b01010010001001010010001001010010, 0b01011011101101011011101101011011], + expected: 0b00001001100100001001100100001001 + }], + + 64: [ { - input: [V(0b00000000000000000000000000000000), V(0b00000000000000000000000000000000)], - expected: V(0b00000000000000000000000000000000) + input: [ + 0b0000000000000000000000000000000000000000000000000000000000000000n, + 0b0000000000000000000000000000000000000000000000000000000000000000n], + + expected: 0b0000000000000000000000000000000000000000000000000000000000000000n }, { - input: [V(0b11111111111111111111111111111111), V(0b00000000000000000000000000000000)], - expected: V(0b11111111111111111111111111111111) + input: [ + 0b1111111111111111111111111111111111111111111111111111111111111111n, + 0b0000000000000000000000000000000000000000000000000000000000000000n], + + expected: 0b1111111111111111111111111111111111111111111111111111111111111111n }, { - input: [V(0b00000000000000000000000000000000), V(0b11111111111111111111111111111111)], - expected: V(0b11111111111111111111111111111111) + input: [ + 0b0000000000000000000000000000000000000000000000000000000000000000n, + 0b1111111111111111111111111111111111111111111111111111111111111111n], + + expected: 0b1111111111111111111111111111111111111111111111111111111111111111n }, { - input: [V(0b11111111111111111111111111111111), V(0b11111111111111111111111111111111)], - expected: V(0b00000000000000000000000000000000) + input: [ + 0b1111111111111111111111111111111111111111111111111111111111111111n, + 0b1111111111111111111111111111111111111111111111111111111111111111n], + + expected: 0b0000000000000000000000000000000000000000000000000000000000000000n }, { - input: [V(0b10100100010010100100010010100100), V(0b00000000000000000000000000000000)], - expected: V(0b10100100010010100100010010100100) + input: [ + 0b1010010001001010010001001010010010100100010010100100010010100100n, + 0b0000000000000000000000000000000000000000000000000000000000000000n], + + expected: 0b1010010001001010010001001010010010100100010010100100010010100100n }, { - input: [V(0b10100100010010100100010010100100), V(0b11111111111111111111111111111111)], - expected: V(0b01011011101101011011101101011011) + input: [ + 0b1010010001001010010001001010010010100100010010100100010010100100n, + 0b1111111111111111111111111111111111111111111111111111111111111111n], + + expected: 0b0101101110110101101110110101101101011011101101011011101101011011n }, { - input: [V(0b00000000000000000000000000000000), V(0b10100100010010100100010010100100)], - expected: V(0b10100100010010100100010010100100) + input: [ + 0b0000000000000000000000000000000000000000000000000000000000000000n, + 0b1010010001001010010001001010010010100100010010100100010010100100n], + + expected: 0b1010010001001010010001001010010010100100010010100100010010100100n }, { - input: [V(0b11111111111111111111111111111111), V(0b10100100010010100100010010100100)], - expected: V(0b01011011101101011011101101011011) + input: [ + 0b1111111111111111111111111111111111111111111111111111111111111111n, + 0b1010010001001010010001001010010010100100010010100100010010100100n], + + expected: 0b0101101110110101101110110101101101011011101101011011101101011011n }, { - input: [V(0b01010010001001010010001001010010), V(0b01011011101101011011101101011011)], - expected: V(0b00001001100100001001100100001001) - }]; + input: [ + 0b0101001000100101001000100101001001010010001001010010001001010010n, + 0b0101101110110101101110110101101101011011101101011011101101011011n], + expected: 0b0000100110010000100110010000100100001001100100001001100100001001n + }] + +}; + +/** @returns a set of bitwise-xor cases for the specific input type */ +function makeBitwiseExclusiveOrCases(inputType) { + const impl = scalarImplForInputType(inputType); + const indices = + impl.size === 64 ? [...Array(impl.size).keys()].map(BigInt) : [...Array(impl.size).keys()]; + + return [ + ...kBitwiseExclusiveOrStaticPatterns[impl.size].map((c) => { + return { + input: c.input.map(impl.builder), + expected: impl.builder(c.expected) + }; + }), // Permute all combinations of a single bit being set for the LHS and all but one bit set for the RHS - for (let i = 0; i < 32; i++) { - const lhs = 1 << i; - for (let j = 0; j < 32; j++) { - const rhs = 0xffffffff ^ 1 << j; - cases.push({ - input: [V(lhs), V(rhs)], - expected: V(lhs ^ rhs) - }); - } - } - return cases; + ...indices.flatMap((i) => { + const lhs = typeof i === 'bigint' ? 1n << i : 1 << i; + return indices.map((j) => { + const rhs = typeof j === 'bigint' ? 0xffffffffffffffffn ^ 1n << j : 0xffffffff ^ 1 << j; + assert(typeof lhs === typeof rhs); + const result = typeof lhs === 'bigint' ? lhs ^ rhs : lhs ^ rhs; + return { input: [impl.builder(lhs), impl.builder(rhs)], expected: impl.builder(result) }; + }); + })]; + } g.test('bitwise_exclusive_or'). @@ -263,21 +538,25 @@ specURL('https://www.w3.org/TR/WGSL/#bit-expr'). desc( ` e1 ^ e2: T -T is i32, u32, vecN, or vecN +T is i32, u32, abstractInt, vecN, vecN, or vecN Bitwise-exclusive-or. Component-wise when T is a vector. ` ). params((u) => u. -combine('type', ['i32', 'u32']). +combine('type', ['i32', 'u32', 'abstract-int']). combine('inputSource', allInputSources). combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { + t.skipIf( + t.params.type === 'abstract-int' && !onlyConstInputSource.includes(t.params.inputSource) + ); const type = scalarType(t.params.type); - const cases = makeBitwiseExcluseOrCases(t.params.type); - await run(t, binary('^'), [type, type], type, t.params, cases); + const cases = makeBitwiseExclusiveOrCases(t.params.type); + const builder = t.params.type === 'abstract-int' ? abstractIntBinary('^') : binary('^'); + await run(t, builder, [type, type], type, t.params, cases); }); g.test('bitwise_exclusive_or_compound'). @@ -298,6 +577,6 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const type = scalarType(t.params.type); - const cases = makeBitwiseExcluseOrCases(t.params.type); + const cases = makeBitwiseExclusiveOrCases(t.params.type); await run(t, compoundBinary('^='), [type, type], type, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise_shift.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise_shift.spec.js index feed24b687..ebad2a8493 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise_shift.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise_shift.spec.js @@ -4,7 +4,8 @@ Execution Tests for the bitwise shift binary expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { i32, scalarType, TypeU32, u32 } from '../../../../util/conversion.js'; +import { i32, scalarType, Type, u32 } from '../../../../util/conversion.js'; + import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; @@ -193,7 +194,7 @@ combine('vectorize', [undefined, 2, 3, 4]) fn(async (t) => { const type = scalarType(t.params.type); const cases = makeShiftLeftConcreteCases(t.params.type, t.params.inputSource, type); - await run(t, binary('<<'), [type, TypeU32], type, t.params, cases); + await run(t, binary('<<'), [type, Type.u32], type, t.params, cases); }); g.test('shift_left_concrete_compound'). @@ -214,7 +215,7 @@ combine('vectorize', [undefined, 2, 3, 4]) fn(async (t) => { const type = scalarType(t.params.type); const cases = makeShiftLeftConcreteCases(t.params.type, t.params.inputSource, type); - await run(t, compoundBinary('<<='), [type, TypeU32], type, t.params, cases); + await run(t, compoundBinary('<<='), [type, Type.u32], type, t.params, cases); }); function makeShiftRightConcreteCases(inputType, inputSource, type) { @@ -318,7 +319,7 @@ combine('vectorize', [undefined, 2, 3, 4]) fn(async (t) => { const type = scalarType(t.params.type); const cases = makeShiftRightConcreteCases(t.params.type, t.params.inputSource, type); - await run(t, binary('>>'), [type, TypeU32], type, t.params, cases); + await run(t, binary('>>'), [type, Type.u32], type, t.params, cases); }); g.test('shift_right_concrete_compound'). @@ -339,5 +340,5 @@ combine('vectorize', [undefined, 2, 3, 4]) fn(async (t) => { const type = scalarType(t.params.type); const cases = makeShiftRightConcreteCases(t.params.type, t.params.inputSource, type); - await run(t, compoundBinary('>>='), [type, TypeU32], type, t.params, cases); + await run(t, compoundBinary('>>='), [type, Type.u32], type, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bool_logical.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bool_logical.spec.js index 52cbe17222..69a24f22a0 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bool_logical.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bool_logical.spec.js @@ -4,7 +4,7 @@ Execution Tests for the boolean binary logical expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { bool, TypeBool } from '../../../../util/conversion.js'; +import { bool, Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; @@ -33,7 +33,7 @@ fn(async (t) => { { input: [bool(true), bool(true)], expected: bool(true) }]; - await run(t, binary('&'), [TypeBool, TypeBool], TypeBool, t.params, cases); + await run(t, binary('&'), [Type.bool, Type.bool], Type.bool, t.params, cases); }); g.test('and_compound'). @@ -55,7 +55,7 @@ fn(async (t) => { { input: [bool(true), bool(true)], expected: bool(true) }]; - await run(t, compoundBinary('&='), [TypeBool, TypeBool], TypeBool, t.params, cases); + await run(t, compoundBinary('&='), [Type.bool, Type.bool], Type.bool, t.params, cases); }); g.test('and_short_circuit'). @@ -75,7 +75,7 @@ fn(async (t) => { { input: [bool(true), bool(true)], expected: bool(true) }]; - await run(t, binary('&&'), [TypeBool, TypeBool], TypeBool, t.params, cases); + await run(t, binary('&&'), [Type.bool, Type.bool], Type.bool, t.params, cases); }); g.test('or'). @@ -97,7 +97,7 @@ fn(async (t) => { { input: [bool(true), bool(true)], expected: bool(true) }]; - await run(t, binary('|'), [TypeBool, TypeBool], TypeBool, t.params, cases); + await run(t, binary('|'), [Type.bool, Type.bool], Type.bool, t.params, cases); }); g.test('or_compound'). @@ -119,7 +119,7 @@ fn(async (t) => { { input: [bool(true), bool(true)], expected: bool(true) }]; - await run(t, compoundBinary('|='), [TypeBool, TypeBool], TypeBool, t.params, cases); + await run(t, compoundBinary('|='), [Type.bool, Type.bool], Type.bool, t.params, cases); }); g.test('or_short_circuit'). @@ -139,7 +139,7 @@ fn(async (t) => { { input: [bool(true), bool(true)], expected: bool(true) }]; - await run(t, binary('||'), [TypeBool, TypeBool], TypeBool, t.params, cases); + await run(t, binary('||'), [Type.bool, Type.bool], Type.bool, t.params, cases); }); g.test('equals'). @@ -161,7 +161,7 @@ fn(async (t) => { { input: [bool(true), bool(true)], expected: bool(true) }]; - await run(t, binary('=='), [TypeBool, TypeBool], TypeBool, t.params, cases); + await run(t, binary('=='), [Type.bool, Type.bool], Type.bool, t.params, cases); }); g.test('not_equals'). @@ -183,5 +183,5 @@ fn(async (t) => { { input: [bool(true), bool(true)], expected: bool(false) }]; - await run(t, binary('!='), [TypeBool, TypeBool], TypeBool, t.params, cases); + await run(t, binary('!='), [Type.bool, Type.bool], Type.bool, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_addition.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_addition.cache.js new file mode 100644 index 0000000000..deefe3744e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_addition.cache.js @@ -0,0 +1,60 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF16Range, sparseVectorF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const additionVectorScalarInterval = (v, s) => { + return FP.f16.toVector(v.map((e) => FP.f16.additionInterval(e, s))); +}; + +const additionScalarVectorInterval = (s, v) => { + return FP.f16.toVector(v.map((e) => FP.f16.additionInterval(s, e))); +}; + +const scalar_cases = [true, false]. +map((nonConst) => ({ + [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarPairToIntervalCases( + sparseScalarF16Range(), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f16.additionInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const vector_scalar_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateVectorScalarToVectorCases( + sparseVectorF16Range(dim), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + additionVectorScalarInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarVectorToVectorCases( + sparseScalarF16Range(), + sparseVectorF16Range(dim), + nonConst ? 'unfiltered' : 'finite', + additionScalarVectorInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f16_addition', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_addition.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_addition.spec.js index 28087a1ca3..982aa1e43a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_addition.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_addition.spec.js @@ -4,73 +4,14 @@ Execution Tests for non-matrix f16 addition expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF16Range, sparseVectorF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -const additionVectorScalarInterval = (v, s) => { - return FP.f16.toVector(v.map((e) => FP.f16.additionInterval(e, s))); -}; - -const additionScalarVectorInterval = (s, v) => { - return FP.f16.toVector(v.map((e) => FP.f16.additionInterval(s, e))); -}; +import { d } from './f16_addition.cache.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = [true, false]. -map((nonConst) => ({ - [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarPairToIntervalCases( - sparseF16Range(), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f16.additionInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const vector_scalar_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorScalarToVectorCases( - sparseVectorF16Range(dim), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - additionVectorScalarInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarVectorToVectorCases( - sparseF16Range(), - sparseVectorF16Range(dim), - nonConst ? 'unfiltered' : 'finite', - additionScalarVectorInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f16_addition', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -87,7 +28,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('+'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, binary('+'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('vector'). @@ -106,7 +47,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' // Using vectorize to generate vector cases based on scalar cases ); - await run(t, binary('+'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, binary('+'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('scalar_compound'). @@ -127,7 +68,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, compoundBinary('+='), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, compoundBinary('+='), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('vector_scalar'). @@ -150,8 +91,8 @@ fn(async (t) => { await run( t, binary('+'), - [TypeVec(dim, TypeF16), TypeF16], - TypeVec(dim, TypeF16), + [Type.vec(dim, Type.f16), Type.f16], + Type.vec(dim, Type.f16), t.params, cases ); @@ -177,8 +118,8 @@ fn(async (t) => { await run( t, compoundBinary('+='), - [TypeVec(dim, TypeF16), TypeF16], - TypeVec(dim, TypeF16), + [Type.vec(dim, Type.f16), Type.f16], + Type.vec(dim, Type.f16), t.params, cases ); @@ -204,8 +145,8 @@ fn(async (t) => { await run( t, binary('+'), - [TypeF16, TypeVec(dim, TypeF16)], - TypeVec(dim, TypeF16), + [Type.f16, Type.vec(dim, Type.f16)], + Type.vec(dim, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_comparison.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_comparison.cache.js new file mode 100644 index 0000000000..2c5edd5027 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_comparison.cache.js @@ -0,0 +1,144 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { anyOf } from '../../../../util/compare.js';import { bool, f16 } from '../../../../util/conversion.js';import { flushSubnormalNumberF16, vectorF16Range } from '../../../../util/math.js'; + +import { makeCaseCache } from '../case_cache.js'; + +/** + * @returns a test case for the provided left hand & right hand values and truth function. + * Handles quantization and subnormals. + */ +function makeCase( +lhs, +rhs, +truthFunc) +{ + // Subnormal float values may be flushed at any time. + // https://www.w3.org/TR/WGSL/#floating-point-evaluation + const f16_lhs = f16(lhs); + const f16_rhs = f16(rhs); + const lhs_options = new Set([f16_lhs, f16(flushSubnormalNumberF16(lhs))]); + const rhs_options = new Set([f16_rhs, f16(flushSubnormalNumberF16(rhs))]); + const expected = []; + lhs_options.forEach((l) => { + rhs_options.forEach((r) => { + const result = bool(truthFunc(l, r)); + if (!expected.includes(result)) { + expected.push(result); + } + }); + }); + + return { input: [f16_lhs, f16_rhs], expected: anyOf(...expected) }; +} + +export const d = makeCaseCache('binary/f16_logical', { + equals_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value === rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + equals_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value === rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + not_equals_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value !== rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + not_equals_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value !== rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + less_than_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value < rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + less_than_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value < rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + less_equals_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value <= rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + less_equals_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value <= rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + greater_than_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value > rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + greater_than_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value > rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + greater_equals_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value >= rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + greater_equals_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value >= rhs.value; + }; + + return vectorF16Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_comparison.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_comparison.spec.js index 33b99a219b..defab2c209 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_comparison.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_comparison.spec.js @@ -4,155 +4,14 @@ Execution Tests for the f16 comparison operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { anyOf } from '../../../../util/compare.js'; -import { bool, f16, TypeBool, TypeF16 } from '../../../../util/conversion.js'; -import { flushSubnormalNumberF16, vectorF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary } from './binary.js'; +import { d } from './f16_comparison.cache.js'; export const g = makeTestGroup(GPUTest); -/** - * @returns a test case for the provided left hand & right hand values and truth function. - * Handles quantization and subnormals. - */ -function makeCase( -lhs, -rhs, -truthFunc) -{ - // Subnormal float values may be flushed at any time. - // https://www.w3.org/TR/WGSL/#floating-point-evaluation - const f16_lhs = f16(lhs); - const f16_rhs = f16(rhs); - const lhs_options = new Set([f16_lhs, f16(flushSubnormalNumberF16(lhs))]); - const rhs_options = new Set([f16_rhs, f16(flushSubnormalNumberF16(rhs))]); - const expected = []; - lhs_options.forEach((l) => { - rhs_options.forEach((r) => { - const result = bool(truthFunc(l, r)); - if (!expected.includes(result)) { - expected.push(result); - } - }); - }); - - return { input: [f16_lhs, f16_rhs], expected: anyOf(...expected) }; -} - -export const d = makeCaseCache('binary/f16_logical', { - equals_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value === rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - equals_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value === rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - not_equals_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value !== rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - not_equals_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value !== rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - less_than_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value < rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - less_than_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value < rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - less_equals_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value <= rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - less_equals_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value <= rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - greater_than_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value > rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - greater_than_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value > rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - greater_equals_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value >= rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - greater_equals_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value >= rhs.value; - }; - - return vectorF16Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - } -}); - g.test('equals'). specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). desc( @@ -171,7 +30,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'equals_const' : 'equals_non_const' ); - await run(t, binary('=='), [TypeF16, TypeF16], TypeBool, t.params, cases); + await run(t, binary('=='), [Type.f16, Type.f16], Type.bool, t.params, cases); }); g.test('not_equals'). @@ -192,7 +51,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'not_equals_const' : 'not_equals_non_const' ); - await run(t, binary('!='), [TypeF16, TypeF16], TypeBool, t.params, cases); + await run(t, binary('!='), [Type.f16, Type.f16], Type.bool, t.params, cases); }); g.test('less_than'). @@ -213,7 +72,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'less_than_const' : 'less_than_non_const' ); - await run(t, binary('<'), [TypeF16, TypeF16], TypeBool, t.params, cases); + await run(t, binary('<'), [Type.f16, Type.f16], Type.bool, t.params, cases); }); g.test('less_equals'). @@ -234,7 +93,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'less_equals_const' : 'less_equals_non_const' ); - await run(t, binary('<='), [TypeF16, TypeF16], TypeBool, t.params, cases); + await run(t, binary('<='), [Type.f16, Type.f16], Type.bool, t.params, cases); }); g.test('greater_than'). @@ -255,7 +114,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'greater_than_const' : 'greater_than_non_const' ); - await run(t, binary('>'), [TypeF16, TypeF16], TypeBool, t.params, cases); + await run(t, binary('>'), [Type.f16, Type.f16], Type.bool, t.params, cases); }); g.test('greater_equals'). @@ -276,5 +135,5 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'greater_equals_const' : 'greater_equals_non_const' ); - await run(t, binary('>='), [TypeF16, TypeF16], TypeBool, t.params, cases); + await run(t, binary('>='), [Type.f16, Type.f16], Type.bool, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_division.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_division.cache.js new file mode 100644 index 0000000000..bd3335f681 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_division.cache.js @@ -0,0 +1,60 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF16Range, sparseVectorF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const divisionVectorScalarInterval = (v, s) => { + return FP.f16.toVector(v.map((e) => FP.f16.divisionInterval(e, s))); +}; + +const divisionScalarVectorInterval = (s, v) => { + return FP.f16.toVector(v.map((e) => FP.f16.divisionInterval(s, e))); +}; + +const scalar_cases = [true, false]. +map((nonConst) => ({ + [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarPairToIntervalCases( + sparseScalarF16Range(), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f16.divisionInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const vector_scalar_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateVectorScalarToVectorCases( + sparseVectorF16Range(dim), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + divisionVectorScalarInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarVectorToVectorCases( + sparseScalarF16Range(), + sparseVectorF16Range(dim), + nonConst ? 'unfiltered' : 'finite', + divisionScalarVectorInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f16_division', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_division.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_division.spec.js index bcbb523c0e..324d27c43a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_division.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_division.spec.js @@ -4,73 +4,14 @@ Execution Tests for non-matrix f16 division expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF16Range, sparseVectorF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -const divisionVectorScalarInterval = (v, s) => { - return FP.f16.toVector(v.map((e) => FP.f16.divisionInterval(e, s))); -}; - -const divisionScalarVectorInterval = (s, v) => { - return FP.f16.toVector(v.map((e) => FP.f16.divisionInterval(s, e))); -}; +import { d } from './f16_division.cache.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = [true, false]. -map((nonConst) => ({ - [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarPairToIntervalCases( - sparseF16Range(), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f16.divisionInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const vector_scalar_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorScalarToVectorCases( - sparseVectorF16Range(dim), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - divisionVectorScalarInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarVectorToVectorCases( - sparseF16Range(), - sparseVectorF16Range(dim), - nonConst ? 'unfiltered' : 'finite', - divisionScalarVectorInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f16_division', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -87,7 +28,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('/'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, binary('/'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('vector'). @@ -106,7 +47,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' // Using vectorize to generate vector cases based on scalar cases ); - await run(t, binary('/'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, binary('/'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('scalar_compound'). @@ -127,7 +68,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, compoundBinary('/='), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, compoundBinary('/='), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('vector_scalar'). @@ -150,8 +91,8 @@ fn(async (t) => { await run( t, binary('/'), - [TypeVec(dim, TypeF16), TypeF16], - TypeVec(dim, TypeF16), + [Type.vec(dim, Type.f16), Type.f16], + Type.vec(dim, Type.f16), t.params, cases ); @@ -177,8 +118,8 @@ fn(async (t) => { await run( t, compoundBinary('/='), - [TypeVec(dim, TypeF16), TypeF16], - TypeVec(dim, TypeF16), + [Type.vec(dim, Type.f16), Type.f16], + Type.vec(dim, Type.f16), t.params, cases ); @@ -204,8 +145,8 @@ fn(async (t) => { await run( t, binary('/'), - [TypeF16, TypeVec(dim, TypeF16)], - TypeVec(dim, TypeF16), + [Type.f16, Type.vec(dim, Type.f16)], + Type.vec(dim, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_addition.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_addition.cache.js new file mode 100644 index 0000000000..fb3140a58a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_addition.cache.js @@ -0,0 +1,23 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR_[non_]const +const mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateMatrixPairToMatrixCases( + sparseMatrixF16Range(cols, rows), + sparseMatrixF16Range(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f16.additionMatrixMatrixInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f16_matrix_addition', mat_cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_addition.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_addition.spec.js index 9948b0d164..a5478d9a49 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_addition.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_addition.spec.js @@ -4,36 +4,14 @@ Execution Tests for matrix f16 addition expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16, TypeMat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseMatrixF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; +import { d } from './f16_matrix_addition.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: matCxR_[non_]const -const mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateMatrixPairToMatrixCases( - sparseMatrixF16Range(cols, rows), - sparseMatrixF16Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f16.additionMatrixMatrixInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f16_matrix_addition', mat_cases); - g.test('matrix'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -60,8 +38,8 @@ fn(async (t) => { await run( t, binary('+'), - [TypeMat(cols, rows, TypeF16), TypeMat(cols, rows, TypeF16)], - TypeMat(cols, rows, TypeF16), + [Type.mat(cols, rows, Type.f16), Type.mat(cols, rows, Type.f16)], + Type.mat(cols, rows, Type.f16), t.params, cases ); @@ -93,8 +71,8 @@ fn(async (t) => { await run( t, compoundBinary('+='), - [TypeMat(cols, rows, TypeF16), TypeMat(cols, rows, TypeF16)], - TypeMat(cols, rows, TypeF16), + [Type.mat(cols, rows, Type.f16), Type.mat(cols, rows, Type.f16)], + Type.mat(cols, rows, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_matrix_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_matrix_multiplication.cache.js new file mode 100644 index 0000000000..356c64e3e0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_matrix_multiplication.cache.js @@ -0,0 +1,25 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +// Cases: matKxR_matCxK_[non_]const +const mat_mat_cases = [2, 3, 4]. +flatMap((k) => +[2, 3, 4].flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`mat${k}x${rows}_mat${cols}x${k}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateMatrixPairToMatrixCases( + sparseMatrixF16Range(k, rows), + sparseMatrixF16Range(cols, k), + nonConst ? 'unfiltered' : 'finite', + FP.f16.multiplicationMatrixMatrixInterval + ); + } +})) +) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f16_matrix_matrix_multiplication', mat_mat_cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_matrix_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_matrix_multiplication.spec.js index 5076e979ab..9df1697583 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_matrix_multiplication.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_matrix_multiplication.spec.js @@ -4,38 +4,14 @@ Execution Tests for matrix-matrix f16 multiplication expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16, TypeMat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseMatrixF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; +import { d } from './f16_matrix_matrix_multiplication.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: matKxR_matCxK_[non_]const -const mat_mat_cases = [2, 3, 4]. -flatMap((k) => -[2, 3, 4].flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`mat${k}x${rows}_mat${cols}x${k}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateMatrixPairToMatrixCases( - sparseMatrixF16Range(k, rows), - sparseMatrixF16Range(cols, k), - nonConst ? 'unfiltered' : 'finite', - FP.f16.multiplicationMatrixMatrixInterval - ); - } -})) -) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f16_matrix_matrix_multiplication', mat_mat_cases); - g.test('matrix_matrix'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -68,8 +44,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeMat(x_cols, x_rows, TypeF16), TypeMat(y_cols, y_rows, TypeF16)], - TypeMat(y_cols, x_rows, TypeF16), + [Type.mat(x_cols, x_rows, Type.f16), Type.mat(y_cols, y_rows, Type.f16)], + Type.mat(y_cols, x_rows, Type.f16), t.params, cases ); @@ -106,8 +82,8 @@ fn(async (t) => { await run( t, compoundBinary('*='), - [TypeMat(x_cols, x_rows, TypeF16), TypeMat(y_cols, y_rows, TypeF16)], - TypeMat(y_cols, x_rows, TypeF16), + [Type.mat(x_cols, x_rows, Type.f16), Type.mat(y_cols, y_rows, Type.f16)], + Type.mat(y_cols, x_rows, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_scalar_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_scalar_multiplication.cache.js new file mode 100644 index 0000000000..43776ca14a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_scalar_multiplication.cache.js @@ -0,0 +1,44 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF16Range, sparseScalarF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR_scalar_[non_]const +const mat_scalar_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`mat${cols}x${rows}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateMatrixScalarToMatrixCases( + sparseMatrixF16Range(cols, rows), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f16.multiplicationMatrixScalarInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: scalar_matCxR_[non_]const +const scalar_mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`scalar_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarMatrixToMatrixCases( + sparseScalarF16Range(), + sparseMatrixF16Range(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f16.multiplicationScalarMatrixInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f16_matrix_scalar_multiplication', { + ...mat_scalar_cases, + ...scalar_mat_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_scalar_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_scalar_multiplication.spec.js index 292c7ad508..040745320e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_scalar_multiplication.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_scalar_multiplication.spec.js @@ -4,57 +4,14 @@ Execution Tests for matrix-scalar and scalar-matrix f16 multiplication expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16, TypeMat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF16Range, sparseMatrixF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; +import { d } from './f16_matrix_scalar_multiplication.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: matCxR_scalar_[non_]const -const mat_scalar_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`mat${cols}x${rows}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateMatrixScalarToMatrixCases( - sparseMatrixF16Range(cols, rows), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f16.multiplicationMatrixScalarInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: scalar_matCxR_[non_]const -const scalar_mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`scalar_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarMatrixToMatrixCases( - sparseF16Range(), - sparseMatrixF16Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f16.multiplicationScalarMatrixInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f16_matrix_scalar_multiplication', { - ...mat_scalar_cases, - ...scalar_mat_cases -}); - g.test('matrix_scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -83,8 +40,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeMat(cols, rows, TypeF16), TypeF16], - TypeMat(cols, rows, TypeF16), + [Type.mat(cols, rows, Type.f16), Type.f16], + Type.mat(cols, rows, Type.f16), t.params, cases ); @@ -118,8 +75,8 @@ fn(async (t) => { await run( t, compoundBinary('*='), - [TypeMat(cols, rows, TypeF16), TypeF16], - TypeMat(cols, rows, TypeF16), + [Type.mat(cols, rows, Type.f16), Type.f16], + Type.mat(cols, rows, Type.f16), t.params, cases ); @@ -153,8 +110,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeF16, TypeMat(cols, rows, TypeF16)], - TypeMat(cols, rows, TypeF16), + [Type.f16, Type.mat(cols, rows, Type.f16)], + Type.mat(cols, rows, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_subtraction.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_subtraction.cache.js new file mode 100644 index 0000000000..f759832ae7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_subtraction.cache.js @@ -0,0 +1,23 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR_[non_]const +const mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateMatrixPairToMatrixCases( + sparseMatrixF16Range(cols, rows), + sparseMatrixF16Range(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f16.subtractionMatrixMatrixInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f16_matrix_subtraction', mat_cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_subtraction.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_subtraction.spec.js index c787e555be..f47021eee6 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_subtraction.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_subtraction.spec.js @@ -4,36 +4,14 @@ Execution Tests for matrix f16 subtraction expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16, TypeMat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseMatrixF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; +import { d } from './f16_matrix_subtraction.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: matCxR_[non_]const -const mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateMatrixPairToMatrixCases( - sparseMatrixF16Range(cols, rows), - sparseMatrixF16Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f16.subtractionMatrixMatrixInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f16_matrix_subtraction', mat_cases); - g.test('matrix'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -60,8 +38,8 @@ fn(async (t) => { await run( t, binary('-'), - [TypeMat(cols, rows, TypeF16), TypeMat(cols, rows, TypeF16)], - TypeMat(cols, rows, TypeF16), + [Type.mat(cols, rows, Type.f16), Type.mat(cols, rows, Type.f16)], + Type.mat(cols, rows, Type.f16), t.params, cases ); @@ -93,8 +71,8 @@ fn(async (t) => { await run( t, compoundBinary('-='), - [TypeMat(cols, rows, TypeF16), TypeMat(cols, rows, TypeF16)], - TypeMat(cols, rows, TypeF16), + [Type.mat(cols, rows, Type.f16), Type.mat(cols, rows, Type.f16)], + Type.mat(cols, rows, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_vector_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_vector_multiplication.cache.js new file mode 100644 index 0000000000..81b117512a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_vector_multiplication.cache.js @@ -0,0 +1,44 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF16Range, sparseVectorF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR_vecC_[non_]const +const mat_vec_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`mat${cols}x${rows}_vec${cols}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateMatrixVectorToVectorCases( + sparseMatrixF16Range(cols, rows), + sparseVectorF16Range(cols), + nonConst ? 'unfiltered' : 'finite', + FP.f16.multiplicationMatrixVectorInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: vecR_matCxR_[non_]const +const vec_mat_cases = [2, 3, 4]. +flatMap((rows) => +[2, 3, 4].flatMap((cols) => +[true, false].map((nonConst) => ({ + [`vec${rows}_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateVectorMatrixToVectorCases( + sparseVectorF16Range(rows), + sparseMatrixF16Range(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f16.multiplicationVectorMatrixInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f16_matrix_vector_multiplication', { + ...mat_vec_cases, + ...vec_mat_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_vector_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_vector_multiplication.spec.js index 3cfcd5d4e1..d0262e0484 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_vector_multiplication.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_matrix_vector_multiplication.spec.js @@ -4,57 +4,14 @@ Execution Tests for matrix-vector and vector-matrix f16 multiplication expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16, TypeMat, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseMatrixF16Range, sparseVectorF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; +import { d } from './f16_matrix_vector_multiplication.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: matCxR_vecC_[non_]const -const mat_vec_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`mat${cols}x${rows}_vec${cols}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateMatrixVectorToVectorCases( - sparseMatrixF16Range(cols, rows), - sparseVectorF16Range(cols), - nonConst ? 'unfiltered' : 'finite', - FP.f16.multiplicationMatrixVectorInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: vecR_matCxR_[non_]const -const vec_mat_cases = [2, 3, 4]. -flatMap((rows) => -[2, 3, 4].flatMap((cols) => -[true, false].map((nonConst) => ({ - [`vec${rows}_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorMatrixToVectorCases( - sparseVectorF16Range(rows), - sparseMatrixF16Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f16.multiplicationVectorMatrixInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f16_matrix_vector_multiplication', { - ...mat_vec_cases, - ...vec_mat_cases -}); - g.test('matrix_vector'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -83,8 +40,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeMat(cols, rows, TypeF16), TypeVec(cols, TypeF16)], - TypeVec(rows, TypeF16), + [Type.mat(cols, rows, Type.f16), Type.vec(cols, Type.f16)], + Type.vec(rows, Type.f16), t.params, cases ); @@ -118,8 +75,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeVec(rows, TypeF16), TypeMat(cols, rows, TypeF16)], - TypeVec(cols, TypeF16), + [Type.vec(rows, Type.f16), Type.mat(cols, rows, Type.f16)], + Type.vec(cols, Type.f16), t.params, cases ); @@ -148,8 +105,8 @@ fn(async (t) => { await run( t, compoundBinary('*='), - [TypeVec(rows, TypeF16), TypeMat(cols, rows, TypeF16)], - TypeVec(cols, TypeF16), + [Type.vec(rows, Type.f16), Type.mat(cols, rows, Type.f16)], + Type.vec(cols, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_multiplication.cache.js new file mode 100644 index 0000000000..35ad006426 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_multiplication.cache.js @@ -0,0 +1,60 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF16Range, sparseVectorF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const multiplicationVectorScalarInterval = (v, s) => { + return FP.f16.toVector(v.map((e) => FP.f16.multiplicationInterval(e, s))); +}; + +const multiplicationScalarVectorInterval = (s, v) => { + return FP.f16.toVector(v.map((e) => FP.f16.multiplicationInterval(s, e))); +}; + +const scalar_cases = [true, false]. +map((nonConst) => ({ + [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarPairToIntervalCases( + sparseScalarF16Range(), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f16.multiplicationInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const vector_scalar_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateVectorScalarToVectorCases( + sparseVectorF16Range(dim), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + multiplicationVectorScalarInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarVectorToVectorCases( + sparseScalarF16Range(), + sparseVectorF16Range(dim), + nonConst ? 'unfiltered' : 'finite', + multiplicationScalarVectorInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f16_multiplication', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_multiplication.spec.js index 42310b240f..c9d264f949 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_multiplication.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_multiplication.spec.js @@ -4,73 +4,14 @@ Execution Tests for non-matrix f16 multiplication expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF16Range, sparseVectorF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -const multiplicationVectorScalarInterval = (v, s) => { - return FP.f16.toVector(v.map((e) => FP.f16.multiplicationInterval(e, s))); -}; - -const multiplicationScalarVectorInterval = (s, v) => { - return FP.f16.toVector(v.map((e) => FP.f16.multiplicationInterval(s, e))); -}; +import { d } from './f16_multiplication.cache.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = [true, false]. -map((nonConst) => ({ - [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarPairToIntervalCases( - sparseF16Range(), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f16.multiplicationInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const vector_scalar_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorScalarToVectorCases( - sparseVectorF16Range(dim), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - multiplicationVectorScalarInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarVectorToVectorCases( - sparseF16Range(), - sparseVectorF16Range(dim), - nonConst ? 'unfiltered' : 'finite', - multiplicationScalarVectorInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f16_multiplication', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -87,7 +28,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('*'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, binary('*'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('vector'). @@ -106,7 +47,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' // Using vectorize to generate vector cases based on scalar cases ); - await run(t, binary('*'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, binary('*'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('scalar_compound'). @@ -127,7 +68,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, compoundBinary('*='), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, compoundBinary('*='), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('vector_scalar'). @@ -150,8 +91,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeVec(dim, TypeF16), TypeF16], - TypeVec(dim, TypeF16), + [Type.vec(dim, Type.f16), Type.f16], + Type.vec(dim, Type.f16), t.params, cases ); @@ -177,8 +118,8 @@ fn(async (t) => { await run( t, compoundBinary('*='), - [TypeVec(dim, TypeF16), TypeF16], - TypeVec(dim, TypeF16), + [Type.vec(dim, Type.f16), Type.f16], + Type.vec(dim, Type.f16), t.params, cases ); @@ -204,8 +145,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeF16, TypeVec(dim, TypeF16)], - TypeVec(dim, TypeF16), + [Type.f16, Type.vec(dim, Type.f16)], + Type.vec(dim, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_remainder.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_remainder.cache.js new file mode 100644 index 0000000000..816fd1d510 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_remainder.cache.js @@ -0,0 +1,60 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF16Range, sparseVectorF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const remainderVectorScalarInterval = (v, s) => { + return FP.f16.toVector(v.map((e) => FP.f16.remainderInterval(e, s))); +}; + +const remainderScalarVectorInterval = (s, v) => { + return FP.f16.toVector(v.map((e) => FP.f16.remainderInterval(s, e))); +}; + +const scalar_cases = [true, false]. +map((nonConst) => ({ + [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarPairToIntervalCases( + sparseScalarF16Range(), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f16.remainderInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const vector_scalar_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateVectorScalarToVectorCases( + sparseVectorF16Range(dim), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + remainderVectorScalarInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarVectorToVectorCases( + sparseScalarF16Range(), + sparseVectorF16Range(dim), + nonConst ? 'unfiltered' : 'finite', + remainderScalarVectorInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f16_remainder', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_remainder.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_remainder.spec.js index e03aeee248..52aa994502 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_remainder.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_remainder.spec.js @@ -4,73 +4,14 @@ Execution Tests for non-matrix f16 remainder expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF16Range, sparseVectorF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -const remainderVectorScalarInterval = (v, s) => { - return FP.f16.toVector(v.map((e) => FP.f16.remainderInterval(e, s))); -}; - -const remainderScalarVectorInterval = (s, v) => { - return FP.f16.toVector(v.map((e) => FP.f16.remainderInterval(s, e))); -}; +import { d } from './f16_remainder.cache.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = [true, false]. -map((nonConst) => ({ - [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarPairToIntervalCases( - sparseF16Range(), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f16.remainderInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const vector_scalar_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorScalarToVectorCases( - sparseVectorF16Range(dim), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - remainderVectorScalarInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarVectorToVectorCases( - sparseF16Range(), - sparseVectorF16Range(dim), - nonConst ? 'unfiltered' : 'finite', - remainderScalarVectorInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f16_remainder', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -87,7 +28,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('%'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, binary('%'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('vector'). @@ -106,7 +47,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('%'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, binary('%'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('scalar_compound'). @@ -127,7 +68,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, compoundBinary('%='), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, compoundBinary('%='), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('vector_scalar'). @@ -150,8 +91,8 @@ fn(async (t) => { await run( t, binary('%'), - [TypeVec(dim, TypeF16), TypeF16], - TypeVec(dim, TypeF16), + [Type.vec(dim, Type.f16), Type.f16], + Type.vec(dim, Type.f16), t.params, cases ); @@ -177,8 +118,8 @@ fn(async (t) => { await run( t, compoundBinary('%='), - [TypeVec(dim, TypeF16), TypeF16], - TypeVec(dim, TypeF16), + [Type.vec(dim, Type.f16), Type.f16], + Type.vec(dim, Type.f16), t.params, cases ); @@ -204,8 +145,8 @@ fn(async (t) => { await run( t, binary('%'), - [TypeF16, TypeVec(dim, TypeF16)], - TypeVec(dim, TypeF16), + [Type.f16, Type.vec(dim, Type.f16)], + Type.vec(dim, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_subtraction.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_subtraction.cache.js new file mode 100644 index 0000000000..65ff0d7f18 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_subtraction.cache.js @@ -0,0 +1,60 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF16Range, sparseVectorF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const subtractionVectorScalarInterval = (v, s) => { + return FP.f16.toVector(v.map((e) => FP.f16.subtractionInterval(e, s))); +}; + +const subtractionScalarVectorInterval = (s, v) => { + return FP.f16.toVector(v.map((e) => FP.f16.subtractionInterval(s, e))); +}; + +const scalar_cases = [true, false]. +map((nonConst) => ({ + [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarPairToIntervalCases( + sparseScalarF16Range(), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f16.subtractionInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const vector_scalar_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateVectorScalarToVectorCases( + sparseVectorF16Range(dim), + sparseScalarF16Range(), + nonConst ? 'unfiltered' : 'finite', + subtractionVectorScalarInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateScalarVectorToVectorCases( + sparseScalarF16Range(), + sparseVectorF16Range(dim), + nonConst ? 'unfiltered' : 'finite', + subtractionScalarVectorInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f16_subtraction', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_subtraction.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_subtraction.spec.js index badf829b69..f5910cd986 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_subtraction.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f16_subtraction.spec.js @@ -4,73 +4,14 @@ Execution Tests for non-matrix f16 subtraction expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF16Range, sparseVectorF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -const subtractionVectorScalarInterval = (v, s) => { - return FP.f16.toVector(v.map((e) => FP.f16.subtractionInterval(e, s))); -}; - -const subtractionScalarVectorInterval = (s, v) => { - return FP.f16.toVector(v.map((e) => FP.f16.subtractionInterval(s, e))); -}; +import { d } from './f16_subtraction.cache.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = [true, false]. -map((nonConst) => ({ - [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarPairToIntervalCases( - sparseF16Range(), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f16.subtractionInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const vector_scalar_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorScalarToVectorCases( - sparseVectorF16Range(dim), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - subtractionVectorScalarInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateScalarVectorToVectorCases( - sparseF16Range(), - sparseVectorF16Range(dim), - nonConst ? 'unfiltered' : 'finite', - subtractionScalarVectorInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f16_subtraction', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -87,7 +28,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('-'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, binary('-'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('vector'). @@ -106,7 +47,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' // Using vectorize to generate vector cases based on scalar cases ); - await run(t, binary('-'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, binary('-'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('scalar_compound'). @@ -127,7 +68,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, compoundBinary('-='), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, compoundBinary('-='), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('vector_scalar'). @@ -150,8 +91,8 @@ fn(async (t) => { await run( t, binary('-'), - [TypeVec(dim, TypeF16), TypeF16], - TypeVec(dim, TypeF16), + [Type.vec(dim, Type.f16), Type.f16], + Type.vec(dim, Type.f16), t.params, cases ); @@ -177,8 +118,8 @@ fn(async (t) => { await run( t, compoundBinary('-='), - [TypeVec(dim, TypeF16), TypeF16], - TypeVec(dim, TypeF16), + [Type.vec(dim, Type.f16), Type.f16], + Type.vec(dim, Type.f16), t.params, cases ); @@ -204,8 +145,8 @@ fn(async (t) => { await run( t, binary('-'), - [TypeF16, TypeVec(dim, TypeF16)], - TypeVec(dim, TypeF16), + [Type.f16, Type.vec(dim, Type.f16)], + Type.vec(dim, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_addition.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_addition.cache.js new file mode 100644 index 0000000000..65c280ce3b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_addition.cache.js @@ -0,0 +1,60 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF32Range, sparseVectorF32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const additionVectorScalarInterval = (v, s) => { + return FP.f32.toVector(v.map((e) => FP.f32.additionInterval(e, s))); +}; + +const additionScalarVectorInterval = (s, v) => { + return FP.f32.toVector(v.map((e) => FP.f32.additionInterval(s, e))); +}; + +const scalar_cases = [true, false]. +map((nonConst) => ({ + [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarPairToIntervalCases( + sparseScalarF32Range(), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f32.additionInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const vector_scalar_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateVectorScalarToVectorCases( + sparseVectorF32Range(dim), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + additionVectorScalarInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarVectorToVectorCases( + sparseScalarF32Range(), + sparseVectorF32Range(dim), + nonConst ? 'unfiltered' : 'finite', + additionScalarVectorInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f32_addition', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_addition.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_addition.spec.js index a4dff15436..6c9adbb126 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_addition.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_addition.spec.js @@ -4,73 +4,14 @@ Execution Tests for non-matrix f32 addition expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF32Range, sparseVectorF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -const additionVectorScalarInterval = (v, s) => { - return FP.f32.toVector(v.map((e) => FP.f32.additionInterval(e, s))); -}; - -const additionScalarVectorInterval = (s, v) => { - return FP.f32.toVector(v.map((e) => FP.f32.additionInterval(s, e))); -}; +import { d } from './f32_addition.cache.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = [true, false]. -map((nonConst) => ({ - [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarPairToIntervalCases( - sparseF32Range(), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f32.additionInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const vector_scalar_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorScalarToVectorCases( - sparseVectorF32Range(dim), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - additionVectorScalarInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarVectorToVectorCases( - sparseF32Range(), - sparseVectorF32Range(dim), - nonConst ? 'unfiltered' : 'finite', - additionScalarVectorInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f32_addition', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -84,7 +25,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('+'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, binary('+'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('vector'). @@ -100,7 +41,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' // Using vectorize to generate vector cases based on scalar cases ); - await run(t, binary('+'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, binary('+'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('scalar_compound'). @@ -118,7 +59,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, compoundBinary('+='), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, compoundBinary('+='), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('vector_scalar'). @@ -138,8 +79,8 @@ fn(async (t) => { await run( t, binary('+'), - [TypeVec(dim, TypeF32), TypeF32], - TypeVec(dim, TypeF32), + [Type.vec(dim, Type.f32), Type.f32], + Type.vec(dim, Type.f32), t.params, cases ); @@ -162,8 +103,8 @@ fn(async (t) => { await run( t, compoundBinary('+='), - [TypeVec(dim, TypeF32), TypeF32], - TypeVec(dim, TypeF32), + [Type.vec(dim, Type.f32), Type.f32], + Type.vec(dim, Type.f32), t.params, cases ); @@ -186,8 +127,8 @@ fn(async (t) => { await run( t, binary('+'), - [TypeF32, TypeVec(dim, TypeF32)], - TypeVec(dim, TypeF32), + [Type.f32, Type.vec(dim, Type.f32)], + Type.vec(dim, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_comparison.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_comparison.cache.js new file mode 100644 index 0000000000..6ed518e519 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_comparison.cache.js @@ -0,0 +1,144 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { anyOf } from '../../../../util/compare.js';import { bool, f32 } from '../../../../util/conversion.js';import { flushSubnormalNumberF32, vectorF32Range } from '../../../../util/math.js'; + +import { makeCaseCache } from '../case_cache.js'; + +/** + * @returns a test case for the provided left hand & right hand values and truth function. + * Handles quantization and subnormals. + */ +function makeCase( +lhs, +rhs, +truthFunc) +{ + // Subnormal float values may be flushed at any time. + // https://www.w3.org/TR/WGSL/#floating-point-evaluation + const f32_lhs = f32(lhs); + const f32_rhs = f32(rhs); + const lhs_options = new Set([f32_lhs, f32(flushSubnormalNumberF32(lhs))]); + const rhs_options = new Set([f32_rhs, f32(flushSubnormalNumberF32(rhs))]); + const expected = []; + lhs_options.forEach((l) => { + rhs_options.forEach((r) => { + const result = bool(truthFunc(l, r)); + if (!expected.includes(result)) { + expected.push(result); + } + }); + }); + + return { input: [f32_lhs, f32_rhs], expected: anyOf(...expected) }; +} + +export const d = makeCaseCache('binary/f32_logical', { + equals_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value === rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + equals_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value === rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + not_equals_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value !== rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + not_equals_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value !== rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + less_than_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value < rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + less_than_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value < rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + less_equals_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value <= rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + less_equals_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value <= rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + greater_than_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value > rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + greater_than_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value > rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + greater_equals_non_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value >= rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + }, + greater_equals_const: () => { + const truthFunc = (lhs, rhs) => { + return lhs.value >= rhs.value; + }; + + return vectorF32Range(2).map((v) => { + return makeCase(v[0], v[1], truthFunc); + }); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_comparison.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_comparison.spec.js index dddf58cb3f..2c362db2ed 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_comparison.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_comparison.spec.js @@ -4,155 +4,14 @@ Execution Tests for the f32 comparison operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { anyOf } from '../../../../util/compare.js'; -import { bool, f32, TypeBool, TypeF32 } from '../../../../util/conversion.js'; -import { flushSubnormalNumberF32, vectorF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary } from './binary.js'; +import { d } from './f32_comparison.cache.js'; export const g = makeTestGroup(GPUTest); -/** - * @returns a test case for the provided left hand & right hand values and truth function. - * Handles quantization and subnormals. - */ -function makeCase( -lhs, -rhs, -truthFunc) -{ - // Subnormal float values may be flushed at any time. - // https://www.w3.org/TR/WGSL/#floating-point-evaluation - const f32_lhs = f32(lhs); - const f32_rhs = f32(rhs); - const lhs_options = new Set([f32_lhs, f32(flushSubnormalNumberF32(lhs))]); - const rhs_options = new Set([f32_rhs, f32(flushSubnormalNumberF32(rhs))]); - const expected = []; - lhs_options.forEach((l) => { - rhs_options.forEach((r) => { - const result = bool(truthFunc(l, r)); - if (!expected.includes(result)) { - expected.push(result); - } - }); - }); - - return { input: [f32_lhs, f32_rhs], expected: anyOf(...expected) }; -} - -export const d = makeCaseCache('binary/f32_logical', { - equals_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value === rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - equals_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value === rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - not_equals_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value !== rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - not_equals_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value !== rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - less_than_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value < rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - less_than_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value < rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - less_equals_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value <= rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - less_equals_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value <= rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - greater_than_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value > rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - greater_than_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value > rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - greater_equals_non_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value >= rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - }, - greater_equals_const: () => { - const truthFunc = (lhs, rhs) => { - return lhs.value >= rhs.value; - }; - - return vectorF32Range(2).map((v) => { - return makeCase(v[0], v[1], truthFunc); - }); - } -}); - g.test('equals'). specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). desc( @@ -168,7 +27,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'equals_const' : 'equals_non_const' ); - await run(t, binary('=='), [TypeF32, TypeF32], TypeBool, t.params, cases); + await run(t, binary('=='), [Type.f32, Type.f32], Type.bool, t.params, cases); }); g.test('not_equals'). @@ -186,7 +45,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'not_equals_const' : 'not_equals_non_const' ); - await run(t, binary('!='), [TypeF32, TypeF32], TypeBool, t.params, cases); + await run(t, binary('!='), [Type.f32, Type.f32], Type.bool, t.params, cases); }); g.test('less_than'). @@ -204,7 +63,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'less_than_const' : 'less_than_non_const' ); - await run(t, binary('<'), [TypeF32, TypeF32], TypeBool, t.params, cases); + await run(t, binary('<'), [Type.f32, Type.f32], Type.bool, t.params, cases); }); g.test('less_equals'). @@ -222,7 +81,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'less_equals_const' : 'less_equals_non_const' ); - await run(t, binary('<='), [TypeF32, TypeF32], TypeBool, t.params, cases); + await run(t, binary('<='), [Type.f32, Type.f32], Type.bool, t.params, cases); }); g.test('greater_than'). @@ -240,7 +99,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'greater_than_const' : 'greater_than_non_const' ); - await run(t, binary('>'), [TypeF32, TypeF32], TypeBool, t.params, cases); + await run(t, binary('>'), [Type.f32, Type.f32], Type.bool, t.params, cases); }); g.test('greater_equals'). @@ -258,5 +117,5 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'greater_equals_const' : 'greater_equals_non_const' ); - await run(t, binary('>='), [TypeF32, TypeF32], TypeBool, t.params, cases); + await run(t, binary('>='), [Type.f32, Type.f32], Type.bool, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_division.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_division.cache.js new file mode 100644 index 0000000000..987cb3676f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_division.cache.js @@ -0,0 +1,60 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF32Range, sparseVectorF32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const divisionVectorScalarInterval = (v, s) => { + return FP.f32.toVector(v.map((e) => FP.f32.divisionInterval(e, s))); +}; + +const divisionScalarVectorInterval = (s, v) => { + return FP.f32.toVector(v.map((e) => FP.f32.divisionInterval(s, e))); +}; + +const scalar_cases = [true, false]. +map((nonConst) => ({ + [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarPairToIntervalCases( + sparseScalarF32Range(), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f32.divisionInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const vector_scalar_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateVectorScalarToVectorCases( + sparseVectorF32Range(dim), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + divisionVectorScalarInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarVectorToVectorCases( + sparseScalarF32Range(), + sparseVectorF32Range(dim), + nonConst ? 'unfiltered' : 'finite', + divisionScalarVectorInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f32_division', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_division.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_division.spec.js index 66573b123c..fc752b9e3a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_division.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_division.spec.js @@ -4,73 +4,14 @@ Execution Tests for non-matrix f32 division expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF32Range, sparseVectorF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -const divisionVectorScalarInterval = (v, s) => { - return FP.f32.toVector(v.map((e) => FP.f32.divisionInterval(e, s))); -}; - -const divisionScalarVectorInterval = (s, v) => { - return FP.f32.toVector(v.map((e) => FP.f32.divisionInterval(s, e))); -}; +import { d } from './f32_division.cache.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = [true, false]. -map((nonConst) => ({ - [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarPairToIntervalCases( - sparseF32Range(), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f32.divisionInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const vector_scalar_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorScalarToVectorCases( - sparseVectorF32Range(dim), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - divisionVectorScalarInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarVectorToVectorCases( - sparseF32Range(), - sparseVectorF32Range(dim), - nonConst ? 'unfiltered' : 'finite', - divisionScalarVectorInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f32_division', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -84,7 +25,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('/'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, binary('/'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('vector'). @@ -100,7 +41,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' // Using vectorize to generate vector cases based on scalar cases ); - await run(t, binary('/'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, binary('/'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('scalar_compound'). @@ -118,7 +59,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, compoundBinary('/='), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, compoundBinary('/='), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('vector_scalar'). @@ -138,8 +79,8 @@ fn(async (t) => { await run( t, binary('/'), - [TypeVec(dim, TypeF32), TypeF32], - TypeVec(dim, TypeF32), + [Type.vec(dim, Type.f32), Type.f32], + Type.vec(dim, Type.f32), t.params, cases ); @@ -162,8 +103,8 @@ fn(async (t) => { await run( t, compoundBinary('/='), - [TypeVec(dim, TypeF32), TypeF32], - TypeVec(dim, TypeF32), + [Type.vec(dim, Type.f32), Type.f32], + Type.vec(dim, Type.f32), t.params, cases ); @@ -186,8 +127,8 @@ fn(async (t) => { await run( t, binary('/'), - [TypeF32, TypeVec(dim, TypeF32)], - TypeVec(dim, TypeF32), + [Type.f32, Type.vec(dim, Type.f32)], + Type.vec(dim, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_addition.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_addition.cache.js new file mode 100644 index 0000000000..b3c7bec492 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_addition.cache.js @@ -0,0 +1,23 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR_[non_]const +const mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateMatrixPairToMatrixCases( + sparseMatrixF32Range(cols, rows), + sparseMatrixF32Range(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f32.additionMatrixMatrixInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f32_matrix_addition', mat_cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_addition.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_addition.spec.js index f203990550..7da49853cc 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_addition.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_addition.spec.js @@ -4,36 +4,14 @@ Execution Tests for matrix f32 addition expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32, TypeMat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseMatrixF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; +import { d } from './f32_matrix_addition.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: matCxR_[non_]const -const mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateMatrixPairToMatrixCases( - sparseMatrixF32Range(cols, rows), - sparseMatrixF32Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f32.additionMatrixMatrixInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f32_matrix_addition', mat_cases); - g.test('matrix'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -57,8 +35,8 @@ fn(async (t) => { await run( t, binary('+'), - [TypeMat(cols, rows, TypeF32), TypeMat(cols, rows, TypeF32)], - TypeMat(cols, rows, TypeF32), + [Type.mat(cols, rows, Type.f32), Type.mat(cols, rows, Type.f32)], + Type.mat(cols, rows, Type.f32), t.params, cases ); @@ -87,8 +65,8 @@ fn(async (t) => { await run( t, compoundBinary('+='), - [TypeMat(cols, rows, TypeF32), TypeMat(cols, rows, TypeF32)], - TypeMat(cols, rows, TypeF32), + [Type.mat(cols, rows, Type.f32), Type.mat(cols, rows, Type.f32)], + Type.mat(cols, rows, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_matrix_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_matrix_multiplication.cache.js new file mode 100644 index 0000000000..4d5382f649 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_matrix_multiplication.cache.js @@ -0,0 +1,25 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +// Cases: matKxR_matCxK_[non_]const +const mat_mat_cases = [2, 3, 4]. +flatMap((k) => +[2, 3, 4].flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`mat${k}x${rows}_mat${cols}x${k}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateMatrixPairToMatrixCases( + sparseMatrixF32Range(k, rows), + sparseMatrixF32Range(cols, k), + nonConst ? 'unfiltered' : 'finite', + FP.f32.multiplicationMatrixMatrixInterval + ); + } +})) +) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f32_matrix_matrix_multiplication', mat_mat_cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_matrix_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_matrix_multiplication.spec.js index bebbaa701a..bee27aea4c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_matrix_multiplication.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_matrix_multiplication.spec.js @@ -4,38 +4,14 @@ Execution Tests for matrix-matrix f32 multiplication expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32, TypeMat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseMatrixF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; +import { d } from './f32_matrix_matrix_multiplication.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: matKxR_matCxK_[non_]const -const mat_mat_cases = [2, 3, 4]. -flatMap((k) => -[2, 3, 4].flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`mat${k}x${rows}_mat${cols}x${k}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateMatrixPairToMatrixCases( - sparseMatrixF32Range(k, rows), - sparseMatrixF32Range(cols, k), - nonConst ? 'unfiltered' : 'finite', - FP.f32.multiplicationMatrixMatrixInterval - ); - } -})) -) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f32_matrix_matrix_multiplication', mat_mat_cases); - g.test('matrix_matrix'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -65,8 +41,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeMat(x_cols, x_rows, TypeF32), TypeMat(y_cols, y_rows, TypeF32)], - TypeMat(y_cols, x_rows, TypeF32), + [Type.mat(x_cols, x_rows, Type.f32), Type.mat(y_cols, y_rows, Type.f32)], + Type.mat(y_cols, x_rows, Type.f32), t.params, cases ); @@ -100,8 +76,8 @@ fn(async (t) => { await run( t, compoundBinary('*='), - [TypeMat(x_cols, x_rows, TypeF32), TypeMat(y_cols, y_rows, TypeF32)], - TypeMat(y_cols, x_rows, TypeF32), + [Type.mat(x_cols, x_rows, Type.f32), Type.mat(y_cols, y_rows, Type.f32)], + Type.mat(y_cols, x_rows, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_scalar_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_scalar_multiplication.cache.js new file mode 100644 index 0000000000..cc3321acb7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_scalar_multiplication.cache.js @@ -0,0 +1,44 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF32Range, sparseScalarF32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR_scalar_[non_]const +const mat_scalar_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`mat${cols}x${rows}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateMatrixScalarToMatrixCases( + sparseMatrixF32Range(cols, rows), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f32.multiplicationMatrixScalarInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: scalar_matCxR_[non_]const +const scalar_mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`scalar_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarMatrixToMatrixCases( + sparseScalarF32Range(), + sparseMatrixF32Range(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f32.multiplicationScalarMatrixInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f32_matrix_scalar_multiplication', { + ...mat_scalar_cases, + ...scalar_mat_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_scalar_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_scalar_multiplication.spec.js index 324998e915..918cbc49d6 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_scalar_multiplication.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_scalar_multiplication.spec.js @@ -4,57 +4,14 @@ Execution Tests for matrix-scalar and scalar-matrix f32 multiplication expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32, TypeMat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF32Range, sparseMatrixF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; +import { d } from './f32_matrix_scalar_multiplication.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: matCxR_scalar_[non_]const -const mat_scalar_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`mat${cols}x${rows}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateMatrixScalarToMatrixCases( - sparseMatrixF32Range(cols, rows), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f32.multiplicationMatrixScalarInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: scalar_matCxR_[non_]const -const scalar_mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`scalar_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarMatrixToMatrixCases( - sparseF32Range(), - sparseMatrixF32Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f32.multiplicationScalarMatrixInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f32_matrix_scalar_multiplication', { - ...mat_scalar_cases, - ...scalar_mat_cases -}); - g.test('matrix_scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -80,8 +37,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeMat(cols, rows, TypeF32), TypeF32], - TypeMat(cols, rows, TypeF32), + [Type.mat(cols, rows, Type.f32), Type.f32], + Type.mat(cols, rows, Type.f32), t.params, cases ); @@ -112,8 +69,8 @@ fn(async (t) => { await run( t, compoundBinary('*='), - [TypeMat(cols, rows, TypeF32), TypeF32], - TypeMat(cols, rows, TypeF32), + [Type.mat(cols, rows, Type.f32), Type.f32], + Type.mat(cols, rows, Type.f32), t.params, cases ); @@ -144,8 +101,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeF32, TypeMat(cols, rows, TypeF32)], - TypeMat(cols, rows, TypeF32), + [Type.f32, Type.mat(cols, rows, Type.f32)], + Type.mat(cols, rows, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_subtraction.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_subtraction.cache.js new file mode 100644 index 0000000000..61a60d8e49 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_subtraction.cache.js @@ -0,0 +1,23 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR_[non_]const +const mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateMatrixPairToMatrixCases( + sparseMatrixF32Range(cols, rows), + sparseMatrixF32Range(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f32.subtractionMatrixMatrixInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f32_matrix_subtraction', mat_cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_subtraction.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_subtraction.spec.js index c427c8d5bd..9c6930a63c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_subtraction.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_subtraction.spec.js @@ -4,36 +4,14 @@ Execution Tests for matrix f32 subtraction expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32, TypeMat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseMatrixF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; +import { d } from './f32_matrix_subtraction.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: matCxR_[non_]const -const mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateMatrixPairToMatrixCases( - sparseMatrixF32Range(cols, rows), - sparseMatrixF32Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f32.subtractionMatrixMatrixInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f32_matrix_subtraction', mat_cases); - g.test('matrix'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -57,8 +35,8 @@ fn(async (t) => { await run( t, binary('-'), - [TypeMat(cols, rows, TypeF32), TypeMat(cols, rows, TypeF32)], - TypeMat(cols, rows, TypeF32), + [Type.mat(cols, rows, Type.f32), Type.mat(cols, rows, Type.f32)], + Type.mat(cols, rows, Type.f32), t.params, cases ); @@ -87,8 +65,8 @@ fn(async (t) => { await run( t, compoundBinary('-='), - [TypeMat(cols, rows, TypeF32), TypeMat(cols, rows, TypeF32)], - TypeMat(cols, rows, TypeF32), + [Type.mat(cols, rows, Type.f32), Type.mat(cols, rows, Type.f32)], + Type.mat(cols, rows, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_vector_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_vector_multiplication.cache.js new file mode 100644 index 0000000000..778c0500f8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_vector_multiplication.cache.js @@ -0,0 +1,44 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseMatrixF32Range, sparseVectorF32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +// Cases: matCxR_vecC_[non_]const +const mat_vec_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`mat${cols}x${rows}_vec${cols}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateMatrixVectorToVectorCases( + sparseMatrixF32Range(cols, rows), + sparseVectorF32Range(cols), + nonConst ? 'unfiltered' : 'finite', + FP.f32.multiplicationMatrixVectorInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: vecR_matCxR_[non_]const +const vec_mat_cases = [2, 3, 4]. +flatMap((rows) => +[2, 3, 4].flatMap((cols) => +[true, false].map((nonConst) => ({ + [`vec${rows}_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateVectorMatrixToVectorCases( + sparseVectorF32Range(rows), + sparseMatrixF32Range(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f32.multiplicationVectorMatrixInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f32_matrix_vector_multiplication', { + ...mat_vec_cases, + ...vec_mat_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_vector_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_vector_multiplication.spec.js index 8149f4a140..dc2d9a2604 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_vector_multiplication.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_matrix_vector_multiplication.spec.js @@ -4,57 +4,14 @@ Execution Tests for matrix-vector and vector-matrix f32 multiplication expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32, TypeMat, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseMatrixF32Range, sparseVectorF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; +import { d } from './f32_matrix_vector_multiplication.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: matCxR_vecC_[non_]const -const mat_vec_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`mat${cols}x${rows}_vec${cols}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateMatrixVectorToVectorCases( - sparseMatrixF32Range(cols, rows), - sparseVectorF32Range(cols), - nonConst ? 'unfiltered' : 'finite', - FP.f32.multiplicationMatrixVectorInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: vecR_matCxR_[non_]const -const vec_mat_cases = [2, 3, 4]. -flatMap((rows) => -[2, 3, 4].flatMap((cols) => -[true, false].map((nonConst) => ({ - [`vec${rows}_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorMatrixToVectorCases( - sparseVectorF32Range(rows), - sparseMatrixF32Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f32.multiplicationVectorMatrixInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f32_matrix_vector_multiplication', { - ...mat_vec_cases, - ...vec_mat_cases -}); - g.test('matrix_vector'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -80,8 +37,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeMat(cols, rows, TypeF32), TypeVec(cols, TypeF32)], - TypeVec(rows, TypeF32), + [Type.mat(cols, rows, Type.f32), Type.vec(cols, Type.f32)], + Type.vec(rows, Type.f32), t.params, cases ); @@ -112,8 +69,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeVec(rows, TypeF32), TypeMat(cols, rows, TypeF32)], - TypeVec(cols, TypeF32), + [Type.vec(rows, Type.f32), Type.mat(cols, rows, Type.f32)], + Type.vec(cols, Type.f32), t.params, cases ); @@ -139,8 +96,8 @@ fn(async (t) => { await run( t, compoundBinary('*='), - [TypeVec(rows, TypeF32), TypeMat(cols, rows, TypeF32)], - TypeVec(cols, TypeF32), + [Type.vec(rows, Type.f32), Type.mat(cols, rows, Type.f32)], + Type.vec(cols, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_multiplication.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_multiplication.cache.js new file mode 100644 index 0000000000..3135f87b29 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_multiplication.cache.js @@ -0,0 +1,60 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF32Range, sparseVectorF32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const multiplicationVectorScalarInterval = (v, s) => { + return FP.f32.toVector(v.map((e) => FP.f32.multiplicationInterval(e, s))); +}; + +const multiplicationScalarVectorInterval = (s, v) => { + return FP.f32.toVector(v.map((e) => FP.f32.multiplicationInterval(s, e))); +}; + +const scalar_cases = [true, false]. +map((nonConst) => ({ + [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarPairToIntervalCases( + sparseScalarF32Range(), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f32.multiplicationInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const vector_scalar_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateVectorScalarToVectorCases( + sparseVectorF32Range(dim), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + multiplicationVectorScalarInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarVectorToVectorCases( + sparseScalarF32Range(), + sparseVectorF32Range(dim), + nonConst ? 'unfiltered' : 'finite', + multiplicationScalarVectorInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f32_multiplication', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_multiplication.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_multiplication.spec.js index dd60365d5d..c7a737a876 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_multiplication.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_multiplication.spec.js @@ -4,73 +4,14 @@ Execution Tests for non-matrix f32 multiplication expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF32Range, sparseVectorF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -const multiplicationVectorScalarInterval = (v, s) => { - return FP.f32.toVector(v.map((e) => FP.f32.multiplicationInterval(e, s))); -}; - -const multiplicationScalarVectorInterval = (s, v) => { - return FP.f32.toVector(v.map((e) => FP.f32.multiplicationInterval(s, e))); -}; +import { d } from './f32_multiplication.cache.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = [true, false]. -map((nonConst) => ({ - [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarPairToIntervalCases( - sparseF32Range(), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f32.multiplicationInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const vector_scalar_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorScalarToVectorCases( - sparseVectorF32Range(dim), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - multiplicationVectorScalarInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarVectorToVectorCases( - sparseF32Range(), - sparseVectorF32Range(dim), - nonConst ? 'unfiltered' : 'finite', - multiplicationScalarVectorInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f32_multiplication', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -84,7 +25,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('*'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, binary('*'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('vector'). @@ -100,7 +41,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' // Using vectorize to generate vector cases based on scalar cases ); - await run(t, binary('*'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, binary('*'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('scalar_compound'). @@ -118,7 +59,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, compoundBinary('*='), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, compoundBinary('*='), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('vector_scalar'). @@ -138,8 +79,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeVec(dim, TypeF32), TypeF32], - TypeVec(dim, TypeF32), + [Type.vec(dim, Type.f32), Type.f32], + Type.vec(dim, Type.f32), t.params, cases ); @@ -162,8 +103,8 @@ fn(async (t) => { await run( t, compoundBinary('*='), - [TypeVec(dim, TypeF32), TypeF32], - TypeVec(dim, TypeF32), + [Type.vec(dim, Type.f32), Type.f32], + Type.vec(dim, Type.f32), t.params, cases ); @@ -186,8 +127,8 @@ fn(async (t) => { await run( t, binary('*'), - [TypeF32, TypeVec(dim, TypeF32)], - TypeVec(dim, TypeF32), + [Type.f32, Type.vec(dim, Type.f32)], + Type.vec(dim, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_remainder.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_remainder.cache.js new file mode 100644 index 0000000000..62f9c4f85c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_remainder.cache.js @@ -0,0 +1,64 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for non-matrix f32 remainder expression +`;import { FP } from '../../../../util/floating_point.js'; +import { sparseScalarF32Range, sparseVectorF32Range } from '../../../../util/math.js'; +import { makeCaseCache } from '../case_cache.js'; + +const remainderVectorScalarInterval = (v, s) => { + return FP.f32.toVector(v.map((e) => FP.f32.remainderInterval(e, s))); +}; + +const remainderScalarVectorInterval = (s, v) => { + return FP.f32.toVector(v.map((e) => FP.f32.remainderInterval(s, e))); +}; + +const scalar_cases = [true, false]. +map((nonConst) => ({ + [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarPairToIntervalCases( + sparseScalarF32Range(), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f32.remainderInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const vector_scalar_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateVectorScalarToVectorCases( + sparseVectorF32Range(dim), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + remainderVectorScalarInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarVectorToVectorCases( + sparseScalarF32Range(), + sparseVectorF32Range(dim), + nonConst ? 'unfiltered' : 'finite', + remainderScalarVectorInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f32_remainder', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_remainder.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_remainder.spec.js index 2b569180ee..aab16e65e9 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_remainder.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_remainder.spec.js @@ -4,73 +4,14 @@ Execution Tests for non-matrix f32 remainder expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF32Range, sparseVectorF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -const remainderVectorScalarInterval = (v, s) => { - return FP.f32.toVector(v.map((e) => FP.f32.remainderInterval(e, s))); -}; - -const remainderScalarVectorInterval = (s, v) => { - return FP.f32.toVector(v.map((e) => FP.f32.remainderInterval(s, e))); -}; +import { d } from './f32_remainder.cache.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = [true, false]. -map((nonConst) => ({ - [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarPairToIntervalCases( - sparseF32Range(), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f32.remainderInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const vector_scalar_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorScalarToVectorCases( - sparseVectorF32Range(dim), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - remainderVectorScalarInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarVectorToVectorCases( - sparseF32Range(), - sparseVectorF32Range(dim), - nonConst ? 'unfiltered' : 'finite', - remainderScalarVectorInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f32_remainder', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -84,7 +25,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('%'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, binary('%'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('vector'). @@ -100,7 +41,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' // Using vectorize to generate vector cases based on scalar cases ); - await run(t, binary('%'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, binary('%'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('scalar_compound'). @@ -118,7 +59,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, compoundBinary('%='), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, compoundBinary('%='), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('vector_scalar'). @@ -138,8 +79,8 @@ fn(async (t) => { await run( t, binary('%'), - [TypeVec(dim, TypeF32), TypeF32], - TypeVec(dim, TypeF32), + [Type.vec(dim, Type.f32), Type.f32], + Type.vec(dim, Type.f32), t.params, cases ); @@ -162,8 +103,8 @@ fn(async (t) => { await run( t, compoundBinary('%='), - [TypeVec(dim, TypeF32), TypeF32], - TypeVec(dim, TypeF32), + [Type.vec(dim, Type.f32), Type.f32], + Type.vec(dim, Type.f32), t.params, cases ); @@ -186,8 +127,8 @@ fn(async (t) => { await run( t, binary('%'), - [TypeF32, TypeVec(dim, TypeF32)], - TypeVec(dim, TypeF32), + [Type.f32, Type.vec(dim, Type.f32)], + Type.vec(dim, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_subtraction.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_subtraction.cache.js new file mode 100644 index 0000000000..d328133b14 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_subtraction.cache.js @@ -0,0 +1,60 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { sparseScalarF32Range, sparseVectorF32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +const subtractionVectorScalarInterval = (v, s) => { + return FP.f32.toVector(v.map((e) => FP.f32.subtractionInterval(e, s))); +}; + +const subtractionScalarVectorInterval = (s, v) => { + return FP.f32.toVector(v.map((e) => FP.f32.subtractionInterval(s, e))); +}; + +const scalar_cases = [true, false]. +map((nonConst) => ({ + [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarPairToIntervalCases( + sparseScalarF32Range(), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + FP.f32.subtractionInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +const vector_scalar_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateVectorScalarToVectorCases( + sparseVectorF32Range(dim), + sparseScalarF32Range(), + nonConst ? 'unfiltered' : 'finite', + subtractionVectorScalarInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const scalar_vector_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateScalarVectorToVectorCases( + sparseScalarF32Range(), + sparseVectorF32Range(dim), + nonConst ? 'unfiltered' : 'finite', + subtractionScalarVectorInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('binary/f32_subtraction', { + ...scalar_cases, + ...vector_scalar_cases, + ...scalar_vector_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_subtraction.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_subtraction.spec.js index fe3ed8783a..92325e6550 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_subtraction.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_subtraction.spec.js @@ -4,73 +4,14 @@ Execution Tests for non-matrix f32 subtraction expression `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32, TypeVec } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { sparseF32Range, sparseVectorF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -const subtractionVectorScalarInterval = (v, s) => { - return FP.f32.toVector(v.map((e) => FP.f32.subtractionInterval(e, s))); -}; - -const subtractionScalarVectorInterval = (s, v) => { - return FP.f32.toVector(v.map((e) => FP.f32.subtractionInterval(s, e))); -}; +import { d } from './f32_subtraction.cache.js'; export const g = makeTestGroup(GPUTest); -const scalar_cases = [true, false]. -map((nonConst) => ({ - [`scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarPairToIntervalCases( - sparseF32Range(), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - FP.f32.subtractionInterval - ); - } -})). -reduce((a, b) => ({ ...a, ...b }), {}); - -const vector_scalar_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorScalarToVectorCases( - sparseVectorF32Range(dim), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - subtractionVectorScalarInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -const scalar_vector_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`scalar_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateScalarVectorToVectorCases( - sparseF32Range(), - sparseVectorF32Range(dim), - nonConst ? 'unfiltered' : 'finite', - subtractionScalarVectorInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('binary/f32_subtraction', { - ...scalar_cases, - ...vector_scalar_cases, - ...scalar_vector_cases -}); - g.test('scalar'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -84,7 +25,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, binary('-'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, binary('-'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('vector'). @@ -100,7 +41,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' // Using vectorize to generate vector cases based on scalar cases ); - await run(t, binary('-'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, binary('-'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('scalar_compound'). @@ -118,7 +59,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'scalar_const' : 'scalar_non_const' ); - await run(t, compoundBinary('-='), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, compoundBinary('-='), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('vector_scalar'). @@ -138,8 +79,8 @@ fn(async (t) => { await run( t, binary('-'), - [TypeVec(dim, TypeF32), TypeF32], - TypeVec(dim, TypeF32), + [Type.vec(dim, Type.f32), Type.f32], + Type.vec(dim, Type.f32), t.params, cases ); @@ -162,8 +103,8 @@ fn(async (t) => { await run( t, compoundBinary('-='), - [TypeVec(dim, TypeF32), TypeF32], - TypeVec(dim, TypeF32), + [Type.vec(dim, Type.f32), Type.f32], + Type.vec(dim, Type.f32), t.params, cases ); @@ -186,8 +127,8 @@ fn(async (t) => { await run( t, binary('-'), - [TypeF32, TypeVec(dim, TypeF32)], - TypeVec(dim, TypeF32), + [Type.f32, Type.vec(dim, Type.f32)], + Type.vec(dim, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.cache.js new file mode 100644 index 0000000000..c1ceca4ec6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.cache.js @@ -0,0 +1,306 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kValue } from '../../../../util/constants.js';import { sparseI32Range, vectorI32Range } from '../../../../util/math.js';import { + generateBinaryToI32Cases, + generateI32VectorBinaryToVectorCases, + generateVectorI32BinaryToVectorCases } from +'../case.js'; +import { makeCaseCache } from '../case_cache.js'; + +function i32_add(x, y) { + return x + y; +} + +function i32_subtract(x, y) { + return x - y; +} + +function i32_multiply(x, y) { + return Math.imul(x, y); +} + +function i32_divide_non_const(x, y) { + if (y === 0) { + return x; + } + if (x === kValue.i32.negative.min && y === -1) { + return x; + } + return x / y; +} + +function i32_divide_const(x, y) { + if (y === 0) { + return undefined; + } + if (x === kValue.i32.negative.min && y === -1) { + return undefined; + } + return x / y; +} + +function i32_remainder_non_const(x, y) { + if (y === 0) { + return 0; + } + if (x === kValue.i32.negative.min && y === -1) { + return 0; + } + return x % y; +} + +function i32_remainder_const(x, y) { + if (y === 0) { + return undefined; + } + if (x === kValue.i32.negative.min && y === -1) { + return undefined; + } + return x % y; +} + +export const d = makeCaseCache('binary/i32_arithmetic', { + addition: () => { + return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_add); + }, + subtraction: () => { + return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_subtract); + }, + multiplication: () => { + return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_multiply); + }, + division_non_const: () => { + return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_divide_non_const); + }, + division_const: () => { + return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_divide_const); + }, + remainder_non_const: () => { + return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_remainder_non_const); + }, + remainder_const: () => { + return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_remainder_const); + }, + addition_scalar_vector2: () => { + return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(2), i32_add); + }, + addition_scalar_vector3: () => { + return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(3), i32_add); + }, + addition_scalar_vector4: () => { + return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(4), i32_add); + }, + addition_vector2_scalar: () => { + return generateVectorI32BinaryToVectorCases(vectorI32Range(2), sparseI32Range(), i32_add); + }, + addition_vector3_scalar: () => { + return generateVectorI32BinaryToVectorCases(vectorI32Range(3), sparseI32Range(), i32_add); + }, + addition_vector4_scalar: () => { + return generateVectorI32BinaryToVectorCases(vectorI32Range(4), sparseI32Range(), i32_add); + }, + subtraction_scalar_vector2: () => { + return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(2), i32_subtract); + }, + subtraction_scalar_vector3: () => { + return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(3), i32_subtract); + }, + subtraction_scalar_vector4: () => { + return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(4), i32_subtract); + }, + subtraction_vector2_scalar: () => { + return generateVectorI32BinaryToVectorCases(vectorI32Range(2), sparseI32Range(), i32_subtract); + }, + subtraction_vector3_scalar: () => { + return generateVectorI32BinaryToVectorCases(vectorI32Range(3), sparseI32Range(), i32_subtract); + }, + subtraction_vector4_scalar: () => { + return generateVectorI32BinaryToVectorCases(vectorI32Range(4), sparseI32Range(), i32_subtract); + }, + multiplication_scalar_vector2: () => { + return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(2), i32_multiply); + }, + multiplication_scalar_vector3: () => { + return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(3), i32_multiply); + }, + multiplication_scalar_vector4: () => { + return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(4), i32_multiply); + }, + multiplication_vector2_scalar: () => { + return generateVectorI32BinaryToVectorCases(vectorI32Range(2), sparseI32Range(), i32_multiply); + }, + multiplication_vector3_scalar: () => { + return generateVectorI32BinaryToVectorCases(vectorI32Range(3), sparseI32Range(), i32_multiply); + }, + multiplication_vector4_scalar: () => { + return generateVectorI32BinaryToVectorCases(vectorI32Range(4), sparseI32Range(), i32_multiply); + }, + division_scalar_vector2_non_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(2), + i32_divide_non_const + ); + }, + division_scalar_vector3_non_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(3), + i32_divide_non_const + ); + }, + division_scalar_vector4_non_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(4), + i32_divide_non_const + ); + }, + division_vector2_scalar_non_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(2), + sparseI32Range(), + i32_divide_non_const + ); + }, + division_vector3_scalar_non_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(3), + sparseI32Range(), + i32_divide_non_const + ); + }, + division_vector4_scalar_non_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(4), + sparseI32Range(), + i32_divide_non_const + ); + }, + division_scalar_vector2_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(2), + i32_divide_const + ); + }, + division_scalar_vector3_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(3), + i32_divide_const + ); + }, + division_scalar_vector4_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(4), + i32_divide_const + ); + }, + division_vector2_scalar_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(2), + sparseI32Range(), + i32_divide_const + ); + }, + division_vector3_scalar_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(3), + sparseI32Range(), + i32_divide_const + ); + }, + division_vector4_scalar_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(4), + sparseI32Range(), + i32_divide_const + ); + }, + remainder_scalar_vector2_non_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(2), + i32_remainder_non_const + ); + }, + remainder_scalar_vector3_non_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(3), + i32_remainder_non_const + ); + }, + remainder_scalar_vector4_non_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(4), + i32_remainder_non_const + ); + }, + remainder_vector2_scalar_non_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(2), + sparseI32Range(), + i32_remainder_non_const + ); + }, + remainder_vector3_scalar_non_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(3), + sparseI32Range(), + i32_remainder_non_const + ); + }, + remainder_vector4_scalar_non_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(4), + sparseI32Range(), + i32_remainder_non_const + ); + }, + remainder_scalar_vector2_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(2), + i32_remainder_const + ); + }, + remainder_scalar_vector3_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(3), + i32_remainder_const + ); + }, + remainder_scalar_vector4_const: () => { + return generateI32VectorBinaryToVectorCases( + sparseI32Range(), + vectorI32Range(4), + i32_remainder_const + ); + }, + remainder_vector2_scalar_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(2), + sparseI32Range(), + i32_remainder_const + ); + }, + remainder_vector3_scalar_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(3), + sparseI32Range(), + i32_remainder_const + ); + }, + remainder_vector4_scalar_const: () => { + return generateVectorI32BinaryToVectorCases( + vectorI32Range(4), + sparseI32Range(), + i32_remainder_const + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.spec.js index 57f03df3da..8f84d041b0 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.spec.js @@ -4,320 +4,14 @@ Execution Tests for the i32 arithmetic binary expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { kValue } from '../../../../util/constants.js'; -import { TypeI32, TypeVec } from '../../../../util/conversion.js'; -import { sparseI32Range, vectorI32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; -import { - allInputSources, - generateBinaryToI32Cases, - generateI32VectorBinaryToVectorCases, - generateVectorI32BinaryToVectorCases, - run } from -'../expression.js'; +import { Type } from '../../../../util/conversion.js'; +import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -function i32_add(x, y) { - return x + y; -} - -function i32_subtract(x, y) { - return x - y; -} - -function i32_multiply(x, y) { - return Math.imul(x, y); -} - -function i32_divide_non_const(x, y) { - if (y === 0) { - return x; - } - if (x === kValue.i32.negative.min && y === -1) { - return x; - } - return x / y; -} - -function i32_divide_const(x, y) { - if (y === 0) { - return undefined; - } - if (x === kValue.i32.negative.min && y === -1) { - return undefined; - } - return x / y; -} - -function i32_remainder_non_const(x, y) { - if (y === 0) { - return 0; - } - if (x === kValue.i32.negative.min && y === -1) { - return 0; - } - return x % y; -} - -function i32_remainder_const(x, y) { - if (y === 0) { - return undefined; - } - if (x === kValue.i32.negative.min && y === -1) { - return undefined; - } - return x % y; -} +import { d } from './i32_arithmetic.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('binary/i32_arithmetic', { - addition: () => { - return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_add); - }, - subtraction: () => { - return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_subtract); - }, - multiplication: () => { - return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_multiply); - }, - division_non_const: () => { - return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_divide_non_const); - }, - division_const: () => { - return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_divide_const); - }, - remainder_non_const: () => { - return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_remainder_non_const); - }, - remainder_const: () => { - return generateBinaryToI32Cases(sparseI32Range(), sparseI32Range(), i32_remainder_const); - }, - addition_scalar_vector2: () => { - return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(2), i32_add); - }, - addition_scalar_vector3: () => { - return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(3), i32_add); - }, - addition_scalar_vector4: () => { - return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(4), i32_add); - }, - addition_vector2_scalar: () => { - return generateVectorI32BinaryToVectorCases(vectorI32Range(2), sparseI32Range(), i32_add); - }, - addition_vector3_scalar: () => { - return generateVectorI32BinaryToVectorCases(vectorI32Range(3), sparseI32Range(), i32_add); - }, - addition_vector4_scalar: () => { - return generateVectorI32BinaryToVectorCases(vectorI32Range(4), sparseI32Range(), i32_add); - }, - subtraction_scalar_vector2: () => { - return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(2), i32_subtract); - }, - subtraction_scalar_vector3: () => { - return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(3), i32_subtract); - }, - subtraction_scalar_vector4: () => { - return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(4), i32_subtract); - }, - subtraction_vector2_scalar: () => { - return generateVectorI32BinaryToVectorCases(vectorI32Range(2), sparseI32Range(), i32_subtract); - }, - subtraction_vector3_scalar: () => { - return generateVectorI32BinaryToVectorCases(vectorI32Range(3), sparseI32Range(), i32_subtract); - }, - subtraction_vector4_scalar: () => { - return generateVectorI32BinaryToVectorCases(vectorI32Range(4), sparseI32Range(), i32_subtract); - }, - multiplication_scalar_vector2: () => { - return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(2), i32_multiply); - }, - multiplication_scalar_vector3: () => { - return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(3), i32_multiply); - }, - multiplication_scalar_vector4: () => { - return generateI32VectorBinaryToVectorCases(sparseI32Range(), vectorI32Range(4), i32_multiply); - }, - multiplication_vector2_scalar: () => { - return generateVectorI32BinaryToVectorCases(vectorI32Range(2), sparseI32Range(), i32_multiply); - }, - multiplication_vector3_scalar: () => { - return generateVectorI32BinaryToVectorCases(vectorI32Range(3), sparseI32Range(), i32_multiply); - }, - multiplication_vector4_scalar: () => { - return generateVectorI32BinaryToVectorCases(vectorI32Range(4), sparseI32Range(), i32_multiply); - }, - division_scalar_vector2_non_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(2), - i32_divide_non_const - ); - }, - division_scalar_vector3_non_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(3), - i32_divide_non_const - ); - }, - division_scalar_vector4_non_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(4), - i32_divide_non_const - ); - }, - division_vector2_scalar_non_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(2), - sparseI32Range(), - i32_divide_non_const - ); - }, - division_vector3_scalar_non_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(3), - sparseI32Range(), - i32_divide_non_const - ); - }, - division_vector4_scalar_non_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(4), - sparseI32Range(), - i32_divide_non_const - ); - }, - division_scalar_vector2_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(2), - i32_divide_const - ); - }, - division_scalar_vector3_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(3), - i32_divide_const - ); - }, - division_scalar_vector4_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(4), - i32_divide_const - ); - }, - division_vector2_scalar_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(2), - sparseI32Range(), - i32_divide_const - ); - }, - division_vector3_scalar_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(3), - sparseI32Range(), - i32_divide_const - ); - }, - division_vector4_scalar_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(4), - sparseI32Range(), - i32_divide_const - ); - }, - remainder_scalar_vector2_non_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(2), - i32_remainder_non_const - ); - }, - remainder_scalar_vector3_non_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(3), - i32_remainder_non_const - ); - }, - remainder_scalar_vector4_non_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(4), - i32_remainder_non_const - ); - }, - remainder_vector2_scalar_non_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(2), - sparseI32Range(), - i32_remainder_non_const - ); - }, - remainder_vector3_scalar_non_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(3), - sparseI32Range(), - i32_remainder_non_const - ); - }, - remainder_vector4_scalar_non_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(4), - sparseI32Range(), - i32_remainder_non_const - ); - }, - remainder_scalar_vector2_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(2), - i32_remainder_const - ); - }, - remainder_scalar_vector3_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(3), - i32_remainder_const - ); - }, - remainder_scalar_vector4_const: () => { - return generateI32VectorBinaryToVectorCases( - sparseI32Range(), - vectorI32Range(4), - i32_remainder_const - ); - }, - remainder_vector2_scalar_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(2), - sparseI32Range(), - i32_remainder_const - ); - }, - remainder_vector3_scalar_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(3), - sparseI32Range(), - i32_remainder_const - ); - }, - remainder_vector4_scalar_const: () => { - return generateVectorI32BinaryToVectorCases( - vectorI32Range(4), - sparseI32Range(), - i32_remainder_const - ); - } -}); - g.test('addition'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -330,7 +24,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('addition'); - await run(t, binary('+'), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, binary('+'), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('addition_compound'). @@ -345,7 +39,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('addition'); - await run(t, compoundBinary('+='), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, compoundBinary('+='), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('subtraction'). @@ -360,7 +54,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('subtraction'); - await run(t, binary('-'), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, binary('-'), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('subtraction_compound'). @@ -375,7 +69,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('subtraction'); - await run(t, compoundBinary('-='), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, compoundBinary('-='), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('multiplication'). @@ -390,7 +84,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('multiplication'); - await run(t, binary('*'), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, binary('*'), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('multiplication_compound'). @@ -405,7 +99,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('multiplication'); - await run(t, compoundBinary('*='), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, compoundBinary('*='), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('division'). @@ -422,7 +116,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'division_const' : 'division_non_const' ); - await run(t, binary('/'), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, binary('/'), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('division_compound'). @@ -439,7 +133,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'division_const' : 'division_non_const' ); - await run(t, compoundBinary('/='), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, compoundBinary('/='), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('remainder'). @@ -456,7 +150,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'remainder_const' : 'remainder_non_const' ); - await run(t, binary('%'), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, binary('%'), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('remainder_compound'). @@ -473,7 +167,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'remainder_const' : 'remainder_non_const' ); - await run(t, compoundBinary('%='), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, compoundBinary('%='), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('addition_scalar_vector'). @@ -488,9 +182,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_rhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const cases = await d.get(`addition_scalar_vector${vec_size}`); - await run(t, binary('+'), [TypeI32, vec_type], vec_type, t.params, cases); + await run(t, binary('+'), [Type.i32, vec_type], vec_type, t.params, cases); }); g.test('addition_vector_scalar'). @@ -505,9 +199,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const cases = await d.get(`addition_vector${vec_size}_scalar`); - await run(t, binary('+'), [vec_type, TypeI32], vec_type, t.params, cases); + await run(t, binary('+'), [vec_type, Type.i32], vec_type, t.params, cases); }); g.test('addition_vector_scalar_compound'). @@ -522,9 +216,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const cases = await d.get(`addition_vector${vec_size}_scalar`); - await run(t, compoundBinary('+='), [vec_type, TypeI32], vec_type, t.params, cases); + await run(t, compoundBinary('+='), [vec_type, Type.i32], vec_type, t.params, cases); }); g.test('subtraction_scalar_vector'). @@ -539,9 +233,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_rhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const cases = await d.get(`subtraction_scalar_vector${vec_size}`); - await run(t, binary('-'), [TypeI32, vec_type], vec_type, t.params, cases); + await run(t, binary('-'), [Type.i32, vec_type], vec_type, t.params, cases); }); g.test('subtraction_vector_scalar'). @@ -556,9 +250,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const cases = await d.get(`subtraction_vector${vec_size}_scalar`); - await run(t, binary('-'), [vec_type, TypeI32], vec_type, t.params, cases); + await run(t, binary('-'), [vec_type, Type.i32], vec_type, t.params, cases); }); g.test('subtraction_vector_scalar_compound'). @@ -573,9 +267,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const cases = await d.get(`subtraction_vector${vec_size}_scalar`); - await run(t, compoundBinary('-='), [vec_type, TypeI32], vec_type, t.params, cases); + await run(t, compoundBinary('-='), [vec_type, Type.i32], vec_type, t.params, cases); }); g.test('multiplication_scalar_vector'). @@ -590,9 +284,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_rhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const cases = await d.get(`multiplication_scalar_vector${vec_size}`); - await run(t, binary('*'), [TypeI32, vec_type], vec_type, t.params, cases); + await run(t, binary('*'), [Type.i32, vec_type], vec_type, t.params, cases); }); g.test('multiplication_vector_scalar'). @@ -607,9 +301,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const cases = await d.get(`multiplication_vector${vec_size}_scalar`); - await run(t, binary('*'), [vec_type, TypeI32], vec_type, t.params, cases); + await run(t, binary('*'), [vec_type, Type.i32], vec_type, t.params, cases); }); g.test('multiplication_vector_scalar_compound'). @@ -624,9 +318,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const cases = await d.get(`multiplication_vector${vec_size}_scalar`); - await run(t, compoundBinary('*='), [vec_type, TypeI32], vec_type, t.params, cases); + await run(t, compoundBinary('*='), [vec_type, Type.i32], vec_type, t.params, cases); }); g.test('division_scalar_vector'). @@ -641,10 +335,10 @@ u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_rhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`division_scalar_vector${vec_size}_${source}`); - await run(t, binary('/'), [TypeI32, vec_type], vec_type, t.params, cases); + await run(t, binary('/'), [Type.i32, vec_type], vec_type, t.params, cases); }); g.test('division_vector_scalar'). @@ -659,10 +353,10 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`division_vector${vec_size}_scalar_${source}`); - await run(t, binary('/'), [vec_type, TypeI32], vec_type, t.params, cases); + await run(t, binary('/'), [vec_type, Type.i32], vec_type, t.params, cases); }); g.test('division_vector_scalar_compound'). @@ -677,10 +371,10 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`division_vector${vec_size}_scalar_${source}`); - await run(t, compoundBinary('/='), [vec_type, TypeI32], vec_type, t.params, cases); + await run(t, compoundBinary('/='), [vec_type, Type.i32], vec_type, t.params, cases); }); g.test('remainder_scalar_vector'). @@ -695,10 +389,10 @@ u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_rhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`remainder_scalar_vector${vec_size}_${source}`); - await run(t, binary('%'), [TypeI32, vec_type], vec_type, t.params, cases); + await run(t, binary('%'), [Type.i32, vec_type], vec_type, t.params, cases); }); g.test('remainder_vector_scalar'). @@ -713,10 +407,10 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`remainder_vector${vec_size}_scalar_${source}`); - await run(t, binary('%'), [vec_type, TypeI32], vec_type, t.params, cases); + await run(t, binary('%'), [vec_type, Type.i32], vec_type, t.params, cases); }); g.test('remainder_vector_scalar_compound'). @@ -731,8 +425,8 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeI32); + const vec_type = Type.vec(vec_size, Type.i32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`remainder_vector${vec_size}_scalar_${source}`); - await run(t, compoundBinary('%='), [vec_type, TypeI32], vec_type, t.params, cases); + await run(t, compoundBinary('%='), [vec_type, Type.i32], vec_type, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_comparison.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_comparison.cache.js new file mode 100644 index 0000000000..4576051d1d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_comparison.cache.js @@ -0,0 +1,21 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { bool, i32 } from '../../../../util/conversion.js';import { vectorI32Range } from '../../../../util/math.js'; +import { makeCaseCache } from '../case_cache.js'; + +/** + * @returns a test case for the provided left hand & right hand values and + * expected boolean result. + */ +function makeCase(lhs, rhs, expected_answer) { + return { input: [i32(lhs), i32(rhs)], expected: bool(expected_answer) }; +} + +export const d = makeCaseCache('binary/i32_comparison', { + equals: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] === v[1])), + not_equals: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] !== v[1])), + less_than: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] < v[1])), + less_equal: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] <= v[1])), + greater_than: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] > v[1])), + greater_equal: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] >= v[1])) +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_comparison.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_comparison.spec.js index 939bb51cf2..e0f78079ba 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_comparison.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_comparison.spec.js @@ -4,32 +4,14 @@ Execution Tests for the i32 comparison expressions `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { i32, bool, TypeBool, TypeI32 } from '../../../../util/conversion.js'; -import { vectorI32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary } from './binary.js'; +import { d } from './i32_comparison.cache.js'; export const g = makeTestGroup(GPUTest); -/** - * @returns a test case for the provided left hand & right hand values and - * expected boolean result. - */ -function makeCase(lhs, rhs, expected_answer) { - return { input: [i32(lhs), i32(rhs)], expected: bool(expected_answer) }; -} - -export const d = makeCaseCache('binary/i32_comparison', { - equals: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] === v[1])), - not_equals: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] !== v[1])), - less_than: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] < v[1])), - less_equal: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] <= v[1])), - greater_than: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] > v[1])), - greater_equal: () => vectorI32Range(2).map((v) => makeCase(v[0], v[1], v[0] >= v[1])) -}); - g.test('equals'). specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). desc( @@ -42,7 +24,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('equals'); - await run(t, binary('=='), [TypeI32, TypeI32], TypeBool, t.params, cases); + await run(t, binary('=='), [Type.i32, Type.i32], Type.bool, t.params, cases); }); g.test('not_equals'). @@ -57,7 +39,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('not_equals'); - await run(t, binary('!='), [TypeI32, TypeI32], TypeBool, t.params, cases); + await run(t, binary('!='), [Type.i32, Type.i32], Type.bool, t.params, cases); }); g.test('less_than'). @@ -72,7 +54,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('less_than'); - await run(t, binary('<'), [TypeI32, TypeI32], TypeBool, t.params, cases); + await run(t, binary('<'), [Type.i32, Type.i32], Type.bool, t.params, cases); }); g.test('less_equals'). @@ -87,7 +69,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('less_equal'); - await run(t, binary('<='), [TypeI32, TypeI32], TypeBool, t.params, cases); + await run(t, binary('<='), [Type.i32, Type.i32], Type.bool, t.params, cases); }); g.test('greater_than'). @@ -102,7 +84,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('greater_than'); - await run(t, binary('>'), [TypeI32, TypeI32], TypeBool, t.params, cases); + await run(t, binary('>'), [Type.i32, Type.i32], Type.bool, t.params, cases); }); g.test('greater_equals'). @@ -117,5 +99,5 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('greater_equal'); - await run(t, binary('>='), [TypeI32, TypeI32], TypeBool, t.params, cases); + await run(t, binary('>='), [Type.i32, Type.i32], Type.bool, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.cache.js new file mode 100644 index 0000000000..cf7ffcf99e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.cache.js @@ -0,0 +1,293 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { sparseU32Range, vectorU32Range } from '../../../../util/math.js';import { generateBinaryToU32Cases, +generateU32VectorBinaryToVectorCases, +generateVectorU32BinaryToVectorCases } from +'../case.js'; +import { makeCaseCache } from '../case_cache.js'; + +function u32_add(x, y) { + return x + y; +} + +function u32_subtract(x, y) { + return x - y; +} + +function u32_multiply(x, y) { + return Math.imul(x, y); +} + +function u32_divide_non_const(x, y) { + if (y === 0) { + return x; + } + return x / y; +} + +function u32_divide_const(x, y) { + if (y === 0) { + return undefined; + } + return x / y; +} + +function u32_remainder_non_const(x, y) { + if (y === 0) { + return 0; + } + return x % y; +} + +function u32_remainder_const(x, y) { + if (y === 0) { + return undefined; + } + return x % y; +} + +export const d = makeCaseCache('binary/u32_arithmetic', { + addition: () => { + return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_add); + }, + subtraction: () => { + return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_subtract); + }, + multiplication: () => { + return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_multiply); + }, + division_non_const: () => { + return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_divide_non_const); + }, + division_const: () => { + return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_divide_const); + }, + remainder_non_const: () => { + return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_remainder_non_const); + }, + remainder_const: () => { + return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_remainder_const); + }, + addition_scalar_vector2: () => { + return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(2), u32_add); + }, + addition_scalar_vector3: () => { + return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(3), u32_add); + }, + addition_scalar_vector4: () => { + return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(4), u32_add); + }, + addition_vector2_scalar: () => { + return generateVectorU32BinaryToVectorCases(vectorU32Range(2), sparseU32Range(), u32_add); + }, + addition_vector3_scalar: () => { + return generateVectorU32BinaryToVectorCases(vectorU32Range(3), sparseU32Range(), u32_add); + }, + addition_vector4_scalar: () => { + return generateVectorU32BinaryToVectorCases(vectorU32Range(4), sparseU32Range(), u32_add); + }, + subtraction_scalar_vector2: () => { + return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(2), u32_subtract); + }, + subtraction_scalar_vector3: () => { + return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(3), u32_subtract); + }, + subtraction_scalar_vector4: () => { + return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(4), u32_subtract); + }, + subtraction_vector2_scalar: () => { + return generateVectorU32BinaryToVectorCases(vectorU32Range(2), sparseU32Range(), u32_subtract); + }, + subtraction_vector3_scalar: () => { + return generateVectorU32BinaryToVectorCases(vectorU32Range(3), sparseU32Range(), u32_subtract); + }, + subtraction_vector4_scalar: () => { + return generateVectorU32BinaryToVectorCases(vectorU32Range(4), sparseU32Range(), u32_subtract); + }, + multiplication_scalar_vector2: () => { + return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(2), u32_multiply); + }, + multiplication_scalar_vector3: () => { + return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(3), u32_multiply); + }, + multiplication_scalar_vector4: () => { + return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(4), u32_multiply); + }, + multiplication_vector2_scalar: () => { + return generateVectorU32BinaryToVectorCases(vectorU32Range(2), sparseU32Range(), u32_multiply); + }, + multiplication_vector3_scalar: () => { + return generateVectorU32BinaryToVectorCases(vectorU32Range(3), sparseU32Range(), u32_multiply); + }, + multiplication_vector4_scalar: () => { + return generateVectorU32BinaryToVectorCases(vectorU32Range(4), sparseU32Range(), u32_multiply); + }, + division_scalar_vector2_non_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(2), + u32_divide_non_const + ); + }, + division_scalar_vector3_non_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(3), + u32_divide_non_const + ); + }, + division_scalar_vector4_non_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(4), + u32_divide_non_const + ); + }, + division_vector2_scalar_non_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(2), + sparseU32Range(), + u32_divide_non_const + ); + }, + division_vector3_scalar_non_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(3), + sparseU32Range(), + u32_divide_non_const + ); + }, + division_vector4_scalar_non_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(4), + sparseU32Range(), + u32_divide_non_const + ); + }, + division_scalar_vector2_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(2), + u32_divide_const + ); + }, + division_scalar_vector3_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(3), + u32_divide_const + ); + }, + division_scalar_vector4_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(4), + u32_divide_const + ); + }, + division_vector2_scalar_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(2), + sparseU32Range(), + u32_divide_const + ); + }, + division_vector3_scalar_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(3), + sparseU32Range(), + u32_divide_const + ); + }, + division_vector4_scalar_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(4), + sparseU32Range(), + u32_divide_const + ); + }, + remainder_scalar_vector2_non_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(2), + u32_remainder_non_const + ); + }, + remainder_scalar_vector3_non_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(3), + u32_remainder_non_const + ); + }, + remainder_scalar_vector4_non_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(4), + u32_remainder_non_const + ); + }, + remainder_vector2_scalar_non_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(2), + sparseU32Range(), + u32_remainder_non_const + ); + }, + remainder_vector3_scalar_non_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(3), + sparseU32Range(), + u32_remainder_non_const + ); + }, + remainder_vector4_scalar_non_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(4), + sparseU32Range(), + u32_remainder_non_const + ); + }, + remainder_scalar_vector2_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(2), + u32_remainder_const + ); + }, + remainder_scalar_vector3_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(3), + u32_remainder_const + ); + }, + remainder_scalar_vector4_const: () => { + return generateU32VectorBinaryToVectorCases( + sparseU32Range(), + vectorU32Range(4), + u32_remainder_const + ); + }, + remainder_vector2_scalar_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(2), + sparseU32Range(), + u32_remainder_const + ); + }, + remainder_vector3_scalar_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(3), + sparseU32Range(), + u32_remainder_const + ); + }, + remainder_vector4_scalar_const: () => { + return generateVectorU32BinaryToVectorCases( + vectorU32Range(4), + sparseU32Range(), + u32_remainder_const + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.spec.js index 32fd44b474..0a86c46ffd 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.spec.js @@ -4,307 +4,14 @@ Execution Tests for the u32 arithmetic binary expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeU32, TypeVec } from '../../../../util/conversion.js'; -import { sparseU32Range, vectorU32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; -import { - allInputSources, - generateBinaryToU32Cases, - generateU32VectorBinaryToVectorCases, - generateVectorU32BinaryToVectorCases, - run } from -'../expression.js'; +import { Type } from '../../../../util/conversion.js'; +import { allInputSources, run } from '../expression.js'; import { binary, compoundBinary } from './binary.js'; - -function u32_add(x, y) { - return x + y; -} - -function u32_subtract(x, y) { - return x - y; -} - -function u32_multiply(x, y) { - return Math.imul(x, y); -} - -function u32_divide_non_const(x, y) { - if (y === 0) { - return x; - } - return x / y; -} - -function u32_divide_const(x, y) { - if (y === 0) { - return undefined; - } - return x / y; -} - -function u32_remainder_non_const(x, y) { - if (y === 0) { - return 0; - } - return x % y; -} - -function u32_remainder_const(x, y) { - if (y === 0) { - return undefined; - } - return x % y; -} +import { d } from './u32_arithmetic.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('binary/u32_arithmetic', { - addition: () => { - return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_add); - }, - subtraction: () => { - return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_subtract); - }, - multiplication: () => { - return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_multiply); - }, - division_non_const: () => { - return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_divide_non_const); - }, - division_const: () => { - return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_divide_const); - }, - remainder_non_const: () => { - return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_remainder_non_const); - }, - remainder_const: () => { - return generateBinaryToU32Cases(sparseU32Range(), sparseU32Range(), u32_remainder_const); - }, - addition_scalar_vector2: () => { - return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(2), u32_add); - }, - addition_scalar_vector3: () => { - return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(3), u32_add); - }, - addition_scalar_vector4: () => { - return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(4), u32_add); - }, - addition_vector2_scalar: () => { - return generateVectorU32BinaryToVectorCases(vectorU32Range(2), sparseU32Range(), u32_add); - }, - addition_vector3_scalar: () => { - return generateVectorU32BinaryToVectorCases(vectorU32Range(3), sparseU32Range(), u32_add); - }, - addition_vector4_scalar: () => { - return generateVectorU32BinaryToVectorCases(vectorU32Range(4), sparseU32Range(), u32_add); - }, - subtraction_scalar_vector2: () => { - return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(2), u32_subtract); - }, - subtraction_scalar_vector3: () => { - return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(3), u32_subtract); - }, - subtraction_scalar_vector4: () => { - return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(4), u32_subtract); - }, - subtraction_vector2_scalar: () => { - return generateVectorU32BinaryToVectorCases(vectorU32Range(2), sparseU32Range(), u32_subtract); - }, - subtraction_vector3_scalar: () => { - return generateVectorU32BinaryToVectorCases(vectorU32Range(3), sparseU32Range(), u32_subtract); - }, - subtraction_vector4_scalar: () => { - return generateVectorU32BinaryToVectorCases(vectorU32Range(4), sparseU32Range(), u32_subtract); - }, - multiplication_scalar_vector2: () => { - return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(2), u32_multiply); - }, - multiplication_scalar_vector3: () => { - return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(3), u32_multiply); - }, - multiplication_scalar_vector4: () => { - return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(4), u32_multiply); - }, - multiplication_vector2_scalar: () => { - return generateVectorU32BinaryToVectorCases(vectorU32Range(2), sparseU32Range(), u32_multiply); - }, - multiplication_vector3_scalar: () => { - return generateVectorU32BinaryToVectorCases(vectorU32Range(3), sparseU32Range(), u32_multiply); - }, - multiplication_vector4_scalar: () => { - return generateVectorU32BinaryToVectorCases(vectorU32Range(4), sparseU32Range(), u32_multiply); - }, - division_scalar_vector2_non_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(2), - u32_divide_non_const - ); - }, - division_scalar_vector3_non_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(3), - u32_divide_non_const - ); - }, - division_scalar_vector4_non_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(4), - u32_divide_non_const - ); - }, - division_vector2_scalar_non_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(2), - sparseU32Range(), - u32_divide_non_const - ); - }, - division_vector3_scalar_non_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(3), - sparseU32Range(), - u32_divide_non_const - ); - }, - division_vector4_scalar_non_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(4), - sparseU32Range(), - u32_divide_non_const - ); - }, - division_scalar_vector2_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(2), - u32_divide_const - ); - }, - division_scalar_vector3_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(3), - u32_divide_const - ); - }, - division_scalar_vector4_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(4), - u32_divide_const - ); - }, - division_vector2_scalar_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(2), - sparseU32Range(), - u32_divide_const - ); - }, - division_vector3_scalar_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(3), - sparseU32Range(), - u32_divide_const - ); - }, - division_vector4_scalar_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(4), - sparseU32Range(), - u32_divide_const - ); - }, - remainder_scalar_vector2_non_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(2), - u32_remainder_non_const - ); - }, - remainder_scalar_vector3_non_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(3), - u32_remainder_non_const - ); - }, - remainder_scalar_vector4_non_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(4), - u32_remainder_non_const - ); - }, - remainder_vector2_scalar_non_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(2), - sparseU32Range(), - u32_remainder_non_const - ); - }, - remainder_vector3_scalar_non_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(3), - sparseU32Range(), - u32_remainder_non_const - ); - }, - remainder_vector4_scalar_non_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(4), - sparseU32Range(), - u32_remainder_non_const - ); - }, - remainder_scalar_vector2_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(2), - u32_remainder_const - ); - }, - remainder_scalar_vector3_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(3), - u32_remainder_const - ); - }, - remainder_scalar_vector4_const: () => { - return generateU32VectorBinaryToVectorCases( - sparseU32Range(), - vectorU32Range(4), - u32_remainder_const - ); - }, - remainder_vector2_scalar_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(2), - sparseU32Range(), - u32_remainder_const - ); - }, - remainder_vector3_scalar_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(3), - sparseU32Range(), - u32_remainder_const - ); - }, - remainder_vector4_scalar_const: () => { - return generateVectorU32BinaryToVectorCases( - vectorU32Range(4), - sparseU32Range(), - u32_remainder_const - ); - } -}); - g.test('addition'). specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). desc( @@ -317,7 +24,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('addition'); - await run(t, binary('+'), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, binary('+'), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('addition_compound'). @@ -332,7 +39,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('addition'); - await run(t, compoundBinary('+='), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, compoundBinary('+='), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('subtraction'). @@ -347,7 +54,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('subtraction'); - await run(t, binary('-'), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, binary('-'), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('subtraction_compound'). @@ -362,7 +69,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('subtraction'); - await run(t, compoundBinary('-='), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, compoundBinary('-='), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('multiplication'). @@ -377,7 +84,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('multiplication'); - await run(t, binary('*'), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, binary('*'), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('multiplication_compound'). @@ -392,7 +99,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('multiplication'); - await run(t, compoundBinary('*='), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, compoundBinary('*='), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('division'). @@ -409,7 +116,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'division_const' : 'division_non_const' ); - await run(t, binary('/'), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, binary('/'), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('division_compound'). @@ -426,7 +133,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'division_const' : 'division_non_const' ); - await run(t, compoundBinary('/='), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, compoundBinary('/='), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('remainder'). @@ -443,7 +150,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'remainder_const' : 'remainder_non_const' ); - await run(t, binary('%'), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, binary('%'), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('remainder_compound'). @@ -460,7 +167,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'remainder_const' : 'remainder_non_const' ); - await run(t, compoundBinary('%='), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, compoundBinary('%='), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('addition_scalar_vector'). @@ -475,9 +182,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_rhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const cases = await d.get(`addition_scalar_vector${vec_size}`); - await run(t, binary('+'), [TypeU32, vec_type], vec_type, t.params, cases); + await run(t, binary('+'), [Type.u32, vec_type], vec_type, t.params, cases); }); g.test('addition_vector_scalar'). @@ -492,9 +199,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const cases = await d.get(`addition_vector${vec_size}_scalar`); - await run(t, binary('+'), [vec_type, TypeU32], vec_type, t.params, cases); + await run(t, binary('+'), [vec_type, Type.u32], vec_type, t.params, cases); }); g.test('addition_vector_scalar_compound'). @@ -509,9 +216,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const cases = await d.get(`addition_vector${vec_size}_scalar`); - await run(t, compoundBinary('+='), [vec_type, TypeU32], vec_type, t.params, cases); + await run(t, compoundBinary('+='), [vec_type, Type.u32], vec_type, t.params, cases); }); g.test('subtraction_scalar_vector'). @@ -526,9 +233,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_rhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const cases = await d.get(`subtraction_scalar_vector${vec_size}`); - await run(t, binary('-'), [TypeU32, vec_type], vec_type, t.params, cases); + await run(t, binary('-'), [Type.u32, vec_type], vec_type, t.params, cases); }); g.test('subtraction_vector_scalar'). @@ -543,9 +250,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const cases = await d.get(`subtraction_vector${vec_size}_scalar`); - await run(t, binary('-'), [vec_type, TypeU32], vec_type, t.params, cases); + await run(t, binary('-'), [vec_type, Type.u32], vec_type, t.params, cases); }); g.test('subtraction_vector_scalar_compound'). @@ -560,9 +267,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const cases = await d.get(`subtraction_vector${vec_size}_scalar`); - await run(t, compoundBinary('-='), [vec_type, TypeU32], vec_type, t.params, cases); + await run(t, compoundBinary('-='), [vec_type, Type.u32], vec_type, t.params, cases); }); g.test('multiplication_scalar_vector'). @@ -577,9 +284,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_rhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const cases = await d.get(`multiplication_scalar_vector${vec_size}`); - await run(t, binary('*'), [TypeU32, vec_type], vec_type, t.params, cases); + await run(t, binary('*'), [Type.u32, vec_type], vec_type, t.params, cases); }); g.test('multiplication_vector_scalar'). @@ -594,9 +301,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const cases = await d.get(`multiplication_vector${vec_size}_scalar`); - await run(t, binary('*'), [vec_type, TypeU32], vec_type, t.params, cases); + await run(t, binary('*'), [vec_type, Type.u32], vec_type, t.params, cases); }); g.test('multiplication_vector_scalar_compound'). @@ -611,9 +318,9 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const cases = await d.get(`multiplication_vector${vec_size}_scalar`); - await run(t, compoundBinary('*='), [vec_type, TypeU32], vec_type, t.params, cases); + await run(t, compoundBinary('*='), [vec_type, Type.u32], vec_type, t.params, cases); }); g.test('division_scalar_vector'). @@ -628,10 +335,10 @@ u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_rhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`division_scalar_vector${vec_size}_${source}`); - await run(t, binary('/'), [TypeU32, vec_type], vec_type, t.params, cases); + await run(t, binary('/'), [Type.u32, vec_type], vec_type, t.params, cases); }); g.test('division_vector_scalar'). @@ -646,10 +353,10 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`division_vector${vec_size}_scalar_${source}`); - await run(t, binary('/'), [vec_type, TypeU32], vec_type, t.params, cases); + await run(t, binary('/'), [vec_type, Type.u32], vec_type, t.params, cases); }); g.test('division_vector_scalar_compound'). @@ -664,10 +371,10 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`division_vector${vec_size}_scalar_${source}`); - await run(t, compoundBinary('/='), [vec_type, TypeU32], vec_type, t.params, cases); + await run(t, compoundBinary('/='), [vec_type, Type.u32], vec_type, t.params, cases); }); g.test('remainder_scalar_vector'). @@ -682,10 +389,10 @@ u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_rhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`remainder_scalar_vector${vec_size}_${source}`); - await run(t, binary('%'), [TypeU32, vec_type], vec_type, t.params, cases); + await run(t, binary('%'), [Type.u32, vec_type], vec_type, t.params, cases); }); g.test('remainder_vector_scalar'). @@ -700,10 +407,10 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`remainder_vector${vec_size}_scalar_${source}`); - await run(t, binary('%'), [vec_type, TypeU32], vec_type, t.params, cases); + await run(t, binary('%'), [vec_type, Type.u32], vec_type, t.params, cases); }); g.test('remainder_vector_scalar_compound'). @@ -718,8 +425,8 @@ u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]) ). fn(async (t) => { const vec_size = t.params.vectorize_lhs; - const vec_type = TypeVec(vec_size, TypeU32); + const vec_type = Type.vec(vec_size, Type.u32); const source = t.params.inputSource === 'const' ? 'const' : 'non_const'; const cases = await d.get(`remainder_vector${vec_size}_scalar_${source}`); - await run(t, compoundBinary('%='), [vec_type, TypeU32], vec_type, t.params, cases); + await run(t, compoundBinary('%='), [vec_type, Type.u32], vec_type, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_comparison.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_comparison.cache.js new file mode 100644 index 0000000000..cd4e4c067e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_comparison.cache.js @@ -0,0 +1,21 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { bool, u32 } from '../../../../util/conversion.js';import { vectorU32Range } from '../../../../util/math.js'; +import { makeCaseCache } from '../case_cache.js'; + +/** + * @returns a test case for the provided left hand & right hand values and + * expected boolean result. + */ +function makeCase(lhs, rhs, expected_answer) { + return { input: [u32(lhs), u32(rhs)], expected: bool(expected_answer) }; +} + +export const d = makeCaseCache('binary/u32_comparison', { + equals: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] === v[1])), + not_equals: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] !== v[1])), + less_than: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] < v[1])), + less_equal: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] <= v[1])), + greater_than: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] > v[1])), + greater_equal: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] >= v[1])) +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_comparison.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_comparison.spec.js index 20bf128901..a9424f205c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_comparison.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_comparison.spec.js @@ -4,32 +4,14 @@ Execution Tests for the u32 comparison expressions `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { u32, bool, TypeBool, TypeU32 } from '../../../../util/conversion.js'; -import { vectorU32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { binary } from './binary.js'; +import { d } from './u32_comparison.cache.js'; export const g = makeTestGroup(GPUTest); -/** - * @returns a test case for the provided left hand & right hand values and - * expected boolean result. - */ -function makeCase(lhs, rhs, expected_answer) { - return { input: [u32(lhs), u32(rhs)], expected: bool(expected_answer) }; -} - -export const d = makeCaseCache('binary/u32_comparison', { - equals: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] === v[1])), - not_equals: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] !== v[1])), - less_than: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] < v[1])), - less_equal: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] <= v[1])), - greater_than: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] > v[1])), - greater_equal: () => vectorU32Range(2).map((v) => makeCase(v[0], v[1], v[0] >= v[1])) -}); - g.test('equals'). specURL('https://www.w3.org/TR/WGSL/#comparison-expr'). desc( @@ -42,7 +24,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('equals'); - await run(t, binary('=='), [TypeU32, TypeU32], TypeBool, t.params, cases); + await run(t, binary('=='), [Type.u32, Type.u32], Type.bool, t.params, cases); }); g.test('not_equals'). @@ -57,7 +39,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('not_equals'); - await run(t, binary('!='), [TypeU32, TypeU32], TypeBool, t.params, cases); + await run(t, binary('!='), [Type.u32, Type.u32], Type.bool, t.params, cases); }); g.test('less_than'). @@ -72,7 +54,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('less_than'); - await run(t, binary('<'), [TypeU32, TypeU32], TypeBool, t.params, cases); + await run(t, binary('<'), [Type.u32, Type.u32], Type.bool, t.params, cases); }); g.test('less_equals'). @@ -87,7 +69,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('less_equal'); - await run(t, binary('<='), [TypeU32, TypeU32], TypeBool, t.params, cases); + await run(t, binary('<='), [Type.u32, Type.u32], Type.bool, t.params, cases); }); g.test('greater_than'). @@ -102,7 +84,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('greater_than'); - await run(t, binary('>'), [TypeU32, TypeU32], TypeBool, t.params, cases); + await run(t, binary('>'), [Type.u32, Type.u32], Type.bool, t.params, cases); }); g.test('greater_equals'). @@ -117,5 +99,5 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('greater_equal'); - await run(t, binary('>='), [TypeU32, TypeU32], TypeBool, t.params, cases); + await run(t, binary('>='), [Type.u32, Type.u32], Type.bool, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.cache.js new file mode 100644 index 0000000000..18404671f5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.cache.js @@ -0,0 +1,26 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { abstractInt } from '../../../../../util/conversion.js';import { FP } from '../../../../../util/floating_point.js';import { absBigInt, fullI64Range } from '../../../../../util/math.js'; +import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract_float|abstract_int] +const cases = { + ...['f32', 'f16', 'abstract']. + map((trait) => ({ + [`${trait === 'abstract' ? 'abstract_float' : trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + 'unfiltered', + FP[trait].absInterval + ); + } + })). + reduce((a, b) => ({ ...a, ...b }), {}), + abstract_int: () => { + return fullI64Range().map((e) => { + return { input: abstractInt(e), expected: abstractInt(absBigInt(e)) }; + }); + } +}; + +export const d = makeCaseCache('abs', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.spec.js index d6f843e50a..e5f9196d5d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.spec.js @@ -3,14 +3,14 @@ **/export const description = ` Execution tests for the 'abs' builtin function -S is AbstractInt, i32, or u32 +S is abstract-int, i32, or u32 T is S or vecN @const fn abs(e: T ) -> T The absolute value of e. Component-wise when T is a vector. If e is a signed integral scalar type and evaluates to the largest negative value, then the result is e. If e is an unsigned integral type, then the result is e. -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn abs(e: T ) -> T Returns the absolute value of e (e.g. e with a positive sign bit). @@ -18,47 +18,26 @@ Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; import { kBit } from '../../../../../util/constants.js'; -import { - i32Bits, - TypeF32, - TypeF16, - TypeI32, - TypeU32, - u32Bits, - TypeAbstractFloat } from -'../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range, fullF64Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type, i32Bits, u32Bits } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { d } from './abs.cache.js'; +import { abstractFloatBuiltin, abstractIntBuiltin, builtin } from './builtin.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('abs', { - f32: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'unfiltered', FP.f32.absInterval); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'unfiltered', FP.f16.absInterval); - }, - abstract: () => { - return FP.abstract.generateScalarToIntervalCases( - fullF64Range(), - 'unfiltered', - FP.abstract.absInterval - ); - } -}); - g.test('abstract_int'). specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions'). desc(`abstract int tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_int'); + await run(t, abstractIntBuiltin('abs'), [Type.abstractInt], Type.abstractInt, t.params, cases); +}); g.test('u32'). specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions'). @@ -67,7 +46,7 @@ params((u) => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { - await run(t, builtin('abs'), [TypeU32], TypeU32, t.params, [ + await run(t, builtin('abs'), [Type.u32], Type.u32, t.params, [ // Min and Max u32 { input: u32Bits(kBit.u32.min), expected: u32Bits(kBit.u32.min) }, { input: u32Bits(kBit.u32.max), expected: u32Bits(kBit.u32.max) }, @@ -114,7 +93,7 @@ params((u) => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { - await run(t, builtin('abs'), [TypeI32], TypeI32, t.params, [ + await run(t, builtin('abs'), [Type.i32], Type.i32, t.params, [ // Min and max i32 // If e evaluates to the largest negative value, then the result is e. { input: i32Bits(kBit.i32.negative.min), expected: i32Bits(kBit.i32.negative.min) }, @@ -166,8 +145,15 @@ combine('inputSource', onlyConstInputSource). combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { - const cases = await d.get('abstract'); - await run(t, abstractBuiltin('abs'), [TypeAbstractFloat], TypeAbstractFloat, t.params, cases); + const cases = await d.get('abstract_float'); + await run( + t, + abstractFloatBuiltin('abs'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); }); g.test('f32'). @@ -178,7 +164,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('abs'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('abs'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -192,5 +178,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('abs'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('abs'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.cache.js new file mode 100644 index 0000000000..2252cdfada --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.cache.js @@ -0,0 +1,24 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { linearRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + [...linearRange(-1, 1, 100), ...FP[trait].scalarRange()], // acos is defined on [-1, 1] + nonConst ? 'unfiltered' : 'finite', + // acos has an ulp or inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].acosInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('acos', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.spec.js index c3970213ff..587d894db4 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.spec.js @@ -3,54 +3,39 @@ **/export const description = ` Execution tests for the 'acos' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn acos(e: T ) -> T Returns the arc cosine of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { linearRange, fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { d } from './acos.cache.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; export const g = makeTestGroup(GPUTest); -const f32_inputs = [ -...linearRange(-1, 1, 100), // acos is defined on [-1, 1] -...fullF32Range()]; - - -const f16_inputs = [ -...linearRange(-1, 1, 100), // acos is defined on [-1, 1] -...fullF16Range()]; - - -export const d = makeCaseCache('acos', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.acosInterval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', FP.f32.acosInterval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', FP.f16.acosInterval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', FP.f16.acosInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('acos'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -60,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('acos'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('acos'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -74,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('acos'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('acos'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.cache.js new file mode 100644 index 0000000000..7ec1882dea --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.cache.js @@ -0,0 +1,24 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { biasedRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + [...biasedRange(1, 2, 100), ...FP[trait].scalarRange()], // x near 1 can be problematic to implement + nonConst ? 'unfiltered' : 'finite', + // acosh has an inherited accuracy, so is only expected to be as accurate as f32 + ...FP[trait !== 'abstract' ? trait : 'f32'].acoshIntervals + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('acosh', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.spec.js index a6d3d4728f..621805031f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.spec.js @@ -3,7 +3,7 @@ **/export const description = ` Execution tests for the 'acosh' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn acosh(e: T ) -> T Returns the hyperbolic arc cosine of e. The result is 0 when e < 1. @@ -13,47 +13,33 @@ Note: The result is not mathematically meaningful when e < 1. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { biasedRange, fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { d } from './acosh.cache.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; export const g = makeTestGroup(GPUTest); -const f32_inputs = [ -...biasedRange(1, 2, 100), // x near 1 can be problematic to implement -...fullF32Range()]; - -const f16_inputs = [ -...biasedRange(1, 2, 100), // x near 1 can be problematic to implement -...fullF16Range()]; - - -export const d = makeCaseCache('acosh', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', ...FP.f32.acoshIntervals); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', ...FP.f32.acoshIntervals); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', ...FP.f16.acoshIntervals); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', ...FP.f16.acoshIntervals); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('acosh'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -63,7 +49,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('acosh'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('acosh'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -77,5 +63,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('acosh'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('acosh'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/all.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/all.spec.js index 09bbb7c02e..8189413ce4 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/all.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/all.spec.js @@ -10,15 +10,7 @@ Returns e if e is scalar. Returns true if each component of e is true if e is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { - False, - True, - TypeBool, - TypeVec, - vec2, - vec3, - vec4 } from -'../../../../../util/conversion.js'; +import { False, True, Type, vec2, vec3, vec4 } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -36,14 +28,14 @@ combine('overload', ['scalar', 'vec2', 'vec3', 'vec4']) fn(async (t) => { const overloads = { scalar: { - type: TypeBool, + type: Type.bool, cases: [ { input: False, expected: False }, { input: True, expected: True }] }, vec2: { - type: TypeVec(2, TypeBool), + type: Type.vec(2, Type.bool), cases: [ { input: vec2(False, False), expected: False }, { input: vec2(True, False), expected: False }, @@ -52,7 +44,7 @@ fn(async (t) => { }, vec3: { - type: TypeVec(3, TypeBool), + type: Type.vec(3, Type.bool), cases: [ { input: vec3(False, False, False), expected: False }, { input: vec3(True, False, False), expected: False }, @@ -65,7 +57,7 @@ fn(async (t) => { }, vec4: { - type: TypeVec(4, TypeBool), + type: Type.vec(4, Type.bool), cases: [ { input: vec4(False, False, False, False), expected: False }, { input: vec4(False, True, False, False), expected: False }, @@ -88,5 +80,5 @@ fn(async (t) => { }; const overload = overloads[t.params.overload]; - await run(t, builtin('all'), [overload.type], TypeBool, t.params, overload.cases); + await run(t, builtin('all'), [overload.type], Type.bool, t.params, overload.cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/any.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/any.spec.js index 119efbb2be..621e56be22 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/any.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/any.spec.js @@ -10,15 +10,7 @@ Returns e if e is scalar. Returns true if any component of e is true if e is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { - False, - True, - TypeBool, - TypeVec, - vec2, - vec3, - vec4 } from -'../../../../../util/conversion.js'; +import { False, True, Type, vec2, vec3, vec4 } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -36,14 +28,14 @@ combine('overload', ['scalar', 'vec2', 'vec3', 'vec4']) fn(async (t) => { const overloads = { scalar: { - type: TypeBool, + type: Type.bool, cases: [ { input: False, expected: False }, { input: True, expected: True }] }, vec2: { - type: TypeVec(2, TypeBool), + type: Type.vec(2, Type.bool), cases: [ { input: vec2(False, False), expected: False }, { input: vec2(True, False), expected: True }, @@ -52,7 +44,7 @@ fn(async (t) => { }, vec3: { - type: TypeVec(3, TypeBool), + type: Type.vec(3, Type.bool), cases: [ { input: vec3(False, False, False), expected: False }, { input: vec3(True, False, False), expected: True }, @@ -65,7 +57,7 @@ fn(async (t) => { }, vec4: { - type: TypeVec(4, TypeBool), + type: Type.vec(4, Type.bool), cases: [ { input: vec4(False, False, False, False), expected: False }, { input: vec4(False, True, False, False), expected: True }, @@ -88,5 +80,5 @@ fn(async (t) => { }; const overload = overloads[t.params.overload]; - await run(t, builtin('any'), [overload.type], TypeBool, t.params, overload.cases); + await run(t, builtin('any'), [overload.type], Type.bool, t.params, overload.cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.cache.js new file mode 100644 index 0000000000..99f0e6b798 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.cache.js @@ -0,0 +1,24 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { linearRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + [...linearRange(-1, 1, 100), ...FP[trait].scalarRange()], // asin is defined on [-1, 1] + nonConst ? 'unfiltered' : 'finite', + // asin has an ulp or inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].asinInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('asin', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.spec.js index 13461e409a..0f8d808079 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.spec.js @@ -3,54 +3,39 @@ **/export const description = ` Execution tests for the 'asin' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn asin(e: T ) -> T Returns the arc sine of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { linearRange, fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { d } from './asin.cache.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; export const g = makeTestGroup(GPUTest); -const f32_inputs = [ -...linearRange(-1, 1, 100), // asin is defined on [-1, 1] -...fullF32Range()]; - - -const f16_inputs = [ -...linearRange(-1, 1, 100), // asin is defined on [-1, 1] -...fullF16Range()]; - - -export const d = makeCaseCache('asin', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.asinInterval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', FP.f32.asinInterval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', FP.f16.asinInterval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', FP.f16.asinInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('asin'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -60,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('asin'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('asin'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -74,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('asin'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('asin'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.cache.js new file mode 100644 index 0000000000..2c3d6f33eb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.cache.js @@ -0,0 +1,18 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + 'unfiltered', + // asinh has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].asinhInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('asinh', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.spec.js index 4460e16cf7..4cee7ca2d8 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.spec.js @@ -3,7 +3,7 @@ **/export const description = ` Execution tests for the 'sinh' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn asinh(e: T ) -> T Returns the hyperbolic arc sine of e. @@ -12,32 +12,33 @@ Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { d } from './asinh.cache.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('asinh', { - f32: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'unfiltered', FP.f32.asinhInterval); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'unfiltered', FP.f16.asinhInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float test`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('asinh'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -47,7 +48,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('asinh'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('asinh'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -61,5 +62,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('asinh'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('asinh'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.cache.js new file mode 100644 index 0000000000..aff1d32cba --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.cache.js @@ -0,0 +1,25 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +const known_values = [-Math.sqrt(3), -1, -1 / Math.sqrt(3), 0, 1, 1 / Math.sqrt(3), Math.sqrt(3)]; + +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + [...known_values, ...FP[trait].scalarRange()], + nonConst ? 'unfiltered' : 'finite', + // atan has an ulp accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].atanInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('atan', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.spec.js index df6c63401b..fe58aca571 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.spec.js @@ -3,50 +3,40 @@ **/export const description = ` Execution tests for the 'atan' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn atan(e: T ) -> T Returns the arc tangent of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { d } from './atan.cache.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; export const g = makeTestGroup(GPUTest); -const known_values = [-Math.sqrt(3), -1, -1 / Math.sqrt(3), 0, 1, 1 / Math.sqrt(3), Math.sqrt(3)]; - -const f32_inputs = [...known_values, ...fullF32Range()]; -const f16_inputs = [...known_values, ...fullF16Range()]; - -export const d = makeCaseCache('atan', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.atanInterval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', FP.f32.atanInterval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', FP.f16.atanInterval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', FP.f16.atanInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('atan'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -62,7 +52,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('atan'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('atan'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -76,5 +66,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('atan'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('atan'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.cache.js new file mode 100644 index 0000000000..b4625d38eb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.cache.js @@ -0,0 +1,35 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { linearRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + // Using sparse range since there are N^2 cases being generated, and also including extra values + // around 0, where there is a discontinuity that implementations may behave badly at. + const numeric_range = [ + ...FP[trait].sparseScalarRange(), + ...linearRange( + FP[trait].constants().negative.max, + FP[trait].constants().positive.min, + 10 + )]; + + return FP[trait].generateScalarPairToIntervalCases( + numeric_range, + numeric_range, + nonConst ? 'unfiltered' : 'finite', + // atan2 has an ulp accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].atan2Interval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('atan2', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.spec.js index d3b13d34c2..88a223e52e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.spec.js @@ -3,53 +3,39 @@ **/export const description = ` Execution tests for the 'atan2' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn atan2(e1: T ,e2: T ) -> T Returns the arc tangent of e1 over e2. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { linearRange, sparseF32Range, sparseF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { d } from './atan2.cache.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; export const g = makeTestGroup(GPUTest); -const cases = ['f32', 'f16']. -flatMap((kind) => -[true, false].map((nonConst) => ({ - [`${kind}_${nonConst ? 'non_const' : 'const'}`]: () => { - const fp = FP[kind]; - // Using sparse range since there are N^2 cases being generated, and also including extra values - // around 0, where there is a discontinuity that implementations may behave badly at. - const numeric_range = [ - ...(kind === 'f32' ? sparseF32Range() : sparseF16Range()), - ...linearRange(fp.constants().negative.max, fp.constants().positive.min, 10)]; - - return fp.generateScalarPairToIntervalCases( - numeric_range, - numeric_range, - nonConst ? 'unfiltered' : 'finite', - fp.atan2Interval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('atan2', cases); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get(`abstract_const`); + await run( + t, + abstractFloatBuiltin('atan2'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -65,7 +51,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(`f32_${t.params.inputSource === 'const' ? 'const' : 'non_const'}`); - await run(t, builtin('atan2'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, builtin('atan2'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -79,5 +65,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(`f16_${t.params.inputSource === 'const' ? 'const' : 'non_const'}`); - await run(t, builtin('atan2'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, builtin('atan2'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.cache.js new file mode 100644 index 0000000000..b10574328e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.cache.js @@ -0,0 +1,32 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { biasedRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + [ + // discontinuity at x = -1 + ...biasedRange(FP[trait].constants().negative.less_than_one, -0.9, 20), + -1, + // discontinuity at x = 1 + ...biasedRange(FP[trait].constants().positive.less_than_one, 0.9, 20), + 1, + ...FP[trait].scalarRange()], + + nonConst ? 'unfiltered' : 'finite', + // atanh has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].atanhInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('atanh', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.spec.js index 85266368a7..b378b0a494 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.spec.js @@ -3,7 +3,7 @@ **/export const description = ` Execution tests for the 'atanh' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn atanh(e: T ) -> T Returns the hyperbolic arc tangent of e. The result is 0 when abs(e) ≥ 1. @@ -12,54 +12,33 @@ Component-wise when T is a vector. Note: The result is not mathematically meaningful when abs(e) >= 1. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { kValue } from '../../../../../util/constants.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { biasedRange, fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { d } from './atanh.cache.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; export const g = makeTestGroup(GPUTest); -const f32_inputs = [ -...biasedRange(kValue.f32.negative.less_than_one, -0.9, 20), // discontinuity at x = -1 --1, -...biasedRange(kValue.f32.positive.less_than_one, 0.9, 20), // discontinuity at x = 1 -1, -...fullF32Range()]; - -const f16_inputs = [ -...biasedRange(kValue.f16.negative.less_than_one, -0.9, 20), // discontinuity at x = -1 --1, -...biasedRange(kValue.f16.positive.less_than_one, 0.9, 20), // discontinuity at x = 1 -1, -...fullF16Range()]; - - -export const d = makeCaseCache('atanh', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.atanhInterval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', FP.f32.atanhInterval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', FP.f16.atanhInterval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', FP.f16.atanhInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('atanh'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -69,7 +48,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('atanh'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('atanh'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -83,5 +62,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('atanh'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('atanh'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomics/atomicCompareExchangeWeak.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomics/atomicCompareExchangeWeak.spec.js index 60d1488c0b..1c33de38ca 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomics/atomicCompareExchangeWeak.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomics/atomicCompareExchangeWeak.spec.js @@ -339,6 +339,11 @@ fn(async (t) => { const numInvocations = t.params.workgroupSize; const scalarType = t.params.scalarType; + t.skipIf( + numInvocations > t.device.limits.maxComputeWorkgroupSizeX, + `${numInvocations} > maxComputeWorkgroupSizeX(${t.device.limits.maxComputeWorkgroupSizeX})` + ); + // Number of times each workgroup attempts to exchange the same value to the same memory address const numWrites = 4; @@ -556,6 +561,11 @@ fn(async (t) => { const numInvocations = t.params.workgroupSize; const scalarType = t.params.scalarType; + t.skipIf( + numInvocations > t.device.limits.maxComputeWorkgroupSizeX, + `${numInvocations} > maxComputeWorkgroupSizeX(${t.device.limits.maxComputeWorkgroupSizeX})` + ); + // Number of times each workgroup attempts to exchange the same value to the same memory address const numWrites = 4; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomics/harness.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomics/harness.js index 986814d425..c377728f10 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomics/harness.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomics/harness.js @@ -25,15 +25,14 @@ export const kMapId = { } }; -export function typedArrayCtor(scalarType) { +export function typedArrayCtor( +scalarType) +{ switch (scalarType) { case 'u32': return Uint32Array; case 'i32': return Int32Array; - default: - assert(false, 'Atomic variables can only by u32 or i32'); - return Uint8Array; } } diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/bitcast.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/bitcast.cache.js new file mode 100644 index 0000000000..6ecbee7dd6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/bitcast.cache.js @@ -0,0 +1,837 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert } from '../../../../../../common/util/util.js';import { alwaysPass, anyOf } from '../../../../../util/compare.js';import { kBit, kValue } from '../../../../../util/constants.js'; +import { + + VectorValue, + f16, + f32, + i32, + toVector, + u32, + abstractFloat, + abstractInt } from +'../../../../../util/conversion.js'; +import { FP, FPInterval } from '../../../../../util/floating_point.js'; +import { + cartesianProduct, + fullI32Range, + fullU32Range, + isFiniteF16, + isFiniteF32, + isSubnormalNumberF16, + isSubnormalNumberF32, + linearRange, + scalarF16Range, + scalarF32Range } from +'../../../../../util/math.js'; +import { + reinterpretF16AsU16, + reinterpretF32AsI32, + reinterpretF32AsU32, + reinterpretI32AsF32, + reinterpretI32AsU32, + reinterpretU16AsF16, + reinterpretU32AsF32, + reinterpretU32AsI32 } from +'../../../../../util/reinterpret.js'; +import { makeCaseCache } from '../../case_cache.js'; + +const numNaNs = 11; +const f32InfAndNaNInU32 = [ +// Cover NaNs evenly in integer space. +// The positive NaN with the lowest integer representation is the integer +// for infinity, plus one. +// The positive NaN with the highest integer representation is i32.max (!) +...linearRange(kBit.f32.positive.infinity + 1, kBit.i32.positive.max, numNaNs), +// The negative NaN with the lowest integer representation is the integer +// for negative infinity, plus one. +// The negative NaN with the highest integer representation is u32.max (!) +...linearRange(kBit.f32.negative.infinity + 1, kBit.u32.max, numNaNs), +kBit.f32.positive.infinity, +kBit.f32.negative.infinity]; + +const f32InfAndNaNInF32 = f32InfAndNaNInU32.map((u) => reinterpretU32AsF32(u)); +const f32InfAndNaNInI32 = f32InfAndNaNInU32.map((u) => reinterpretU32AsI32(u)); + +const f32ZerosInU32 = [0, kBit.f32.negative.zero]; +const f32ZerosInF32 = f32ZerosInU32.map((u) => reinterpretU32AsF32(u)); +const f32ZerosInI32 = f32ZerosInU32.map((u) => reinterpretU32AsI32(u)); +const f32ZerosInterval = new FPInterval('f32', -0.0, 0.0); + +// f32FiniteRange is a list of finite f32s. fullF32Range() already +// has +0, we only need to add -0. +const f32FiniteRange = [...scalarF32Range(), kValue.f32.negative.zero]; +const f32RangeWithInfAndNaN = [...f32FiniteRange, ...f32InfAndNaNInF32]; + +// Type.f16 values, finite, Inf/NaN, and zeros. Represented in float and u16. +const f16FiniteInF16 = [...scalarF16Range(), kValue.f16.negative.zero]; +const f16FiniteInU16 = f16FiniteInF16.map((u) => reinterpretF16AsU16(u)); + +const f16InfAndNaNInU16 = [ +// Cover NaNs evenly in integer space. +// The positive NaN with the lowest integer representation is the integer +// for infinity, plus one. +// The positive NaN with the highest integer representation is u16 0x7fff i.e. 32767. +...linearRange(kBit.f16.positive.infinity + 1, 32767, numNaNs).map((v) => Math.ceil(v)), +// The negative NaN with the lowest integer representation is the integer +// for negative infinity, plus one. +// The negative NaN with the highest integer representation is u16 0xffff i.e. 65535 +...linearRange(kBit.f16.negative.infinity + 1, 65535, numNaNs).map((v) => Math.floor(v)), +kBit.f16.positive.infinity, +kBit.f16.negative.infinity]; + +const f16InfAndNaNInF16 = f16InfAndNaNInU16.map((u) => reinterpretU16AsF16(u)); + +const f16ZerosInU16 = [kBit.f16.negative.zero, 0]; + +// f16 interval that match +/-0.0. +const f16ZerosInterval = new FPInterval('f16', -0.0, 0.0); + +/** + * @returns an u32 whose lower and higher 16bits are the two elements of the + * given array of two u16 respectively, in little-endian. + */ +function u16x2ToU32(u16x2) { + assert(u16x2.length === 2); + // Create a DataView with 4 bytes buffer. + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + // Enforce little-endian. + view.setUint16(0, u16x2[0], true); + view.setUint16(2, u16x2[1], true); + return view.getUint32(0, true); +} + +/** + * @returns an array of two u16, respectively the lower and higher 16bits of + * given u32 in little-endian. + */ +function u32ToU16x2(u32) { + // Create a DataView with 4 bytes buffer. + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + // Enforce little-endian. + view.setUint32(0, u32, true); + return [view.getUint16(0, true), view.getUint16(2, true)]; +} + +/** + * @returns a vec2 from an array of two u16, each reinterpreted as f16. + */ +function u16x2ToVec2F16(u16x2) { + assert(u16x2.length === 2); + return toVector(u16x2.map(reinterpretU16AsF16), f16); +} + +/** + * @returns a vec4 from an array of four u16, each reinterpreted as f16. + */ +function u16x4ToVec4F16(u16x4) { + assert(u16x4.length === 4); + return toVector(u16x4.map(reinterpretU16AsF16), f16); +} + +/** + * @returns true if and only if a given u32 can bitcast to a vec2 with all elements + * being finite f16 values. + */ +function canU32BitcastToFiniteVec2F16(u32) { + return u32ToU16x2(u32). + map((u16) => isFiniteF16(reinterpretU16AsF16(u16))). + reduce((a, b) => a && b, true); +} + +/** + * @returns an array of N elements with the i-th element being an array of len elements + * [a_i, a_((i+1)%N), ..., a_((i+len-1)%N)], for the input array of N element [a_1, ... a_N] + * and the given len. For example, slidingSlice([1, 2, 3], 2) result in + * [[1, 2], [2, 3], [3, 1]]. + * This helper function is used for generating vector cases from scalar values array. + */ +function slidingSlice(input, len) { + const result = []; + for (let i = 0; i < input.length; i++) { + const sub = []; + for (let j = 0; j < len; j++) { + sub.push(input[(i + j) % input.length]); + } + result.push(sub); + } + return result; +} + +// vec2 interesting (zeros, Inf, and NaN) values for testing cases. +// vec2 values that has at least one Inf/NaN f16 element, reinterpreted as u32/i32. +const f16Vec2InfAndNaNInU32 = [ +...cartesianProduct(f16InfAndNaNInU16, [...f16InfAndNaNInU16, ...f16FiniteInU16]), +...cartesianProduct(f16FiniteInU16, f16InfAndNaNInU16)]. +map(u16x2ToU32); +const f16Vec2InfAndNaNInI32 = f16Vec2InfAndNaNInU32.map((u) => reinterpretU32AsI32(u)); +// vec2 values with two f16 0.0 element, reinterpreted as u32/i32. +const f16Vec2ZerosInU32 = cartesianProduct(f16ZerosInU16, f16ZerosInU16).map(u16x2ToU32); +const f16Vec2ZerosInI32 = f16Vec2ZerosInU32.map((u) => reinterpretU32AsI32(u)); + +// i32/u32/f32 range for bitcasting to vec2 +// u32 values for bitcasting to vec2 finite, Inf, and NaN. +const u32RangeForF16Vec2FiniteInfNaN = [ +...fullU32Range(), +...f16Vec2ZerosInU32, +...f16Vec2InfAndNaNInU32]; + +// u32 values for bitcasting to finite only vec2, used for constant evaluation. +const u32RangeForF16Vec2Finite = u32RangeForF16Vec2FiniteInfNaN.filter( + canU32BitcastToFiniteVec2F16 +); +// i32 values for bitcasting to vec2 finite, zeros, Inf, and NaN. +const i32RangeForF16Vec2FiniteInfNaN = [ +...fullI32Range(), +...f16Vec2ZerosInI32, +...f16Vec2InfAndNaNInI32]; + +// i32 values for bitcasting to finite only vec2, used for constant evaluation. +const i32RangeForF16Vec2Finite = i32RangeForF16Vec2FiniteInfNaN.filter((u) => +canU32BitcastToFiniteVec2F16(reinterpretI32AsU32(u)) +); +// f32 values with finite/Inf/NaN f32, for bitcasting to vec2 finite, zeros, Inf, and NaN. +const f32RangeWithInfAndNaNForF16Vec2FiniteInfNaN = [ +...f32RangeWithInfAndNaN, +...u32RangeForF16Vec2FiniteInfNaN.map(reinterpretU32AsF32)]; + +// Finite f32 values for bitcasting to finite only vec2, used for constant evaluation. +const f32FiniteRangeForF16Vec2Finite = f32RangeWithInfAndNaNForF16Vec2FiniteInfNaN. +filter(isFiniteF32). +filter((u) => canU32BitcastToFiniteVec2F16(reinterpretF32AsU32(u))); + +// vec2 cases for bitcasting to i32/u32/f32, by combining f16 values into pairs +const f16Vec2FiniteInU16x2 = slidingSlice(f16FiniteInU16, 2); +const f16Vec2FiniteInfNanInU16x2 = slidingSlice([...f16FiniteInU16, ...f16InfAndNaNInU16], 2); +// vec4 cases for bitcasting to vec2, by combining f16 values 4-by-4 +const f16Vec2FiniteInU16x4 = slidingSlice(f16FiniteInU16, 4); +const f16Vec2FiniteInfNanInU16x4 = slidingSlice([...f16FiniteInU16, ...f16InfAndNaNInU16], 4); + +// alwaysPass comparator for i32/u32/f32 cases. For f32/f16 we also use unbound interval, which +// allow per-element unbounded expectation for vector. +const anyF32 = alwaysPass('any f32'); +const anyI32 = alwaysPass('any i32'); +const anyU32 = alwaysPass('any u32'); + +// Unbounded FPInterval +const f32UnboundedInterval = FP.f32.constants().unboundedInterval; +const f16UnboundedInterval = FP.f16.constants().unboundedInterval; + +// i32 and u32 cases for bitcasting to f32. +// i32 cases for bitcasting to f32 finite, zeros, Inf, and NaN. +const i32RangeForF32FiniteInfNaN = [ +...fullI32Range(), +...f32ZerosInI32, +...f32InfAndNaNInI32]; + +// i32 cases for bitcasting to f32 finite only. +const i32RangeForF32Finite = i32RangeForF32FiniteInfNaN.filter((i) => +isFiniteF32(reinterpretI32AsF32(i)) +); +// u32 cases for bitcasting to f32 finite, zeros, Inf, and NaN. +const u32RangeForF32FiniteInfNaN = [ +...fullU32Range(), +...f32ZerosInU32, +...f32InfAndNaNInU32]; + +// u32 cases for bitcasting to f32 finite only. +const u32RangeForF32Finite = u32RangeForF32FiniteInfNaN.filter((u) => +isFiniteF32(reinterpretU32AsF32(u)) +); + +/** + * @returns a Comparator for checking if a f32 value is a valid + * bitcast conversion from f32. + */ +function bitcastF32ToF32Comparator(f) { + if (!isFiniteF32(f)) return anyF32; + const acceptable = [f, ...(isSubnormalNumberF32(f) ? f32ZerosInF32 : [])]; + return anyOf(...acceptable.map(f32)); +} + +/** + * @returns a Comparator for checking if a u32 value is a valid + * bitcast conversion from f32. + */ +function bitcastF32ToU32Comparator(f) { + if (!isFiniteF32(f)) return anyU32; + const acceptable = [ + reinterpretF32AsU32(f), + ...(isSubnormalNumberF32(f) ? f32ZerosInU32 : [])]; + + return anyOf(...acceptable.map(u32)); +} + +/** + * @returns a Comparator for checking if a i32 value is a valid + * bitcast conversion from f32. + */ +function bitcastF32ToI32Comparator(f) { + if (!isFiniteF32(f)) return anyI32; + const acceptable = [ + reinterpretF32AsI32(f), + ...(isSubnormalNumberF32(f) ? f32ZerosInI32 : [])]; + + return anyOf(...acceptable.map(i32)); +} + +/** + * @returns a Comparator for checking if a f32 value is a valid + * bitcast conversion from i32. + */ +function bitcastI32ToF32Comparator(i) { + const f = reinterpretI32AsF32(i); + if (!isFiniteF32(f)) return anyI32; + // Positive or negative zero bit pattern map to any zero. + if (f32ZerosInI32.includes(i)) return anyOf(...f32ZerosInF32.map(f32)); + const acceptable = [f, ...(isSubnormalNumberF32(f) ? f32ZerosInF32 : [])]; + return anyOf(...acceptable.map(f32)); +} + +/** + * @returns a Comparator for checking if a f32 value is a valid + * bitcast conversion from u32. + */ +function bitcastU32ToF32Comparator(u) { + const f = reinterpretU32AsF32(u); + if (!isFiniteF32(f)) return anyU32; + // Positive or negative zero bit pattern map to any zero. + if (f32ZerosInU32.includes(u)) return anyOf(...f32ZerosInF32.map(f32)); + const acceptable = [f, ...(isSubnormalNumberF32(f) ? f32ZerosInF32 : [])]; + return anyOf(...acceptable.map(f32)); +} + +/** + * @returns an array of expected f16 FPInterval for the given bitcasted f16 value, which may be + * subnormal, Inf, or NaN. Test cases that bitcasted to vector of f16 use this function to get + * per-element expectation and build vector expectation using cartesianProduct. + */ +function generateF16ExpectationIntervals(bitcastedF16Value) { + // If the bitcasted f16 value is inf or nan, the result is unbounded + if (!isFiniteF16(bitcastedF16Value)) { + return [f16UnboundedInterval]; + } + // If the casted f16 value is +/-0.0, the result can be one of both. Note that in JS -0.0 === 0.0. + if (bitcastedF16Value === 0.0) { + return [f16ZerosInterval]; + } + const exactInterval = FP.f16.toInterval(bitcastedF16Value); + // If the casted f16 value is subnormal, it also may be flushed to +/-0.0. + return [exactInterval, ...(isSubnormalNumberF16(bitcastedF16Value) ? [f16ZerosInterval] : [])]; +} + +/** + * @returns a Comparator for checking if a f16 value is a valid + * bitcast conversion from f16. + */ +function bitcastF16ToF16Comparator(f) { + if (!isFiniteF16(f)) return anyOf(f16UnboundedInterval); + return anyOf(...generateF16ExpectationIntervals(f)); +} + +/** + * @returns a Comparator for checking if a vec2 is a valid bitcast + * conversion from u32. + */ +function bitcastU32ToVec2F16Comparator(u) { + const bitcastedVec2F16InU16x2 = u32ToU16x2(u).map(reinterpretU16AsF16); + // Generate expection for vec2 f16 result, by generating expected intervals for each elements and + // then do cartesian product. + const expectedIntervalsCombination = cartesianProduct( + ...bitcastedVec2F16InU16x2.map(generateF16ExpectationIntervals) + ); + return anyOf(...expectedIntervalsCombination); +} + +/** + * @returns a Comparator for checking if a vec2 value is a valid + * bitcast conversion from i32. + */ +function bitcastI32ToVec2F16Comparator(i) { + const bitcastedVec2F16InU16x2 = u32ToU16x2(reinterpretI32AsU32(i)).map(reinterpretU16AsF16); + // Generate expection for vec2 f16 result, by generating expected intervals for each elements and + // then do cartesian product. + const expectedIntervalsCombination = cartesianProduct( + ...bitcastedVec2F16InU16x2.map(generateF16ExpectationIntervals) + ); + return anyOf(...expectedIntervalsCombination); +} + +/** + * @returns a Comparator for checking if a vec2 value is a valid + * bitcast conversion from f32. + */ +function bitcastF32ToVec2F16Comparator(f) { + // If input f32 is not finite, it can be evaluated to any value and thus any result f16 vec2 is + // possible. + if (!isFiniteF32(f)) { + return anyOf([f16UnboundedInterval, f16UnboundedInterval]); + } + const bitcastedVec2F16InU16x2 = u32ToU16x2(reinterpretF32AsU32(f)).map(reinterpretU16AsF16); + // Generate expection for vec2 f16 result, by generating expected intervals for each elements and + // then do cartesian product. + const expectedIntervalsCombination = cartesianProduct( + ...bitcastedVec2F16InU16x2.map(generateF16ExpectationIntervals) + ); + return anyOf(...expectedIntervalsCombination); +} + +/** + * @returns a Comparator for checking if a vec4 is a valid + * bitcast conversion from vec2. + */ +function bitcastVec2U32ToVec4F16Comparator(u32x2) { + assert(u32x2.length === 2); + const bitcastedVec4F16InU16x4 = u32x2.flatMap(u32ToU16x2).map(reinterpretU16AsF16); + // Generate expection for vec4 f16 result, by generating expected intervals for each elements and + // then do cartesian product. + const expectedIntervalsCombination = cartesianProduct( + ...bitcastedVec4F16InU16x4.map(generateF16ExpectationIntervals) + ); + return anyOf(...expectedIntervalsCombination); +} + +/** + * @returns a Comparator for checking if a vec4 is a valid + * bitcast conversion from vec2. + */ +function bitcastVec2I32ToVec4F16Comparator(i32x2) { + assert(i32x2.length === 2); + const bitcastedVec4F16InU16x4 = i32x2. + map(reinterpretI32AsU32). + flatMap(u32ToU16x2). + map(reinterpretU16AsF16); + // Generate expection for vec4 f16 result, by generating expected intervals for each elements and + // then do cartesian product. + const expectedIntervalsCombination = cartesianProduct( + ...bitcastedVec4F16InU16x4.map(generateF16ExpectationIntervals) + ); + return anyOf(...expectedIntervalsCombination); +} + +/** + * @returns a Comparator for checking if a vec4 is a valid + * bitcast conversion from vec2. + */ +function bitcastVec2F32ToVec4F16Comparator(f32x2) { + assert(f32x2.length === 2); + const bitcastedVec4F16InU16x4 = f32x2. + map(reinterpretF32AsU32). + flatMap(u32ToU16x2). + map(reinterpretU16AsF16); + // Generate expection for vec4 f16 result, by generating expected intervals for each elements and + // then do cartesian product. + const expectedIntervalsCombination = cartesianProduct( + ...bitcastedVec4F16InU16x4.map(generateF16ExpectationIntervals) + ); + return anyOf(...expectedIntervalsCombination); +} + +// Structure that store the expectations of a single 32bit scalar/element bitcasted from two f16. + + + + + + + +/** + * @returns the array of possible 16bits, represented in u16, that bitcasted + * from a given finite f16 represented in u16, handling the possible subnormal + * flushing. Used to build up 32bits or larger results. + */ +function possibleBitsInU16FromFiniteF16InU16(f16InU16) { + const h = reinterpretU16AsF16(f16InU16); + assert(isFiniteF16(h)); + return [f16InU16, ...(isSubnormalNumberF16(h) ? f16ZerosInU16 : [])]; +} + +/** + * @returns the expectation for a single 32bit scalar bitcasted from given pair of + * f16, result in ExpectionFor32BitsScalarFromF16x2. + */ +function possible32BitScalarIntervalsFromF16x2( +f16x2InU16x2, +type) +{ + assert(f16x2InU16x2.length === 2); + let reinterpretFromU32; + let expectationsForValue; + let unboundedExpectations; + if (type === 'u32') { + reinterpretFromU32 = (x) => x; + expectationsForValue = (x) => [u32(x)]; + // Scalar expectation can not express "unbounded" for i32 and u32, so use 0 here as a + // placeholder, and the possibleExpectations should be ignored if the result is unbounded. + unboundedExpectations = [u32(0)]; + } else if (type === 'i32') { + reinterpretFromU32 = (x) => reinterpretU32AsI32(x); + expectationsForValue = (x) => [i32(x)]; + // Scalar expectation can not express "unbounded" for i32 and u32, so use 0 here as a + // placeholder, and the possibleExpectations should be ignored if the result is unbounded. + unboundedExpectations = [i32(0)]; + } else { + assert(type === 'f32'); + reinterpretFromU32 = (x) => reinterpretU32AsF32(x); + expectationsForValue = (x) => { + // Handle the possible Inf/NaN/zeros and subnormal cases for f32 result. + if (!isFiniteF32(x)) { + return [f32UnboundedInterval]; + } + // If the casted f16 value is +/-0.0, the result can be one of both. Note that in JS -0.0 === 0.0. + if (x === 0.0) { + return [f32ZerosInterval]; + } + const exactInterval = FP.f32.toInterval(x); + // If the casted f16 value is subnormal, it also may be flushed to +/-0.0. + return [exactInterval, ...(isSubnormalNumberF32(x) ? [f32ZerosInterval] : [])]; + }; + unboundedExpectations = [f32UnboundedInterval]; + } + // Return unbounded expection if f16 Inf/NaN occurs + if ( + !isFiniteF16(reinterpretU16AsF16(f16x2InU16x2[0])) || + !isFiniteF16(reinterpretU16AsF16(f16x2InU16x2[1]))) + { + return { possibleExpectations: unboundedExpectations, isUnbounded: true }; + } + const possibleU16Bits = f16x2InU16x2.map(possibleBitsInU16FromFiniteF16InU16); + const possibleExpectations = cartesianProduct(...possibleU16Bits).flatMap( + + (possibleBitsU16x2) => { + assert(possibleBitsU16x2.length === 2); + return expectationsForValue(reinterpretFromU32(u16x2ToU32(possibleBitsU16x2))); + }); + return { possibleExpectations, isUnbounded: false }; +} + +/** + * @returns a Comparator for checking if a u32 value is a valid + * bitcast conversion from vec2 f16. + */ +function bitcastVec2F16ToU32Comparator(vec2F16InU16x2) { + assert(vec2F16InU16x2.length === 2); + const expectations = possible32BitScalarIntervalsFromF16x2(vec2F16InU16x2, 'u32'); + // Return alwaysPass if result is expected unbounded. + if (expectations.isUnbounded) { + return anyU32; + } + return anyOf(...expectations.possibleExpectations); +} + +/** + * @returns a Comparator for checking if a i32 value is a valid + * bitcast conversion from vec2 f16. + */ +function bitcastVec2F16ToI32Comparator(vec2F16InU16x2) { + assert(vec2F16InU16x2.length === 2); + const expectations = possible32BitScalarIntervalsFromF16x2(vec2F16InU16x2, 'i32'); + // Return alwaysPass if result is expected unbounded. + if (expectations.isUnbounded) { + return anyI32; + } + return anyOf(...expectations.possibleExpectations); +} + +/** + * @returns a Comparator for checking if a i32 value is a valid + * bitcast conversion from vec2 f16. + */ +function bitcastVec2F16ToF32Comparator(vec2F16InU16x2) { + assert(vec2F16InU16x2.length === 2); + const expectations = possible32BitScalarIntervalsFromF16x2(vec2F16InU16x2, 'f32'); + // Return alwaysPass if result is expected unbounded. + if (expectations.isUnbounded) { + return anyF32; + } + return anyOf(...expectations.possibleExpectations); +} + +/** + * @returns a Comparator for checking if a vec2 u32 value is a valid + * bitcast conversion from vec4 f16. + */ +function bitcastVec4F16ToVec2U32Comparator(vec4F16InU16x4) { + assert(vec4F16InU16x4.length === 4); + const expectationsPerElement = [vec4F16InU16x4.slice(0, 2), vec4F16InU16x4.slice(2, 4)].map((e) => + possible32BitScalarIntervalsFromF16x2(e, 'u32') + ); + // Return alwaysPass if any element is expected unbounded. Although it may be only one unbounded + // element in the result vector, currently we don't have a way to build a comparator that expect + // only one element of i32/u32 vector unbounded. + if (expectationsPerElement.map((e) => e.isUnbounded).reduce((a, b) => a || b, false)) { + return alwaysPass('any vec2'); + } + return anyOf( + ...cartesianProduct(...expectationsPerElement.map((e) => e.possibleExpectations)).map( + (e) => new VectorValue(e) + ) + ); +} + +/** + * @returns a Comparator for checking if a vec2 i32 value is a valid + * bitcast conversion from vec4 f16. + */ +function bitcastVec4F16ToVec2I32Comparator(vec4F16InU16x4) { + assert(vec4F16InU16x4.length === 4); + const expectationsPerElement = [vec4F16InU16x4.slice(0, 2), vec4F16InU16x4.slice(2, 4)].map((e) => + possible32BitScalarIntervalsFromF16x2(e, 'i32') + ); + // Return alwaysPass if any element is expected unbounded. Although it may be only one unbounded + // element in the result vector, currently we don't have a way to build a comparator that expect + // only one element of i32/u32 vector unbounded. + if (expectationsPerElement.map((e) => e.isUnbounded).reduce((a, b) => a || b, false)) { + return alwaysPass('any vec2'); + } + return anyOf( + ...cartesianProduct(...expectationsPerElement.map((e) => e.possibleExpectations)).map( + (e) => new VectorValue(e) + ) + ); +} + +/** + * @returns a Comparator for checking if a vec2 f32 value is a valid + * bitcast conversion from vec4 f16. + */ +function bitcastVec4F16ToVec2F32Comparator(vec4F16InU16x4) { + assert(vec4F16InU16x4.length === 4); + const expectationsPerElement = [vec4F16InU16x4.slice(0, 2), vec4F16InU16x4.slice(2, 4)].map((e) => + possible32BitScalarIntervalsFromF16x2(e, 'f32') + ); + return anyOf( + ...cartesianProduct(...expectationsPerElement.map((e) => e.possibleExpectations)).map((e) => [ + e[0], + e[1]] + ) + ); +} + +export const d = makeCaseCache('bitcast', { + // Identity Cases + i32_to_i32: () => fullI32Range().map((e) => ({ input: i32(e), expected: i32(e) })), + u32_to_u32: () => fullU32Range().map((e) => ({ input: u32(e), expected: u32(e) })), + f32_inf_nan_to_f32: () => + f32RangeWithInfAndNaN.map((e) => ({ + input: f32(e), + expected: bitcastF32ToF32Comparator(e) + })), + f32_to_f32: () => + f32FiniteRange.map((e) => ({ input: f32(e), expected: bitcastF32ToF32Comparator(e) })), + f16_inf_nan_to_f16: () => + [...f16FiniteInF16, ...f16InfAndNaNInF16].map((e) => ({ + input: f16(e), + expected: bitcastF16ToF16Comparator(e) + })), + f16_to_f16: () => + f16FiniteInF16.map((e) => ({ input: f16(e), expected: bitcastF16ToF16Comparator(e) })), + + // i32,u32,f32,Abstract to different i32,u32,f32 + i32_to_u32: () => fullI32Range().map((e) => ({ input: i32(e), expected: u32(e) })), + i32_to_f32: () => + i32RangeForF32Finite.map((e) => ({ + input: i32(e), + expected: bitcastI32ToF32Comparator(e) + })), + ai_to_i32: () => fullI32Range().map((e) => ({ input: abstractInt(BigInt(e)), expected: i32(e) })), + ai_to_u32: () => fullU32Range().map((e) => ({ input: abstractInt(BigInt(e)), expected: u32(e) })), + ai_to_f32: () => + // AbstractInt is converted to i32, because there is no explicit overload + i32RangeForF32Finite.map((e) => ({ + input: abstractInt(BigInt(e)), + expected: bitcastI32ToF32Comparator(e) + })), + i32_to_f32_inf_nan: () => + i32RangeForF32FiniteInfNaN.map((e) => ({ + input: i32(e), + expected: bitcastI32ToF32Comparator(e) + })), + u32_to_i32: () => fullU32Range().map((e) => ({ input: u32(e), expected: i32(e) })), + u32_to_f32: () => + u32RangeForF32Finite.map((e) => ({ + input: u32(e), + expected: bitcastU32ToF32Comparator(e) + })), + u32_to_f32_inf_nan: () => + u32RangeForF32FiniteInfNaN.map((e) => ({ + input: u32(e), + expected: bitcastU32ToF32Comparator(e) + })), + f32_inf_nan_to_i32: () => + f32RangeWithInfAndNaN.map((e) => ({ + input: f32(e), + expected: bitcastF32ToI32Comparator(e) + })), + f32_to_i32: () => + f32FiniteRange.map((e) => ({ input: f32(e), expected: bitcastF32ToI32Comparator(e) })), + + f32_inf_nan_to_u32: () => + f32RangeWithInfAndNaN.map((e) => ({ + input: f32(e), + expected: bitcastF32ToU32Comparator(e) + })), + f32_to_u32: () => + f32FiniteRange.map((e) => ({ input: f32(e), expected: bitcastF32ToU32Comparator(e) })), + + // i32,u32,f32,AbstractInt to vec2 + u32_to_vec2_f16_inf_nan: () => + u32RangeForF16Vec2FiniteInfNaN.map((e) => ({ + input: u32(e), + expected: bitcastU32ToVec2F16Comparator(e) + })), + u32_to_vec2_f16: () => + u32RangeForF16Vec2Finite.map((e) => ({ + input: u32(e), + expected: bitcastU32ToVec2F16Comparator(e) + })), + i32_to_vec2_f16_inf_nan: () => + i32RangeForF16Vec2FiniteInfNaN.map((e) => ({ + input: i32(e), + expected: bitcastI32ToVec2F16Comparator(e) + })), + i32_to_vec2_f16: () => + i32RangeForF16Vec2Finite.map((e) => ({ + input: i32(e), + expected: bitcastI32ToVec2F16Comparator(e) + })), + ai_to_vec2_f16: () => + // AbstractInt is converted to i32, because there is no explicit overload + i32RangeForF16Vec2Finite.map((e) => ({ + input: abstractInt(BigInt(e)), + expected: bitcastI32ToVec2F16Comparator(e) + })), + f32_inf_nan_to_vec2_f16_inf_nan: () => + f32RangeWithInfAndNaNForF16Vec2FiniteInfNaN.map((e) => ({ + input: f32(e), + expected: bitcastF32ToVec2F16Comparator(e) + })), + f32_to_vec2_f16: () => + f32FiniteRangeForF16Vec2Finite.map((e) => ({ + input: f32(e), + expected: bitcastF32ToVec2F16Comparator(e) + })), + af_to_vec2_f16: () => + f32FiniteRangeForF16Vec2Finite.map((e) => ({ + input: abstractFloat(e), + expected: bitcastF32ToVec2F16Comparator(e) + })), + + // vec2, vec2, vec2, vec2 to vec4 + vec2_i32_to_vec4_f16_inf_nan: () => + slidingSlice(i32RangeForF16Vec2FiniteInfNaN, 2).map((e) => ({ + input: toVector(e, i32), + expected: bitcastVec2I32ToVec4F16Comparator(e) + })), + vec2_i32_to_vec4_f16: () => + slidingSlice(i32RangeForF16Vec2Finite, 2).map((e) => ({ + input: toVector(e, i32), + expected: bitcastVec2I32ToVec4F16Comparator(e) + })), + vec2_ai_to_vec4_f16: () => + // AbstractInt is converted to i32, because there is no explicit overload + slidingSlice(i32RangeForF16Vec2Finite, 2).map((e) => ({ + input: toVector(e, (n) => abstractInt(BigInt(n))), + expected: bitcastVec2I32ToVec4F16Comparator(e) + })), + vec2_u32_to_vec4_f16_inf_nan: () => + slidingSlice(u32RangeForF16Vec2FiniteInfNaN, 2).map((e) => ({ + input: toVector(e, u32), + expected: bitcastVec2U32ToVec4F16Comparator(e) + })), + vec2_u32_to_vec4_f16: () => + slidingSlice(u32RangeForF16Vec2Finite, 2).map((e) => ({ + input: toVector(e, u32), + expected: bitcastVec2U32ToVec4F16Comparator(e) + })), + vec2_f32_inf_nan_to_vec4_f16_inf_nan: () => + slidingSlice(f32RangeWithInfAndNaNForF16Vec2FiniteInfNaN, 2).map((e) => ({ + input: toVector(e, f32), + expected: bitcastVec2F32ToVec4F16Comparator(e) + })), + vec2_f32_to_vec4_f16: () => + slidingSlice(f32FiniteRangeForF16Vec2Finite, 2).map((e) => ({ + input: toVector(e, f32), + expected: bitcastVec2F32ToVec4F16Comparator(e) + })), + vec2_af_to_vec4_f16: () => + slidingSlice(f32FiniteRangeForF16Vec2Finite, 2).map((e) => ({ + input: toVector(e, abstractFloat), + expected: bitcastVec2F32ToVec4F16Comparator(e) + })), + + // vec2 to i32, u32, f32 + vec2_f16_to_u32: () => + f16Vec2FiniteInU16x2.map((e) => ({ + input: u16x2ToVec2F16(e), + expected: bitcastVec2F16ToU32Comparator(e) + })), + vec2_f16_inf_nan_to_u32: () => + f16Vec2FiniteInfNanInU16x2.map((e) => ({ + input: u16x2ToVec2F16(e), + expected: bitcastVec2F16ToU32Comparator(e) + })), + vec2_f16_to_i32: () => + f16Vec2FiniteInU16x2.map((e) => ({ + input: u16x2ToVec2F16(e), + expected: bitcastVec2F16ToI32Comparator(e) + })), + vec2_f16_inf_nan_to_i32: () => + f16Vec2FiniteInfNanInU16x2.map((e) => ({ + input: u16x2ToVec2F16(e), + expected: bitcastVec2F16ToI32Comparator(e) + })), + vec2_f16_to_f32_finite: () => + f16Vec2FiniteInU16x2. + filter((u16x2) => isFiniteF32(reinterpretU32AsF32(u16x2ToU32(u16x2)))). + map((e) => ({ + input: u16x2ToVec2F16(e), + expected: bitcastVec2F16ToF32Comparator(e) + })), + vec2_f16_inf_nan_to_f32: () => + f16Vec2FiniteInfNanInU16x2.map((e) => ({ + input: u16x2ToVec2F16(e), + expected: bitcastVec2F16ToF32Comparator(e) + })), + + // vec4 to vec2 of i32, u32, f32 + vec4_f16_to_vec2_u32: () => + f16Vec2FiniteInU16x4.map((e) => ({ + input: u16x4ToVec4F16(e), + expected: bitcastVec4F16ToVec2U32Comparator(e) + })), + vec4_f16_inf_nan_to_vec2_u32: () => + f16Vec2FiniteInfNanInU16x4.map((e) => ({ + input: u16x4ToVec4F16(e), + expected: bitcastVec4F16ToVec2U32Comparator(e) + })), + vec4_f16_to_vec2_i32: () => + f16Vec2FiniteInU16x4.map((e) => ({ + input: u16x4ToVec4F16(e), + expected: bitcastVec4F16ToVec2I32Comparator(e) + })), + vec4_f16_inf_nan_to_vec2_i32: () => + f16Vec2FiniteInfNanInU16x4.map((e) => ({ + input: u16x4ToVec4F16(e), + expected: bitcastVec4F16ToVec2I32Comparator(e) + })), + vec4_f16_to_vec2_f32_finite: () => + f16Vec2FiniteInU16x4. + filter( + (u16x4) => + isFiniteF32(reinterpretU32AsF32(u16x2ToU32(u16x4.slice(0, 2)))) && + isFiniteF32(reinterpretU32AsF32(u16x2ToU32(u16x4.slice(2, 4)))) + ). + map((e) => ({ + input: u16x4ToVec4F16(e), + expected: bitcastVec4F16ToVec2F32Comparator(e) + })), + vec4_f16_inf_nan_to_vec2_f32: () => + f16Vec2FiniteInfNanInU16x4.map((e) => ({ + input: u16x4ToVec4F16(e), + expected: bitcastVec4F16ToVec2F32Comparator(e) + })) +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/bitcast.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/bitcast.spec.js index d01c43dbfb..a2e9ab49e7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/bitcast.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/bitcast.spec.js @@ -13,6 +13,9 @@ S is i32, u32, f32 T is i32, u32, f32, and T is not S Reinterpretation of bits. Beware non-normal f32 values. +@const @must_use fn bitcast(e : Type.abstractInt) -> T +@const @must_use fn bitcast>(e : vecN) -> T + @const @must_use fn bitcast(e: vec2 ) -> T @const @must_use fn bitcast>(e: vec4 ) -> vec2 @const @must_use fn bitcast>(e: T ) -> vec2 @@ -20,823 +23,26 @@ Reinterpretation of bits. Beware non-normal f32 values. T is i32, u32, f32 `; import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; -import { assert } from '../../../../../../common/util/util.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { alwaysPass, anyOf } from '../../../../../util/compare.js'; -import { kBit, kValue } from '../../../../../util/constants.js'; +import { anyOf } from '../../../../../util/compare.js'; import { f32, - i32, u32, - f16, - TypeF32, - TypeI32, - TypeU32, - TypeF16, - TypeVec, - Vector, - - toVector } from + i32, + abstractFloat, + uint32ToFloat32, + u32Bits, + Type } from '../../../../../util/conversion.js'; -import { FPInterval, FP } from '../../../../../util/floating_point.js'; -import { - fullF32Range, - fullI32Range, - fullU32Range, - fullF16Range, - linearRange, - isSubnormalNumberF32, - isSubnormalNumberF16, - cartesianProduct, - isFiniteF32, - isFiniteF16 } from -'../../../../../util/math.js'; -import { - reinterpretI32AsF32, - reinterpretI32AsU32, - reinterpretF32AsI32, - reinterpretF32AsU32, - reinterpretU32AsF32, - reinterpretU32AsI32, - reinterpretU16AsF16, - reinterpretF16AsU16 } from -'../../../../../util/reinterpret.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { FP } from '../../../../../util/floating_point.js'; +import { scalarF32Range } from '../../../../../util/math.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; +import { d } from './bitcast.cache.js'; import { builtinWithPredeclaration } from './builtin.js'; export const g = makeTestGroup(GPUTest); -const numNaNs = 11; -const f32InfAndNaNInU32 = [ -// Cover NaNs evenly in integer space. -// The positive NaN with the lowest integer representation is the integer -// for infinity, plus one. -// The positive NaN with the highest integer representation is i32.max (!) -...linearRange(kBit.f32.positive.infinity + 1, kBit.i32.positive.max, numNaNs), -// The negative NaN with the lowest integer representation is the integer -// for negative infinity, plus one. -// The negative NaN with the highest integer representation is u32.max (!) -...linearRange(kBit.f32.negative.infinity + 1, kBit.u32.max, numNaNs), -kBit.f32.positive.infinity, -kBit.f32.negative.infinity]; - -const f32InfAndNaNInF32 = f32InfAndNaNInU32.map((u) => reinterpretU32AsF32(u)); -const f32InfAndNaNInI32 = f32InfAndNaNInU32.map((u) => reinterpretU32AsI32(u)); - -const f32ZerosInU32 = [0, kBit.f32.negative.zero]; -const f32ZerosInF32 = f32ZerosInU32.map((u) => reinterpretU32AsF32(u)); -const f32ZerosInI32 = f32ZerosInU32.map((u) => reinterpretU32AsI32(u)); -const f32ZerosInterval = new FPInterval('f32', -0.0, 0.0); - -// f32FiniteRange is a list of finite f32s. fullF32Range() already -// has +0, we only need to add -0. -const f32FiniteRange = [...fullF32Range(), kValue.f32.negative.zero]; -const f32RangeWithInfAndNaN = [...f32FiniteRange, ...f32InfAndNaNInF32]; - -// F16 values, finite, Inf/NaN, and zeros. Represented in float and u16. -const f16FiniteInF16 = [...fullF16Range(), kValue.f16.negative.zero]; -const f16FiniteInU16 = f16FiniteInF16.map((u) => reinterpretF16AsU16(u)); - -const f16InfAndNaNInU16 = [ -// Cover NaNs evenly in integer space. -// The positive NaN with the lowest integer representation is the integer -// for infinity, plus one. -// The positive NaN with the highest integer representation is u16 0x7fff i.e. 32767. -...linearRange(kBit.f16.positive.infinity + 1, 32767, numNaNs).map((v) => Math.ceil(v)), -// The negative NaN with the lowest integer representation is the integer -// for negative infinity, plus one. -// The negative NaN with the highest integer representation is u16 0xffff i.e. 65535 -...linearRange(kBit.f16.negative.infinity + 1, 65535, numNaNs).map((v) => Math.floor(v)), -kBit.f16.positive.infinity, -kBit.f16.negative.infinity]; - -const f16InfAndNaNInF16 = f16InfAndNaNInU16.map((u) => reinterpretU16AsF16(u)); - -const f16ZerosInU16 = [kBit.f16.negative.zero, 0]; - -// f16 interval that match +/-0.0. -const f16ZerosInterval = new FPInterval('f16', -0.0, 0.0); - -/** - * @returns an u32 whose lower and higher 16bits are the two elements of the - * given array of two u16 respectively, in little-endian. - */ -function u16x2ToU32(u16x2) { - assert(u16x2.length === 2); - // Create a DataView with 4 bytes buffer. - const buffer = new ArrayBuffer(4); - const view = new DataView(buffer); - // Enforce little-endian. - view.setUint16(0, u16x2[0], true); - view.setUint16(2, u16x2[1], true); - return view.getUint32(0, true); -} - -/** - * @returns an array of two u16, respectively the lower and higher 16bits of - * given u32 in little-endian. - */ -function u32ToU16x2(u32) { - // Create a DataView with 4 bytes buffer. - const buffer = new ArrayBuffer(4); - const view = new DataView(buffer); - // Enforce little-endian. - view.setUint32(0, u32, true); - return [view.getUint16(0, true), view.getUint16(2, true)]; -} - -/** - * @returns a vec2 from an array of two u16, each reinterpreted as f16. - */ -function u16x2ToVec2F16(u16x2) { - assert(u16x2.length === 2); - return toVector(u16x2.map(reinterpretU16AsF16), f16); -} - -/** - * @returns a vec4 from an array of four u16, each reinterpreted as f16. - */ -function u16x4ToVec4F16(u16x4) { - assert(u16x4.length === 4); - return toVector(u16x4.map(reinterpretU16AsF16), f16); -} - -/** - * @returns true if and only if a given u32 can bitcast to a vec2 with all elements - * being finite f16 values. - */ -function canU32BitcastToFiniteVec2F16(u32) { - return u32ToU16x2(u32). - map((u16) => isFiniteF16(reinterpretU16AsF16(u16))). - reduce((a, b) => a && b, true); -} - -/** - * @returns an array of N elements with the i-th element being an array of len elements - * [a_i, a_((i+1)%N), ..., a_((i+len-1)%N)], for the input array of N element [a_1, ... a_N] - * and the given len. For example, slidingSlice([1, 2, 3], 2) result in - * [[1, 2], [2, 3], [3, 1]]. - * This helper function is used for generating vector cases from scalar values array. - */ -function slidingSlice(input, len) { - const result = []; - for (let i = 0; i < input.length; i++) { - const sub = []; - for (let j = 0; j < len; j++) { - sub.push(input[(i + j) % input.length]); - } - result.push(sub); - } - return result; -} - -// vec2 interesting (zeros, Inf, and NaN) values for testing cases. -// vec2 values that has at least one Inf/NaN f16 element, reinterpreted as u32/i32. -const f16Vec2InfAndNaNInU32 = [ -...cartesianProduct(f16InfAndNaNInU16, [...f16InfAndNaNInU16, ...f16FiniteInU16]), -...cartesianProduct(f16FiniteInU16, f16InfAndNaNInU16)]. -map(u16x2ToU32); -const f16Vec2InfAndNaNInI32 = f16Vec2InfAndNaNInU32.map((u) => reinterpretU32AsI32(u)); -// vec2 values with two f16 0.0 element, reinterpreted as u32/i32. -const f16Vec2ZerosInU32 = cartesianProduct(f16ZerosInU16, f16ZerosInU16).map(u16x2ToU32); -const f16Vec2ZerosInI32 = f16Vec2ZerosInU32.map((u) => reinterpretU32AsI32(u)); - -// i32/u32/f32 range for bitcasting to vec2 -// u32 values for bitcasting to vec2 finite, Inf, and NaN. -const u32RangeForF16Vec2FiniteInfNaN = [ -...fullU32Range(), -...f16Vec2ZerosInU32, -...f16Vec2InfAndNaNInU32]; - -// u32 values for bitcasting to finite only vec2, used for constant evaluation. -const u32RangeForF16Vec2Finite = u32RangeForF16Vec2FiniteInfNaN.filter( - canU32BitcastToFiniteVec2F16 -); -// i32 values for bitcasting to vec2 finite, zeros, Inf, and NaN. -const i32RangeForF16Vec2FiniteInfNaN = [ -...fullI32Range(), -...f16Vec2ZerosInI32, -...f16Vec2InfAndNaNInI32]; - -// i32 values for bitcasting to finite only vec2, used for constant evaluation. -const i32RangeForF16Vec2Finite = i32RangeForF16Vec2FiniteInfNaN.filter((u) => -canU32BitcastToFiniteVec2F16(reinterpretI32AsU32(u)) -); -// f32 values with finite/Inf/NaN f32, for bitcasting to vec2 finite, zeros, Inf, and NaN. -const f32RangeWithInfAndNaNForF16Vec2FiniteInfNaN = [ -...f32RangeWithInfAndNaN, -...u32RangeForF16Vec2FiniteInfNaN.map(reinterpretU32AsF32)]; - -// Finite f32 values for bitcasting to finite only vec2, used for constant evaluation. -const f32FiniteRangeForF16Vec2Finite = f32RangeWithInfAndNaNForF16Vec2FiniteInfNaN. -filter(isFiniteF32). -filter((u) => canU32BitcastToFiniteVec2F16(reinterpretF32AsU32(u))); - -// vec2 cases for bitcasting to i32/u32/f32, by combining f16 values into pairs -const f16Vec2FiniteInU16x2 = slidingSlice(f16FiniteInU16, 2); -const f16Vec2FiniteInfNanInU16x2 = slidingSlice([...f16FiniteInU16, ...f16InfAndNaNInU16], 2); -// vec4 cases for bitcasting to vec2, by combining f16 values 4-by-4 -const f16Vec2FiniteInU16x4 = slidingSlice(f16FiniteInU16, 4); -const f16Vec2FiniteInfNanInU16x4 = slidingSlice([...f16FiniteInU16, ...f16InfAndNaNInU16], 4); - -// alwaysPass comparator for i32/u32/f32 cases. For f32/f16 we also use unbound interval, which -// allow per-element unbounded expectation for vector. -const anyF32 = alwaysPass('any f32'); -const anyI32 = alwaysPass('any i32'); -const anyU32 = alwaysPass('any u32'); - -// Unbounded FPInterval -const f32UnboundedInterval = FP.f32.constants().unboundedInterval; -const f16UnboundedInterval = FP.f16.constants().unboundedInterval; - -// i32 and u32 cases for bitcasting to f32. -// i32 cases for bitcasting to f32 finite, zeros, Inf, and NaN. -const i32RangeForF32FiniteInfNaN = [ -...fullI32Range(), -...f32ZerosInI32, -...f32InfAndNaNInI32]; - -// i32 cases for bitcasting to f32 finite only. -const i32RangeForF32Finite = i32RangeForF32FiniteInfNaN.filter((i) => -isFiniteF32(reinterpretI32AsF32(i)) -); -// u32 cases for bitcasting to f32 finite, zeros, Inf, and NaN. -const u32RangeForF32FiniteInfNaN = [ -...fullU32Range(), -...f32ZerosInU32, -...f32InfAndNaNInU32]; - -// u32 cases for bitcasting to f32 finite only. -const u32RangeForF32Finite = u32RangeForF32FiniteInfNaN.filter((u) => -isFiniteF32(reinterpretU32AsF32(u)) -); - -/** - * @returns a Comparator for checking if a f32 value is a valid - * bitcast conversion from f32. - */ -function bitcastF32ToF32Comparator(f) { - if (!isFiniteF32(f)) return anyF32; - const acceptable = [f, ...(isSubnormalNumberF32(f) ? f32ZerosInF32 : [])]; - return anyOf(...acceptable.map(f32)); -} - -/** - * @returns a Comparator for checking if a u32 value is a valid - * bitcast conversion from f32. - */ -function bitcastF32ToU32Comparator(f) { - if (!isFiniteF32(f)) return anyU32; - const acceptable = [ - reinterpretF32AsU32(f), - ...(isSubnormalNumberF32(f) ? f32ZerosInU32 : [])]; - - return anyOf(...acceptable.map(u32)); -} - -/** - * @returns a Comparator for checking if a i32 value is a valid - * bitcast conversion from f32. - */ -function bitcastF32ToI32Comparator(f) { - if (!isFiniteF32(f)) return anyI32; - const acceptable = [ - reinterpretF32AsI32(f), - ...(isSubnormalNumberF32(f) ? f32ZerosInI32 : [])]; - - return anyOf(...acceptable.map(i32)); -} - -/** - * @returns a Comparator for checking if a f32 value is a valid - * bitcast conversion from i32. - */ -function bitcastI32ToF32Comparator(i) { - const f = reinterpretI32AsF32(i); - if (!isFiniteF32(f)) return anyI32; - // Positive or negative zero bit pattern map to any zero. - if (f32ZerosInI32.includes(i)) return anyOf(...f32ZerosInF32.map(f32)); - const acceptable = [f, ...(isSubnormalNumberF32(f) ? f32ZerosInF32 : [])]; - return anyOf(...acceptable.map(f32)); -} - -/** - * @returns a Comparator for checking if a f32 value is a valid - * bitcast conversion from u32. - */ -function bitcastU32ToF32Comparator(u) { - const f = reinterpretU32AsF32(u); - if (!isFiniteF32(f)) return anyU32; - // Positive or negative zero bit pattern map to any zero. - if (f32ZerosInU32.includes(u)) return anyOf(...f32ZerosInF32.map(f32)); - const acceptable = [f, ...(isSubnormalNumberF32(f) ? f32ZerosInF32 : [])]; - return anyOf(...acceptable.map(f32)); -} - -/** - * @returns an array of expected f16 FPInterval for the given bitcasted f16 value, which may be - * subnormal, Inf, or NaN. Test cases that bitcasted to vector of f16 use this function to get - * per-element expectation and build vector expectation using cartesianProduct. - */ -function generateF16ExpectationIntervals(bitcastedF16Value) { - // If the bitcasted f16 value is inf or nan, the result is unbounded - if (!isFiniteF16(bitcastedF16Value)) { - return [f16UnboundedInterval]; - } - // If the casted f16 value is +/-0.0, the result can be one of both. Note that in JS -0.0 === 0.0. - if (bitcastedF16Value === 0.0) { - return [f16ZerosInterval]; - } - const exactInterval = FP.f16.toInterval(bitcastedF16Value); - // If the casted f16 value is subnormal, it also may be flushed to +/-0.0. - return [exactInterval, ...(isSubnormalNumberF16(bitcastedF16Value) ? [f16ZerosInterval] : [])]; -} - -/** - * @returns a Comparator for checking if a f16 value is a valid - * bitcast conversion from f16. - */ -function bitcastF16ToF16Comparator(f) { - if (!isFiniteF16(f)) return anyOf(f16UnboundedInterval); - return anyOf(...generateF16ExpectationIntervals(f)); -} - -/** - * @returns a Comparator for checking if a vec2 is a valid bitcast - * conversion from u32. - */ -function bitcastU32ToVec2F16Comparator(u) { - const bitcastedVec2F16InU16x2 = u32ToU16x2(u).map(reinterpretU16AsF16); - // Generate expection for vec2 f16 result, by generating expected intervals for each elements and - // then do cartesian product. - const expectedIntervalsCombination = cartesianProduct( - ...bitcastedVec2F16InU16x2.map(generateF16ExpectationIntervals) - ); - return anyOf(...expectedIntervalsCombination); -} - -/** - * @returns a Comparator for checking if a vec2 value is a valid - * bitcast conversion from i32. - */ -function bitcastI32ToVec2F16Comparator(i) { - const bitcastedVec2F16InU16x2 = u32ToU16x2(reinterpretI32AsU32(i)).map(reinterpretU16AsF16); - // Generate expection for vec2 f16 result, by generating expected intervals for each elements and - // then do cartesian product. - const expectedIntervalsCombination = cartesianProduct( - ...bitcastedVec2F16InU16x2.map(generateF16ExpectationIntervals) - ); - return anyOf(...expectedIntervalsCombination); -} - -/** - * @returns a Comparator for checking if a vec2 value is a valid - * bitcast conversion from f32. - */ -function bitcastF32ToVec2F16Comparator(f) { - // If input f32 is not finite, it can be evaluated to any value and thus any result f16 vec2 is - // possible. - if (!isFiniteF32(f)) { - return anyOf([f16UnboundedInterval, f16UnboundedInterval]); - } - const bitcastedVec2F16InU16x2 = u32ToU16x2(reinterpretF32AsU32(f)).map(reinterpretU16AsF16); - // Generate expection for vec2 f16 result, by generating expected intervals for each elements and - // then do cartesian product. - const expectedIntervalsCombination = cartesianProduct( - ...bitcastedVec2F16InU16x2.map(generateF16ExpectationIntervals) - ); - return anyOf(...expectedIntervalsCombination); -} - -/** - * @returns a Comparator for checking if a vec4 is a valid - * bitcast conversion from vec2. - */ -function bitcastVec2U32ToVec4F16Comparator(u32x2) { - assert(u32x2.length === 2); - const bitcastedVec4F16InU16x4 = u32x2.flatMap(u32ToU16x2).map(reinterpretU16AsF16); - // Generate expection for vec4 f16 result, by generating expected intervals for each elements and - // then do cartesian product. - const expectedIntervalsCombination = cartesianProduct( - ...bitcastedVec4F16InU16x4.map(generateF16ExpectationIntervals) - ); - return anyOf(...expectedIntervalsCombination); -} - -/** - * @returns a Comparator for checking if a vec4 is a valid - * bitcast conversion from vec2. - */ -function bitcastVec2I32ToVec4F16Comparator(i32x2) { - assert(i32x2.length === 2); - const bitcastedVec4F16InU16x4 = i32x2. - map(reinterpretI32AsU32). - flatMap(u32ToU16x2). - map(reinterpretU16AsF16); - // Generate expection for vec4 f16 result, by generating expected intervals for each elements and - // then do cartesian product. - const expectedIntervalsCombination = cartesianProduct( - ...bitcastedVec4F16InU16x4.map(generateF16ExpectationIntervals) - ); - return anyOf(...expectedIntervalsCombination); -} - -/** - * @returns a Comparator for checking if a vec4 is a valid - * bitcast conversion from vec2. - */ -function bitcastVec2F32ToVec4F16Comparator(f32x2) { - assert(f32x2.length === 2); - const bitcastedVec4F16InU16x4 = f32x2. - map(reinterpretF32AsU32). - flatMap(u32ToU16x2). - map(reinterpretU16AsF16); - // Generate expection for vec4 f16 result, by generating expected intervals for each elements and - // then do cartesian product. - const expectedIntervalsCombination = cartesianProduct( - ...bitcastedVec4F16InU16x4.map(generateF16ExpectationIntervals) - ); - return anyOf(...expectedIntervalsCombination); -} - -// Structure that store the expectations of a single 32bit scalar/element bitcasted from two f16. - - - - - - - -/** - * @returns the array of possible 16bits, represented in u16, that bitcasted - * from a given finite f16 represented in u16, handling the possible subnormal - * flushing. Used to build up 32bits or larger results. - */ -function possibleBitsInU16FromFiniteF16InU16(f16InU16) { - const h = reinterpretU16AsF16(f16InU16); - assert(isFiniteF16(h)); - return [f16InU16, ...(isSubnormalNumberF16(h) ? f16ZerosInU16 : [])]; -} - -/** - * @returns the expectation for a single 32bit scalar bitcasted from given pair of - * f16, result in ExpectionFor32BitsScalarFromF16x2. - */ -function possible32BitScalarIntervalsFromF16x2( -f16x2InU16x2, -type) -{ - assert(f16x2InU16x2.length === 2); - let reinterpretFromU32; - let expectationsForValue; - let unboundedExpectations; - if (type === 'u32') { - reinterpretFromU32 = (x) => x; - expectationsForValue = (x) => [u32(x)]; - // Scalar expectation can not express "unbounded" for i32 and u32, so use 0 here as a - // placeholder, and the possibleExpectations should be ignored if the result is unbounded. - unboundedExpectations = [u32(0)]; - } else if (type === 'i32') { - reinterpretFromU32 = (x) => reinterpretU32AsI32(x); - expectationsForValue = (x) => [i32(x)]; - // Scalar expectation can not express "unbounded" for i32 and u32, so use 0 here as a - // placeholder, and the possibleExpectations should be ignored if the result is unbounded. - unboundedExpectations = [i32(0)]; - } else { - assert(type === 'f32'); - reinterpretFromU32 = (x) => reinterpretU32AsF32(x); - expectationsForValue = (x) => { - // Handle the possible Inf/NaN/zeros and subnormal cases for f32 result. - if (!isFiniteF32(x)) { - return [f32UnboundedInterval]; - } - // If the casted f16 value is +/-0.0, the result can be one of both. Note that in JS -0.0 === 0.0. - if (x === 0.0) { - return [f32ZerosInterval]; - } - const exactInterval = FP.f32.toInterval(x); - // If the casted f16 value is subnormal, it also may be flushed to +/-0.0. - return [exactInterval, ...(isSubnormalNumberF32(x) ? [f32ZerosInterval] : [])]; - }; - unboundedExpectations = [f32UnboundedInterval]; - } - // Return unbounded expection if f16 Inf/NaN occurs - if ( - !isFiniteF16(reinterpretU16AsF16(f16x2InU16x2[0])) || - !isFiniteF16(reinterpretU16AsF16(f16x2InU16x2[1]))) - { - return { possibleExpectations: unboundedExpectations, isUnbounded: true }; - } - const possibleU16Bits = f16x2InU16x2.map(possibleBitsInU16FromFiniteF16InU16); - const possibleExpectations = cartesianProduct(...possibleU16Bits).flatMap( - (possibleBitsU16x2) => { - assert(possibleBitsU16x2.length === 2); - return expectationsForValue(reinterpretFromU32(u16x2ToU32(possibleBitsU16x2))); - } - ); - return { possibleExpectations, isUnbounded: false }; -} - -/** - * @returns a Comparator for checking if a u32 value is a valid - * bitcast conversion from vec2 f16. - */ -function bitcastVec2F16ToU32Comparator(vec2F16InU16x2) { - assert(vec2F16InU16x2.length === 2); - const expectations = possible32BitScalarIntervalsFromF16x2(vec2F16InU16x2, 'u32'); - // Return alwaysPass if result is expected unbounded. - if (expectations.isUnbounded) { - return anyU32; - } - return anyOf(...expectations.possibleExpectations); -} - -/** - * @returns a Comparator for checking if a i32 value is a valid - * bitcast conversion from vec2 f16. - */ -function bitcastVec2F16ToI32Comparator(vec2F16InU16x2) { - assert(vec2F16InU16x2.length === 2); - const expectations = possible32BitScalarIntervalsFromF16x2(vec2F16InU16x2, 'i32'); - // Return alwaysPass if result is expected unbounded. - if (expectations.isUnbounded) { - return anyI32; - } - return anyOf(...expectations.possibleExpectations); -} - -/** - * @returns a Comparator for checking if a i32 value is a valid - * bitcast conversion from vec2 f16. - */ -function bitcastVec2F16ToF32Comparator(vec2F16InU16x2) { - assert(vec2F16InU16x2.length === 2); - const expectations = possible32BitScalarIntervalsFromF16x2(vec2F16InU16x2, 'f32'); - // Return alwaysPass if result is expected unbounded. - if (expectations.isUnbounded) { - return anyF32; - } - return anyOf(...expectations.possibleExpectations); -} - -/** - * @returns a Comparator for checking if a vec2 u32 value is a valid - * bitcast conversion from vec4 f16. - */ -function bitcastVec4F16ToVec2U32Comparator(vec4F16InU16x4) { - assert(vec4F16InU16x4.length === 4); - const expectationsPerElement = [vec4F16InU16x4.slice(0, 2), vec4F16InU16x4.slice(2, 4)].map((e) => - possible32BitScalarIntervalsFromF16x2(e, 'u32') - ); - // Return alwaysPass if any element is expected unbounded. Although it may be only one unbounded - // element in the result vector, currently we don't have a way to build a comparator that expect - // only one element of i32/u32 vector unbounded. - if (expectationsPerElement.map((e) => e.isUnbounded).reduce((a, b) => a || b, false)) { - return alwaysPass('any vec2'); - } - return anyOf( - ...cartesianProduct(...expectationsPerElement.map((e) => e.possibleExpectations)).map( - (e) => new Vector(e) - ) - ); -} - -/** - * @returns a Comparator for checking if a vec2 i32 value is a valid - * bitcast conversion from vec4 f16. - */ -function bitcastVec4F16ToVec2I32Comparator(vec4F16InU16x4) { - assert(vec4F16InU16x4.length === 4); - const expectationsPerElement = [vec4F16InU16x4.slice(0, 2), vec4F16InU16x4.slice(2, 4)].map((e) => - possible32BitScalarIntervalsFromF16x2(e, 'i32') - ); - // Return alwaysPass if any element is expected unbounded. Although it may be only one unbounded - // element in the result vector, currently we don't have a way to build a comparator that expect - // only one element of i32/u32 vector unbounded. - if (expectationsPerElement.map((e) => e.isUnbounded).reduce((a, b) => a || b, false)) { - return alwaysPass('any vec2'); - } - return anyOf( - ...cartesianProduct(...expectationsPerElement.map((e) => e.possibleExpectations)).map( - (e) => new Vector(e) - ) - ); -} - -/** - * @returns a Comparator for checking if a vec2 f32 value is a valid - * bitcast conversion from vec4 f16. - */ -function bitcastVec4F16ToVec2F32Comparator(vec4F16InU16x4) { - assert(vec4F16InU16x4.length === 4); - const expectationsPerElement = [vec4F16InU16x4.slice(0, 2), vec4F16InU16x4.slice(2, 4)].map((e) => - possible32BitScalarIntervalsFromF16x2(e, 'f32') - ); - return anyOf( - ...cartesianProduct(...expectationsPerElement.map((e) => e.possibleExpectations)).map((e) => [ - e[0], - e[1]] - ) - ); -} - -export const d = makeCaseCache('bitcast', { - // Identity Cases - i32_to_i32: () => fullI32Range().map((e) => ({ input: i32(e), expected: i32(e) })), - u32_to_u32: () => fullU32Range().map((e) => ({ input: u32(e), expected: u32(e) })), - f32_inf_nan_to_f32: () => - f32RangeWithInfAndNaN.map((e) => ({ - input: f32(e), - expected: bitcastF32ToF32Comparator(e) - })), - f32_to_f32: () => - f32FiniteRange.map((e) => ({ input: f32(e), expected: bitcastF32ToF32Comparator(e) })), - f16_inf_nan_to_f16: () => - [...f16FiniteInF16, ...f16InfAndNaNInF16].map((e) => ({ - input: f16(e), - expected: bitcastF16ToF16Comparator(e) - })), - f16_to_f16: () => - f16FiniteInF16.map((e) => ({ input: f16(e), expected: bitcastF16ToF16Comparator(e) })), - - // i32,u32,f32 to different i32,u32,f32 - i32_to_u32: () => fullI32Range().map((e) => ({ input: i32(e), expected: u32(e) })), - i32_to_f32: () => - i32RangeForF32Finite.map((e) => ({ - input: i32(e), - expected: bitcastI32ToF32Comparator(e) - })), - i32_to_f32_inf_nan: () => - i32RangeForF32FiniteInfNaN.map((e) => ({ - input: i32(e), - expected: bitcastI32ToF32Comparator(e) - })), - u32_to_i32: () => fullU32Range().map((e) => ({ input: u32(e), expected: i32(e) })), - u32_to_f32: () => - u32RangeForF32Finite.map((e) => ({ - input: u32(e), - expected: bitcastU32ToF32Comparator(e) - })), - u32_to_f32_inf_nan: () => - u32RangeForF32FiniteInfNaN.map((e) => ({ - input: u32(e), - expected: bitcastU32ToF32Comparator(e) - })), - f32_inf_nan_to_i32: () => - f32RangeWithInfAndNaN.map((e) => ({ - input: f32(e), - expected: bitcastF32ToI32Comparator(e) - })), - f32_to_i32: () => - f32FiniteRange.map((e) => ({ input: f32(e), expected: bitcastF32ToI32Comparator(e) })), - - f32_inf_nan_to_u32: () => - f32RangeWithInfAndNaN.map((e) => ({ - input: f32(e), - expected: bitcastF32ToU32Comparator(e) - })), - f32_to_u32: () => - f32FiniteRange.map((e) => ({ input: f32(e), expected: bitcastF32ToU32Comparator(e) })), - - // i32,u32,f32 to vec2 - u32_to_vec2_f16_inf_nan: () => - u32RangeForF16Vec2FiniteInfNaN.map((e) => ({ - input: u32(e), - expected: bitcastU32ToVec2F16Comparator(e) - })), - u32_to_vec2_f16: () => - u32RangeForF16Vec2Finite.map((e) => ({ - input: u32(e), - expected: bitcastU32ToVec2F16Comparator(e) - })), - i32_to_vec2_f16_inf_nan: () => - i32RangeForF16Vec2FiniteInfNaN.map((e) => ({ - input: i32(e), - expected: bitcastI32ToVec2F16Comparator(e) - })), - i32_to_vec2_f16: () => - i32RangeForF16Vec2Finite.map((e) => ({ - input: i32(e), - expected: bitcastI32ToVec2F16Comparator(e) - })), - f32_inf_nan_to_vec2_f16_inf_nan: () => - f32RangeWithInfAndNaNForF16Vec2FiniteInfNaN.map((e) => ({ - input: f32(e), - expected: bitcastF32ToVec2F16Comparator(e) - })), - f32_to_vec2_f16: () => - f32FiniteRangeForF16Vec2Finite.map((e) => ({ - input: f32(e), - expected: bitcastF32ToVec2F16Comparator(e) - })), - - // vec2, vec2, vec2 to vec4 - vec2_i32_to_vec4_f16_inf_nan: () => - slidingSlice(i32RangeForF16Vec2FiniteInfNaN, 2).map((e) => ({ - input: toVector(e, i32), - expected: bitcastVec2I32ToVec4F16Comparator(e) - })), - vec2_i32_to_vec4_f16: () => - slidingSlice(i32RangeForF16Vec2Finite, 2).map((e) => ({ - input: toVector(e, i32), - expected: bitcastVec2I32ToVec4F16Comparator(e) - })), - vec2_u32_to_vec4_f16_inf_nan: () => - slidingSlice(u32RangeForF16Vec2FiniteInfNaN, 2).map((e) => ({ - input: toVector(e, u32), - expected: bitcastVec2U32ToVec4F16Comparator(e) - })), - vec2_u32_to_vec4_f16: () => - slidingSlice(u32RangeForF16Vec2Finite, 2).map((e) => ({ - input: toVector(e, u32), - expected: bitcastVec2U32ToVec4F16Comparator(e) - })), - vec2_f32_inf_nan_to_vec4_f16_inf_nan: () => - slidingSlice(f32RangeWithInfAndNaNForF16Vec2FiniteInfNaN, 2).map((e) => ({ - input: toVector(e, f32), - expected: bitcastVec2F32ToVec4F16Comparator(e) - })), - vec2_f32_to_vec4_f16: () => - slidingSlice(f32FiniteRangeForF16Vec2Finite, 2).map((e) => ({ - input: toVector(e, f32), - expected: bitcastVec2F32ToVec4F16Comparator(e) - })), - - // vec2 to i32, u32, f32 - vec2_f16_to_u32: () => - f16Vec2FiniteInU16x2.map((e) => ({ - input: u16x2ToVec2F16(e), - expected: bitcastVec2F16ToU32Comparator(e) - })), - vec2_f16_inf_nan_to_u32: () => - f16Vec2FiniteInfNanInU16x2.map((e) => ({ - input: u16x2ToVec2F16(e), - expected: bitcastVec2F16ToU32Comparator(e) - })), - vec2_f16_to_i32: () => - f16Vec2FiniteInU16x2.map((e) => ({ - input: u16x2ToVec2F16(e), - expected: bitcastVec2F16ToI32Comparator(e) - })), - vec2_f16_inf_nan_to_i32: () => - f16Vec2FiniteInfNanInU16x2.map((e) => ({ - input: u16x2ToVec2F16(e), - expected: bitcastVec2F16ToI32Comparator(e) - })), - vec2_f16_to_f32_finite: () => - f16Vec2FiniteInU16x2. - filter((u16x2) => isFiniteF32(reinterpretU32AsF32(u16x2ToU32(u16x2)))). - map((e) => ({ - input: u16x2ToVec2F16(e), - expected: bitcastVec2F16ToF32Comparator(e) - })), - vec2_f16_inf_nan_to_f32: () => - f16Vec2FiniteInfNanInU16x2.map((e) => ({ - input: u16x2ToVec2F16(e), - expected: bitcastVec2F16ToF32Comparator(e) - })), - - // vec4 to vec2 of i32, u32, f32 - vec4_f16_to_vec2_u32: () => - f16Vec2FiniteInU16x4.map((e) => ({ - input: u16x4ToVec4F16(e), - expected: bitcastVec4F16ToVec2U32Comparator(e) - })), - vec4_f16_inf_nan_to_vec2_u32: () => - f16Vec2FiniteInfNanInU16x4.map((e) => ({ - input: u16x4ToVec4F16(e), - expected: bitcastVec4F16ToVec2U32Comparator(e) - })), - vec4_f16_to_vec2_i32: () => - f16Vec2FiniteInU16x4.map((e) => ({ - input: u16x4ToVec4F16(e), - expected: bitcastVec4F16ToVec2I32Comparator(e) - })), - vec4_f16_inf_nan_to_vec2_i32: () => - f16Vec2FiniteInfNanInU16x4.map((e) => ({ - input: u16x4ToVec4F16(e), - expected: bitcastVec4F16ToVec2I32Comparator(e) - })), - vec4_f16_to_vec2_f32_finite: () => - f16Vec2FiniteInU16x4. - filter( - (u16x4) => - isFiniteF32(reinterpretU32AsF32(u16x2ToU32(u16x4.slice(0, 2)))) && - isFiniteF32(reinterpretU32AsF32(u16x2ToU32(u16x4.slice(2, 4)))) - ). - map((e) => ({ - input: u16x4ToVec4F16(e), - expected: bitcastVec4F16ToVec2F32Comparator(e) - })), - vec4_f16_inf_nan_to_vec2_f32: () => - f16Vec2FiniteInfNanInU16x4.map((e) => ({ - input: u16x4ToVec4F16(e), - expected: bitcastVec4F16ToVec2F32Comparator(e) - })) -}); - /** * @returns a ShaderBuilder that generates a call to bitcast, * using appropriate destination type, which optionally can be @@ -865,7 +71,7 @@ combine('alias', [false, true]) ). fn(async (t) => { const cases = await d.get('i32_to_i32'); - await run(t, bitcastBuilder('i32', t.params), [TypeI32], TypeI32, t.params, cases); + await run(t, bitcastBuilder('i32', t.params), [Type.i32], Type.i32, t.params, cases); }); g.test('u32_to_u32'). @@ -879,7 +85,7 @@ combine('alias', [false, true]) ). fn(async (t) => { const cases = await d.get('u32_to_u32'); - await run(t, bitcastBuilder('u32', t.params), [TypeU32], TypeU32, t.params, cases); + await run(t, bitcastBuilder('u32', t.params), [Type.u32], Type.u32, t.params, cases); }); g.test('f32_to_f32'). @@ -896,7 +102,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'f32_to_f32' : 'f32_inf_nan_to_f32' ); - await run(t, bitcastBuilder('f32', t.params), [TypeF32], TypeF32, t.params, cases); + await run(t, bitcastBuilder('f32', t.params), [Type.f32], Type.f32, t.params, cases); }); // To i32 from u32, f32 @@ -911,7 +117,7 @@ combine('alias', [false, true]) ). fn(async (t) => { const cases = await d.get('u32_to_i32'); - await run(t, bitcastBuilder('i32', t.params), [TypeU32], TypeI32, t.params, cases); + await run(t, bitcastBuilder('i32', t.params), [Type.u32], Type.i32, t.params, cases); }); g.test('f32_to_i32'). @@ -928,7 +134,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'f32_to_i32' : 'f32_inf_nan_to_i32' ); - await run(t, bitcastBuilder('i32', t.params), [TypeF32], TypeI32, t.params, cases); + await run(t, bitcastBuilder('i32', t.params), [Type.f32], Type.i32, t.params, cases); }); // To u32 from i32, f32 @@ -943,7 +149,7 @@ combine('alias', [false, true]) ). fn(async (t) => { const cases = await d.get('i32_to_u32'); - await run(t, bitcastBuilder('u32', t.params), [TypeI32], TypeU32, t.params, cases); + await run(t, bitcastBuilder('u32', t.params), [Type.i32], Type.u32, t.params, cases); }); g.test('f32_to_u32'). @@ -960,7 +166,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'f32_to_u32' : 'f32_inf_nan_to_u32' ); - await run(t, bitcastBuilder('u32', t.params), [TypeF32], TypeU32, t.params, cases); + await run(t, bitcastBuilder('u32', t.params), [Type.f32], Type.u32, t.params, cases); }); // To f32 from i32, u32 @@ -978,7 +184,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'i32_to_f32' : 'i32_to_f32_inf_nan' ); - await run(t, bitcastBuilder('f32', t.params), [TypeI32], TypeF32, t.params, cases); + await run(t, bitcastBuilder('f32', t.params), [Type.i32], Type.f32, t.params, cases); }); g.test('u32_to_f32'). @@ -995,7 +201,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'u32_to_f32' : 'u32_to_f32_inf_nan' ); - await run(t, bitcastBuilder('f32', t.params), [TypeU32], TypeF32, t.params, cases); + await run(t, bitcastBuilder('f32', t.params), [Type.u32], Type.f32, t.params, cases); }); // 16 bit types @@ -1020,7 +226,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'f16_to_f16' : 'f16_inf_nan_to_f16' ); - await run(t, bitcastBuilder('f16', t.params), [TypeF16], TypeF16, t.params, cases); + await run(t, bitcastBuilder('f16', t.params), [Type.f16], Type.f16, t.params, cases); }); // f16: 32-bit scalar numeric to vec2 @@ -1036,14 +242,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'i32_to_vec2_f16' : 'i32_to_vec2_f16_inf_nan' ); - await run( - t, - bitcastBuilder('vec2', t.params), - [TypeI32], - TypeVec(2, TypeF16), - t.params, - cases - ); + await run(t, bitcastBuilder('vec2', t.params), [Type.i32], Type.vec2h, t.params, cases); }); g.test('u32_to_vec2h'). @@ -1058,14 +257,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'u32_to_vec2_f16' : 'u32_to_vec2_f16_inf_nan' ); - await run( - t, - bitcastBuilder('vec2', t.params), - [TypeU32], - TypeVec(2, TypeF16), - t.params, - cases - ); + await run(t, bitcastBuilder('vec2', t.params), [Type.u32], Type.vec2h, t.params, cases); }); g.test('f32_to_vec2h'). @@ -1080,14 +272,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'f32_to_vec2_f16' : 'f32_inf_nan_to_vec2_f16_inf_nan' ); - await run( - t, - bitcastBuilder('vec2', t.params), - [TypeF32], - TypeVec(2, TypeF16), - t.params, - cases - ); + await run(t, bitcastBuilder('vec2', t.params), [Type.f32], Type.vec2h, t.params, cases); }); // f16: vec2<32-bit scalar numeric> to vec4 @@ -1103,14 +288,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'vec2_i32_to_vec4_f16' : 'vec2_i32_to_vec4_f16_inf_nan' ); - await run( - t, - bitcastBuilder('vec4', t.params), - [TypeVec(2, TypeI32)], - TypeVec(4, TypeF16), - t.params, - cases - ); + await run(t, bitcastBuilder('vec4', t.params), [Type.vec2i], Type.vec4h, t.params, cases); }); g.test('vec2u_to_vec4h'). @@ -1125,14 +303,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'vec2_u32_to_vec4_f16' : 'vec2_u32_to_vec4_f16_inf_nan' ); - await run( - t, - bitcastBuilder('vec4', t.params), - [TypeVec(2, TypeU32)], - TypeVec(4, TypeF16), - t.params, - cases - ); + await run(t, bitcastBuilder('vec4', t.params), [Type.vec2u], Type.vec4h, t.params, cases); }); g.test('vec2f_to_vec4h'). @@ -1149,14 +320,7 @@ fn(async (t) => { 'vec2_f32_to_vec4_f16' : 'vec2_f32_inf_nan_to_vec4_f16_inf_nan' ); - await run( - t, - bitcastBuilder('vec4', t.params), - [TypeVec(2, TypeF32)], - TypeVec(4, TypeF16), - t.params, - cases - ); + await run(t, bitcastBuilder('vec4', t.params), [Type.vec2f], Type.vec4h, t.params, cases); }); // f16: vec2 to 32-bit scalar numeric @@ -1172,7 +336,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'vec2_f16_to_i32' : 'vec2_f16_inf_nan_to_i32' ); - await run(t, bitcastBuilder('i32', t.params), [TypeVec(2, TypeF16)], TypeI32, t.params, cases); + await run(t, bitcastBuilder('i32', t.params), [Type.vec2h], Type.i32, t.params, cases); }); g.test('vec2h_to_u32'). @@ -1187,7 +351,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'vec2_f16_to_u32' : 'vec2_f16_inf_nan_to_u32' ); - await run(t, bitcastBuilder('u32', t.params), [TypeVec(2, TypeF16)], TypeU32, t.params, cases); + await run(t, bitcastBuilder('u32', t.params), [Type.vec2h], Type.u32, t.params, cases); }); g.test('vec2h_to_f32'). @@ -1202,7 +366,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'vec2_f16_to_f32_finite' : 'vec2_f16_inf_nan_to_f32' ); - await run(t, bitcastBuilder('f32', t.params), [TypeVec(2, TypeF16)], TypeF32, t.params, cases); + await run(t, bitcastBuilder('f32', t.params), [Type.vec2h], Type.f32, t.params, cases); }); // f16: vec4 to vec2<32-bit scalar numeric> @@ -1218,14 +382,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'vec4_f16_to_vec2_i32' : 'vec4_f16_inf_nan_to_vec2_i32' ); - await run( - t, - bitcastBuilder('vec2', t.params), - [TypeVec(4, TypeF16)], - TypeVec(2, TypeI32), - t.params, - cases - ); + await run(t, bitcastBuilder('vec2', t.params), [Type.vec4h], Type.vec2i, t.params, cases); }); g.test('vec4h_to_vec2u'). @@ -1240,14 +397,7 @@ fn(async (t) => { // Infinities and NaNs are errors in const-eval. t.params.inputSource === 'const' ? 'vec4_f16_to_vec2_u32' : 'vec4_f16_inf_nan_to_vec2_u32' ); - await run( - t, - bitcastBuilder('vec2', t.params), - [TypeVec(4, TypeF16)], - TypeVec(2, TypeU32), - t.params, - cases - ); + await run(t, bitcastBuilder('vec2', t.params), [Type.vec4h], Type.vec2u, t.params, cases); }); g.test('vec4h_to_vec2f'). @@ -1264,12 +414,230 @@ fn(async (t) => { 'vec4_f16_to_vec2_f32_finite' : 'vec4_f16_inf_nan_to_vec2_f32' ); + await run(t, bitcastBuilder('vec2', t.params), [Type.vec4h], Type.vec2f, t.params, cases); +}); + +// Abstract Float +g.test('af_to_f32'). +specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin'). +desc(`bitcast abstract float to f32 tests`). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = scalarF32Range().map((u) => { + const res = FP['f32'].addFlushedIfNeeded([u]).map((f) => { + return f32(f); + }); + return { + input: abstractFloat(u), + expected: anyOf(...res) + }; + }); + + await run(t, bitcastBuilder('f32', t.params), [Type.abstractFloat], Type.f32, t.params, cases); +}); + +g.test('af_to_i32'). +specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin'). +desc(`bitcast abstract float to i32 tests`). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const values = [ + 0, + 1, + 10, + 256, + u32Bits(0b11111111011111111111111111111111).value, + u32Bits(0b11111111010000000000000000000000).value, + u32Bits(0b11111110110000000000000000000000).value, + u32Bits(0b11111101110000000000000000000000).value, + u32Bits(0b11111011110000000000000000000000).value, + u32Bits(0b11110111110000000000000000000000).value, + u32Bits(0b11101111110000000000000000000000).value, + u32Bits(0b11011111110000000000000000000000).value, + u32Bits(0b10111111110000000000000000000000).value, + u32Bits(0b01111111011111111111111111111111).value, + u32Bits(0b01111111010000000000000000000000).value, + u32Bits(0b01111110110000000000000000000000).value, + u32Bits(0b01111101110000000000000000000000).value, + u32Bits(0b01111011110000000000000000000000).value, + u32Bits(0b01110111110000000000000000000000).value, + u32Bits(0b01101111110000000000000000000000).value, + u32Bits(0b01011111110000000000000000000000).value, + u32Bits(0b00111111110000000000000000000000).value]; + + + const cases = values.map((u) => { + return { + input: abstractFloat(uint32ToFloat32(u)), + expected: i32(u) + }; + }); + + await run(t, bitcastBuilder('i32', t.params), [Type.abstractFloat], Type.i32, t.params, cases); +}); + +g.test('af_to_u32'). +specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin'). +desc(`bitcast abstract float to u32 tests`). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const values = [ + 0, + 1, + 10, + 256, + u32Bits(0b11111111011111111111111111111111).value, + u32Bits(0b11111111010000000000000000000000).value, + u32Bits(0b11111110110000000000000000000000).value, + u32Bits(0b11111101110000000000000000000000).value, + u32Bits(0b11111011110000000000000000000000).value, + u32Bits(0b11110111110000000000000000000000).value, + u32Bits(0b11101111110000000000000000000000).value, + u32Bits(0b11011111110000000000000000000000).value, + u32Bits(0b10111111110000000000000000000000).value, + u32Bits(0b01111111011111111111111111111111).value, + u32Bits(0b01111111010000000000000000000000).value, + u32Bits(0b01111110110000000000000000000000).value, + u32Bits(0b01111101110000000000000000000000).value, + u32Bits(0b01111011110000000000000000000000).value, + u32Bits(0b01110111110000000000000000000000).value, + u32Bits(0b01101111110000000000000000000000).value, + u32Bits(0b01011111110000000000000000000000).value, + u32Bits(0b00111111110000000000000000000000).value]; + + + const cases = values.map((u) => { + return { + input: abstractFloat(uint32ToFloat32(u)), + expected: u32(u) + }; + }); + + await run(t, bitcastBuilder('u32', t.params), [Type.abstractFloat], Type.u32, t.params, cases); +}); + +g.test('af_to_vec2f16'). +specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin'). +desc(`bitcast abstract float to f16 tests`). +beforeAllSubcases((t) => { + t.selectDeviceOrSkipTestCase('shader-f16'); +}). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('af_to_vec2_f16'); + + await run( + t, + bitcastBuilder('vec2', t.params), + [Type.abstractFloat], + Type.vec2h, + t.params, + cases + ); +}); + +g.test('vec2af_to_vec4f16'). +specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin'). +desc(`bitcast abstract float to f16 tests`). +beforeAllSubcases((t) => { + t.selectDeviceOrSkipTestCase('shader-f16'); +}). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('vec2_af_to_vec4_f16'); + await run( t, - bitcastBuilder('vec2', t.params), - [TypeVec(4, TypeF16)], - TypeVec(2, TypeF32), + bitcastBuilder('vec4', t.params), + [Type.vec(2, Type.abstractFloat)], + Type.vec4h, t.params, cases ); +}); + +// Abstract Int +g.test('ai_to_i32'). +specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin'). +desc(`bitcast abstract int to i32 tests`). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]). +combine('alias', [false, true]) +). +fn(async (t) => { + const cases = await d.get('ai_to_i32'); + await run(t, bitcastBuilder('i32', t.params), [Type.abstractInt], Type.i32, t.params, cases); +}); + +g.test('ai_to_u32'). +specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin'). +desc(`bitcast abstract int to u32 tests`). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]). +combine('alias', [false, true]) +). +fn(async (t) => { + const cases = await d.get('ai_to_u32'); + await run(t, bitcastBuilder('u32', t.params), [Type.abstractInt], Type.u32, t.params, cases); +}); + +g.test('ai_to_f32'). +specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin'). +desc(`bitcast abstract int to f32 tests`). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]). +combine('alias', [false, true]) +). +fn(async (t) => { + const cases = await d.get('ai_to_f32'); + await run(t, bitcastBuilder('f32', t.params), [Type.abstractInt], Type.f32, t.params, cases); +}); + +g.test('ai_to_vec2h'). +specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin'). +desc(`bitcast ai to vec2h tests`). +params((u) => u.combine('inputSource', onlyConstInputSource).combine('alias', [false, true])). +beforeAllSubcases((t) => { + t.selectDeviceOrSkipTestCase('shader-f16'); +}). +fn(async (t) => { + const cases = await d.get('ai_to_vec2_f16'); + await run( + t, + bitcastBuilder('vec2', t.params), + [Type.abstractInt], + Type.vec2h, + t.params, + cases + ); +}); + +g.test('vec2ai_to_vec4h'). +specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin'). +desc(`bitcast vec2ai to vec4h tests`). +params((u) => u.combine('inputSource', onlyConstInputSource).combine('alias', [false, true])). +beforeAllSubcases((t) => { + t.selectDeviceOrSkipTestCase('shader-f16'); +}). +fn(async (t) => { + const cases = await d.get('vec2_ai_to_vec4_f16'); + await run(t, bitcastBuilder('vec4', t.params), [Type.vec2ai], Type.vec4h, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/builtin.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/builtin.js index cd3e52298c..1cc248421b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/builtin.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/builtin.js @@ -1,6 +1,7 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { abstractFloatShaderBuilder, basicExpressionBuilder, +**/import { abstractFloatShaderBuilder, abstractIntShaderBuilder, + basicExpressionBuilder, basicExpressionWithPredeclarationBuilder } from '../../expression.js'; @@ -11,10 +12,15 @@ export function builtin(name) { } /* @returns a ShaderBuilder that calls the builtin with the given name that returns AbstractFloats */ -export function abstractBuiltin(name) { +export function abstractFloatBuiltin(name) { return abstractFloatShaderBuilder((values) => `${name}(${values.join(', ')})`); } +/* @returns a ShaderBuilder that calls the builtin with the given name that returns AbstractInts */ +export function abstractIntBuiltin(name) { + return abstractIntShaderBuilder((values) => `${name}(${values.join(', ')})`); +} + /* @returns a ShaderBuilder that calls the builtin with the given name and has given predeclaration */ export function builtinWithPredeclaration(name, predeclaration) { return basicExpressionWithPredeclarationBuilder( diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.cache.js new file mode 100644 index 0000000000..5c101715f1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.cache.js @@ -0,0 +1,26 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +const kSmallMagnitudeTestValues = [0.1, 0.9, 1.0, 1.1, 1.9, -0.1, -0.9, -1.0, -1.1, -1.9]; + +// See https://github.com/gpuweb/cts/issues/2766 for details +const kIssue2766Value = { + f32: 0x8000_0000, + f16: 0x8000, + abstract: 0x8000_0000_0000_0000 +}; + +// Cases: [f32|f16] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + [...kSmallMagnitudeTestValues, kIssue2766Value[trait], ...FP[trait].scalarRange()], + 'unfiltered', + FP[trait].ceilInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('ceil', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.spec.js index 076c7178ef..fab2be8c01 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.spec.js @@ -3,77 +3,40 @@ **/export const description = ` Execution tests for the 'ceil' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn ceil(e: T ) -> T Returns the ceiling of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './ceil.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('ceil', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - [ - // Small positive numbers - 0.1, - 0.9, - 1.0, - 1.1, - 1.9, - // Small negative numbers - -0.1, - -0.9, - -1.0, - -1.1, - -1.9, - 0x80000000, // https://github.com/gpuweb/cts/issues/2766 - ...fullF32Range()], - - 'unfiltered', - FP.f32.ceilInterval - ); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - [ - // Small positive numbers - 0.1, - 0.9, - 1.0, - 1.1, - 1.9, - // Small negative numbers - -0.1, - -0.9, - -1.0, - -1.1, - -1.9, - 0x8000, // https://github.com/gpuweb/cts/issues/2766 - ...fullF16Range()], - - 'unfiltered', - FP.f16.ceilInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('ceil'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -83,7 +46,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('ceil'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('ceil'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -97,5 +60,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('ceil'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('ceil'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.cache.js new file mode 100644 index 0000000000..eee76e0de0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.cache.js @@ -0,0 +1,131 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kValue } from '../../../../../util/constants.js';import { Type } from '../../../../../util/conversion.js';import { FP } from '../../../../../util/floating_point.js'; +import { maxBigInt, minBigInt } from '../../../../../util/math.js'; + +import { makeCaseCache } from '../../case_cache.js'; + +const u32Values = [0, 1, 2, 3, 0x70000000, 0x80000000, kValue.u32.max]; + +const i32Values = [ +kValue.i32.negative.min, +-3, +-2, +-1, +0, +1, +2, +3, +0x70000000, +kValue.i32.positive.max]; + + +const abstractFloatValues = [ +kValue.i64.negative.min, +-3n, +-2n, +-1n, +0n, +1n, +2n, +3n, +0x70000000n, +kValue.i64.positive.max]; + + +/** @returns a set of clamp test cases from an ascending list of concrete integer values */ +function generateConcreteIntegerTestCases( +test_values, +type, +stage) +{ + return test_values.flatMap((low) => + test_values.flatMap((high) => + stage === 'const' && low > high ? + [] : + test_values.map((e) => ({ + input: [type.create(e), type.create(low), type.create(high)], + expected: type.create(Math.min(Math.max(e, low), high)) + })) + ) + ); +} + +/** @returns a set of clamp test cases from an ascending list of abstract integer values */ +function generateAbstractIntegerTestCases(test_values) { + return test_values.flatMap((low) => + test_values.flatMap((high) => + low > high ? + [] : + test_values.map((e) => ({ + input: [ + Type.abstractInt.create(e), + Type.abstractInt.create(low), + Type.abstractInt.create(high)], + + expected: Type.abstractInt.create(minBigInt(maxBigInt(e, low), high)) + })) + ) + ); +} + +function generateFloatTestCases( +test_values, +trait, +stage) +{ + return test_values.flatMap((low) => + test_values.flatMap((high) => + stage === 'const' && low > high ? + [] : + test_values.flatMap((e) => { + const c = FP[trait].makeScalarTripleToIntervalCase( + e, + low, + high, + stage === 'const' ? 'finite' : 'unfiltered', + ...FP[trait].clampIntervals + ); + return c === undefined ? [] : [c]; + }) + ) + ); +} + +// Cases: [f32|f16|abstract]_[non_]const +// abstract_non_const is empty and unused +const fp_cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return generateFloatTestCases( + FP[trait].sparseScalarRange(), + trait, + nonConst ? 'non_const' : 'const' + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('clamp', { + u32_non_const: () => { + return generateConcreteIntegerTestCases(u32Values, Type.u32, 'non_const'); + }, + u32_const: () => { + return generateConcreteIntegerTestCases(u32Values, Type.u32, 'const'); + }, + i32_non_const: () => { + return generateConcreteIntegerTestCases(i32Values, Type.i32, 'non_const'); + }, + i32_const: () => { + return generateConcreteIntegerTestCases(i32Values, Type.i32, 'const'); + }, + abstract_int: () => { + return generateAbstractIntegerTestCases(abstractFloatValues); + }, + ...fp_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.spec.js index 6d4d05ba36..1cf7035691 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.spec.js @@ -3,129 +3,45 @@ **/export const description = ` Execution tests for the 'clamp' builtin function -S is AbstractInt, i32, or u32 +S is abstract-int, i32, or u32 T is S or vecN @const fn clamp(e: T , low: T, high: T) -> T Returns min(max(e,low),high). Component-wise when T is a vector. -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const clamp(e: T , low: T , high: T) -> T Returns either min(max(e,low),high), or the median of the three values e, low, high. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { kValue } from '../../../../../util/constants.js'; -import { - - TypeF32, - TypeF16, - TypeI32, - TypeU32, - TypeAbstractFloat } from -'../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { sparseF32Range, sparseF16Range, sparseF64Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, abstractIntBuiltin, builtin } from './builtin.js'; +import { d } from './clamp.cache.js'; export const g = makeTestGroup(GPUTest); -const u32Values = [0, 1, 2, 3, 0x70000000, 0x80000000, kValue.u32.max]; - -const i32Values = [ -kValue.i32.negative.min, --3, --2, --1, -0, -1, -2, -3, -0x70000000, -kValue.i32.positive.max]; - - -export const d = makeCaseCache('clamp', { - u32_non_const: () => { - return generateIntegerTestCases(u32Values, TypeU32, 'non-const'); - }, - u32_const: () => { - return generateIntegerTestCases(u32Values, TypeU32, 'const'); - }, - i32_non_const: () => { - return generateIntegerTestCases(i32Values, TypeI32, 'non-const'); - }, - i32_const: () => { - return generateIntegerTestCases(i32Values, TypeI32, 'const'); - }, - f32_const: () => { - return generateFloatTestCases(sparseF32Range(), 'f32', 'const'); - }, - f32_non_const: () => { - return generateFloatTestCases(sparseF32Range(), 'f32', 'non-const'); - }, - f16_const: () => { - return generateFloatTestCases(sparseF16Range(), 'f16', 'const'); - }, - f16_non_const: () => { - return generateFloatTestCases(sparseF16Range(), 'f16', 'non-const'); - }, - abstract: () => { - return generateFloatTestCases(sparseF64Range(), 'abstract', 'const'); - } -}); - -/** @returns a set of clamp test cases from an ascending list of integer values */ -function generateIntegerTestCases( -test_values, -type, -stage) -{ - return test_values.flatMap((low) => - test_values.flatMap((high) => - stage === 'const' && low > high ? - [] : - test_values.map((e) => ({ - input: [type.create(e), type.create(low), type.create(high)], - expected: type.create(Math.min(Math.max(e, low), high)) - })) - ) - ); -} - -function generateFloatTestCases( -test_values, -trait, -stage) -{ - return test_values.flatMap((low) => - test_values.flatMap((high) => - stage === 'const' && low > high ? - [] : - test_values.flatMap((e) => { - const c = FP[trait].makeScalarTripleToIntervalCase( - e, - low, - high, - stage === 'const' ? 'finite' : 'unfiltered', - ...FP[trait].clampIntervals - ); - return c === undefined ? [] : [c]; - }) - ) - ); -} - g.test('abstract_int'). specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions'). desc(`abstract int tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_int'); + await run( + t, + abstractIntBuiltin('clamp'), + [Type.abstractInt, Type.abstractInt, Type.abstractInt], + Type.abstractInt, + t.params, + cases + ); +}); g.test('u32'). specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions'). @@ -135,7 +51,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const'); - await run(t, builtin('clamp'), [TypeU32, TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, builtin('clamp'), [Type.u32, Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('i32'). @@ -146,7 +62,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'i32_const' : 'i32_non_const'); - await run(t, builtin('clamp'), [TypeI32, TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, builtin('clamp'), [Type.i32, Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('abstract_float'). @@ -158,12 +74,12 @@ combine('inputSource', onlyConstInputSource). combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { - const cases = await d.get('abstract'); + const cases = await d.get('abstract_const'); await run( t, - abstractBuiltin('clamp'), - [TypeAbstractFloat, TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBuiltin('clamp'), + [Type.abstractFloat, Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -177,7 +93,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('clamp'), [TypeF32, TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, builtin('clamp'), [Type.f32, Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -191,5 +107,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('clamp'), [TypeF16, TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, builtin('clamp'), [Type.f16, Type.f16, Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.cache.js new file mode 100644 index 0000000000..453110b9f7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.cache.js @@ -0,0 +1,23 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { linearRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + [ + // Well-defined accuracy range + ...linearRange(-Math.PI, Math.PI, 100), + ...FP[trait].scalarRange()], + + trait === 'abstract' ? 'finite' : 'unfiltered', + // cos has an absolute accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].cosInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('cos', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.spec.js index 46b5eade73..ae31f07610 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.spec.js @@ -3,54 +3,39 @@ **/export const description = ` Execution tests for the 'cos' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn cos(e: T ) -> T Returns the cosine of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range, linearRange } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './cos.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('cos', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - [ - // Well-defined accuracy range - ...linearRange(-Math.PI, Math.PI, 1000), - ...fullF32Range()], - - 'unfiltered', - FP.f32.cosInterval - ); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - [ - // Well-defined accuracy range - ...linearRange(-Math.PI, Math.PI, 1000), - ...fullF16Range()], - - 'unfiltered', - FP.f16.cosInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('cos'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -66,7 +51,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('cos'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('cos'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -80,5 +65,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('cos'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('cos'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.cache.js new file mode 100644 index 0000000000..264a58ca7f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.cache.js @@ -0,0 +1,23 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + nonConst ? 'unfiltered' : 'finite', + // cosh has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].coshInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('cosh', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.spec.js index 4304a39268..f51fef5dac 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.spec.js @@ -3,44 +3,39 @@ **/export const description = ` Execution tests for the 'cosh' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn cosh(e: T ) -> T Returns the hyperbolic cosine of e. Component-wise when T is a vector `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './cosh.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('cosh', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'finite', FP.f32.coshInterval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'unfiltered', FP.f32.coshInterval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'finite', FP.f16.coshInterval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'unfiltered', FP.f16.coshInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('cosh'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -50,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('cosh'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('cosh'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -64,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('cosh'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('cosh'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countLeadingZeros.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countLeadingZeros.spec.js index 8622bef96e..c394cc60a4 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countLeadingZeros.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countLeadingZeros.spec.js @@ -12,7 +12,7 @@ Component-wise when T is a vector. Also known as "clz" in some languages. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeU32, u32Bits, u32, TypeI32, i32Bits, i32 } from '../../../../../util/conversion.js'; +import { Type, u32Bits, u32, i32Bits, i32 } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -27,7 +27,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cfg = t.params; - await run(t, builtin('countLeadingZeros'), [TypeU32], TypeU32, cfg, [ + await run(t, builtin('countLeadingZeros'), [Type.u32], Type.u32, cfg, [ // Zero { input: u32Bits(0b00000000000000000000000000000000), expected: u32(32) }, @@ -142,7 +142,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cfg = t.params; - await run(t, builtin('countLeadingZeros'), [TypeI32], TypeI32, cfg, [ + await run(t, builtin('countLeadingZeros'), [Type.i32], Type.i32, cfg, [ // Zero { input: i32Bits(0b00000000000000000000000000000000), expected: i32(32) }, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countOneBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countOneBits.spec.js index 500b02ba61..7de73dc811 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countOneBits.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countOneBits.spec.js @@ -11,7 +11,7 @@ Also known as "population count". Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeU32, u32Bits, u32, TypeI32, i32Bits, i32 } from '../../../../../util/conversion.js'; +import { Type, u32Bits, u32, i32Bits, i32 } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -26,7 +26,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cfg = t.params; - await run(t, builtin('countOneBits'), [TypeU32], TypeU32, cfg, [ + await run(t, builtin('countOneBits'), [Type.u32], Type.u32, cfg, [ // Zero { input: u32Bits(0b00000000000000000000000000000000), expected: u32(0) }, @@ -141,7 +141,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cfg = t.params; - await run(t, builtin('countOneBits'), [TypeI32], TypeI32, cfg, [ + await run(t, builtin('countOneBits'), [Type.i32], Type.i32, cfg, [ // Zero { input: i32Bits(0b00000000000000000000000000000000), expected: i32(0) }, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countTrailingZeros.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countTrailingZeros.spec.js index ca3f78ee05..f7b3b3a9dd 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countTrailingZeros.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countTrailingZeros.spec.js @@ -12,7 +12,7 @@ Component-wise when T is a vector. Also known as "ctz" in some languages. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { i32, i32Bits, TypeI32, u32, TypeU32, u32Bits } from '../../../../../util/conversion.js'; +import { i32, i32Bits, Type, u32, u32Bits } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -27,7 +27,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cfg = t.params; - await run(t, builtin('countTrailingZeros'), [TypeU32], TypeU32, cfg, [ + await run(t, builtin('countTrailingZeros'), [Type.u32], Type.u32, cfg, [ // Zero { input: u32Bits(0b00000000000000000000000000000000), expected: u32(32) }, @@ -142,7 +142,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cfg = t.params; - await run(t, builtin('countTrailingZeros'), [TypeI32], TypeI32, cfg, [ + await run(t, builtin('countTrailingZeros'), [Type.i32], Type.i32, cfg, [ // Zero { input: i32Bits(0b00000000000000000000000000000000), expected: i32(32) }, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.cache.js new file mode 100644 index 0000000000..e5a68365ae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.cache.js @@ -0,0 +1,25 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_[non_]const +// abstract_non_const is empty and not used +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateVectorPairToVectorCases( + FP[trait].vectorRange(3), + FP[trait].vectorRange(3), + nonConst ? 'unfiltered' : 'finite', + // cross has an inherited accuracy, so abstract is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].crossInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('cross', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.spec.js index 7d1c862bf1..c5a54fbe3e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.spec.js @@ -3,75 +3,30 @@ **/export const description = ` Execution tests for the 'cross' builtin function -T is AbstractFloat, f32, or f16 +T is abstract-float, f32, or f16 @const fn cross(e1: vec3 ,e2: vec3) -> vec3 Returns the cross product of e1 and e2. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeF16, TypeF32, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { sparseVectorF64Range, vectorF16Range, vectorF32Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './cross.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('cross', { - f32_const: () => { - return FP.f32.generateVectorPairToVectorCases( - vectorF32Range(3), - vectorF32Range(3), - 'finite', - FP.f32.crossInterval - ); - }, - f32_non_const: () => { - return FP.f32.generateVectorPairToVectorCases( - vectorF32Range(3), - vectorF32Range(3), - 'unfiltered', - FP.f32.crossInterval - ); - }, - f16_const: () => { - return FP.f16.generateVectorPairToVectorCases( - vectorF16Range(3), - vectorF16Range(3), - 'finite', - FP.f16.crossInterval - ); - }, - f16_non_const: () => { - return FP.f16.generateVectorPairToVectorCases( - vectorF16Range(3), - vectorF16Range(3), - 'unfiltered', - FP.f16.crossInterval - ); - }, - abstract: () => { - return FP.abstract.generateVectorPairToVectorCases( - sparseVectorF64Range(3), - sparseVectorF64Range(3), - 'finite', - FP.abstract.crossInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => u.combine('inputSource', onlyConstInputSource)). fn(async (t) => { - const cases = await d.get('abstract'); + const cases = await d.get('abstract_const'); await run( t, - abstractBuiltin('cross'), - [TypeVec(3, TypeAbstractFloat), TypeVec(3, TypeAbstractFloat)], - TypeVec(3, TypeAbstractFloat), + abstractFloatBuiltin('cross'), + [Type.vec(3, Type.abstractFloat), Type.vec(3, Type.abstractFloat)], + Type.vec(3, Type.abstractFloat), t.params, cases ); @@ -83,14 +38,7 @@ desc(`f32 tests`). params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run( - t, - builtin('cross'), - [TypeVec(3, TypeF32), TypeVec(3, TypeF32)], - TypeVec(3, TypeF32), - t.params, - cases - ); + await run(t, builtin('cross'), [Type.vec3f, Type.vec3f], Type.vec3f, t.params, cases); }); g.test('f16'). @@ -102,12 +50,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run( - t, - builtin('cross'), - [TypeVec(3, TypeF16), TypeVec(3, TypeF16)], - TypeVec(3, TypeF16), - t.params, - cases - ); + await run(t, builtin('cross'), [Type.vec3h, Type.vec3h], Type.vec3h, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.cache.js new file mode 100644 index 0000000000..e4e012f202 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.cache.js @@ -0,0 +1,24 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_[non_]const +// abstract_non_const is empty and not used +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + nonConst ? 'unfiltered' : 'finite', + // degrees has an inherited accuracy, so abstract is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].degreesInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('degrees', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.spec.js index cf3a7e34bc..a79889a43b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.spec.js @@ -3,52 +3,20 @@ **/export const description = ` Execution tests for the 'degrees' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn degrees(e1: T ) -> T Converts radians to degrees, approximating e1 × 180 ÷ π. Component-wise when T is a vector `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeF16, TypeF32 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF16Range, fullF32Range, fullF64Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './degrees.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('degrees', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'finite', FP.f32.degreesInterval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases( - fullF32Range(), - 'unfiltered', - FP.f32.degreesInterval - ); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'finite', FP.f16.degreesInterval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases( - fullF16Range(), - 'unfiltered', - FP.f16.degreesInterval - ); - }, - abstract: () => { - return FP.abstract.generateScalarToIntervalCases( - fullF64Range(), - 'finite', - FP.abstract.degreesInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). @@ -58,12 +26,12 @@ combine('inputSource', onlyConstInputSource). combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { - const cases = await d.get('abstract'); + const cases = await d.get('abstract_const'); await run( t, - abstractBuiltin('degrees'), - [TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBuiltin('degrees'), + [Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -77,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('degrees'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('degrees'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -91,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('degrees'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('degrees'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/derivatives.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/derivatives.cache.js new file mode 100644 index 0000000000..98a271f54a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/derivatives.cache.js @@ -0,0 +1,14 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { sparseScalarF32Range } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +export const d = makeCaseCache('derivatives', { + scalar: () => { + return FP.f32.generateScalarPairToIntervalCases( + sparseScalarF32Range(), + sparseScalarF32Range(), + 'unfiltered', + FP.f32.subtractionInterval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/derivatives.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/derivatives.js new file mode 100644 index 0000000000..edf2ae3fe7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/derivatives.js @@ -0,0 +1,215 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { Type } from '../../../../../util/conversion.js'; +import { toComparator } from '../../expectation.js'; +import { packScalarsToVector } from '../../expression.js'; + +/** + * Run a test for a derivative builtin function. + * @param t the GPUTest + * @param cases list of test cases to run + * @param builtin the builtin function to test + * @param non_uniform_discard if true, one of each pair of invocations will discard + * @param vectorize if defined, the vector width to use (2, 3, or 4) + */ +export function runDerivativeTest( +t, +cases, +builtin, +non_uniform_discard, +vectorize) +{ + // If the 'vectorize' config option was provided, pack the cases into vectors. + let type = Type.f32; + if (vectorize !== undefined) { + const packed = packScalarsToVector([type, type], type, cases, vectorize); + cases = packed.cases; + type = packed.resultType; + } + + //////////////////////////////////////////////////////////////// + // The two input values for a given case are distributed to two different invocations in a quad. + // We will populate a storage buffer with these input values laid out sequentially: + // [ case_0_input_1, case_0_input_0, case_1_input_1, case_1_input_0, ...] + // + // The render pipeline will be launched several times over a viewport size of (2, 2). Each draw + // call will execute a single quad (four fragment invocation), which will exercise two test cases. + // Each of these draw calls will use a different instance index, which is forwarded to the + // fragment shader. Each invocation will determine its index into the storage buffer using its + // fragment position and the instance index for that draw call. + // + // Consider two draw calls that test 4 cases (c_0, c_1, c_2, c_3). + // + // For derivatives along the 'x' direction, the mapping from fragment position to case input is: + // Quad 0: | c_0_i_1 | c_0_i_0 | Quad 1: | c_2_i_1 | c_2_i_0 | + // | c_1_i_1 | c_1_i_0 | | c_3_i_1 | c_3_i_0 | + // + // For derivatives along the 'y' direction, the mapping from fragment position to case input is: + // Quad 0: | c_0_i_1 | c_1_i_1 | Quad 1: | c_2_i_1 | c_3_i_1 | + // | c_0_i_0 | c_1_i_0 | | c_2_i_0 | c_3_i_0 | + // + //////////////////////////////////////////////////////////////// + + // Determine the direction of the derivative ('x' or 'y') from the builtin name. + const dir = builtin[3]; + + // Determine the WGSL type to use in the shader, and the stride in bytes between values. + let valueStride = 4; + let wgslType = 'f32'; + if (vectorize) { + wgslType = `vec${vectorize}f`; + valueStride = vectorize * 4; + if (vectorize === 3) { + valueStride = 16; + } + } + + // Define a vertex shader that draws a triangle over the full viewport, and a fragment shader that + // calls the derivative builtin with a value loaded from that fragment's index into the storage + // buffer (determined using the quad index and fragment position, as described above). + const code = ` +struct CaseInfo { + @builtin(position) position: vec4f, + @location(0) @interpolate(flat) quad_idx: u32, +} + +@vertex +fn vert(@builtin(vertex_index) vertex_idx: u32, + @builtin(instance_index) instance_idx: u32) -> CaseInfo { + const kVertices = array( + vec2f(-2, -2), + vec2f( 2, -2), + vec2f( 0, 2), + ); + return CaseInfo(vec4(kVertices[vertex_idx], 0, 1), instance_idx); +} + +@group(0) @binding(0) var inputs : array<${wgslType}>; +@group(0) @binding(1) var outputs : array<${wgslType}>; + +@fragment +fn frag(info : CaseInfo) { + let case_idx = u32(info.position.${dir === 'x' ? 'y' : 'x'}); + let inv_idx = u32(info.position.${dir}); + let index = info.quad_idx*4 + case_idx*2 + inv_idx; + let input = inputs[index]; + ${non_uniform_discard ? 'if inv_idx == 0 { discard; }' : ''} + outputs[index] = ${builtin}(input); +} +`; + + // Create the render pipeline. + const module = t.device.createShaderModule({ code }); + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { module }, + fragment: { module, targets: [{ format: 'rgba8unorm', writeMask: 0 }] } + }); + + // Create storage buffers to hold the inputs and outputs. + const bufferSize = cases.length * 2 * valueStride; + const inputBuffer = t.device.createBuffer({ + size: bufferSize, + usage: GPUBufferUsage.STORAGE, + mappedAtCreation: true + }); + const outputBuffer = t.device.createBuffer({ + size: bufferSize, + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC + }); + + // Populate the input storage buffer with case input values. + const valuesData = new Uint8Array(inputBuffer.getMappedRange()); + for (let i = 0; i < cases.length; i++) { + const inputs = cases[i].input; + inputs[0].copyTo(valuesData, (i * 2 + 1) * valueStride); + inputs[1].copyTo(valuesData, i * 2 * valueStride); + } + inputBuffer.unmap(); + + // Create a bind group for the storage buffers. + const group = t.device.createBindGroup({ + entries: [ + { binding: 0, resource: { buffer: inputBuffer } }, + { binding: 1, resource: { buffer: outputBuffer } }], + + layout: pipeline.getBindGroupLayout(0) + }); + + // Create a texture to use as a color attachment. + // We only need this for launching the desired number of fragment invocations. + const colorAttachment = t.device.createTexture({ + size: { width: 2, height: 2 }, + format: 'rgba8unorm', + usage: GPUTextureUsage.RENDER_ATTACHMENT + }); + + // Submit the render pass to the device. + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ + colorAttachments: [ + { + view: colorAttachment.createView(), + loadOp: 'clear', + storeOp: 'discard' + }] + + }); + pass.setPipeline(pipeline); + pass.setBindGroup(0, group); + for (let quad = 0; quad < cases.length / 2; quad++) { + pass.draw(3, 1, undefined, quad); + } + pass.end(); + t.queue.submit([encoder.finish()]); + + // Check the outputs match the expected results. + t.expectGPUBufferValuesPassCheck( + outputBuffer, + (outputData) => { + for (let i = 0; i < cases.length; i++) { + const c = cases[i]; + + // Both invocations involved in the derivative should get the same result. + for (let d = 0; d < 2; d++) { + if (non_uniform_discard && d === 0) { + continue; + } + + const index = (i * 2 + d) * valueStride; + const result = type.read(outputData, index); + const cmp = toComparator(c.expected).compare(result); + if (!cmp.matched) { + // If this is a coarse derivative, the implementation is also allowed to calculate only + // one of the two derivatives and return that result to all of the invocations. + if (!builtin.endsWith('Fine')) { + const c0 = cases[i % 2 === 0 ? i + 1 : i - 1]; + const cmp0 = toComparator(c0.expected).compare(result); + if (!cmp0.matched) { + return new Error(` + 1st pair: (${c.input.join(', ')}) + expected: ${cmp.expected} + + 2nd pair: (${c0.input.join(', ')}) + expected: ${cmp0.expected} + + returned: ${result}`); + } + } else { + return new Error(` + inputs: (${c.input.join(', ')}) + expected: ${cmp.expected} + + returned: ${result}`); + } + } + } + } + return undefined; + }, + { + type: Uint8Array, + typedLength: bufferSize + } + ); +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.cache.js new file mode 100644 index 0000000000..cc6ca5bd00 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.cache.js @@ -0,0 +1,99 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Accuracy for determinant is only defined for e, where e is an integer and +// |e| < quadroot(2**21) [~38], +// due to computational complexity of calculating the general solution for 4x4, +// so custom matrices are used. +// +// Note: For 2x2 and 3x3 the limits are squareroot and cuberoot instead of +// quadroot, but using the tighter 4x4 limits for all cases for simplicity. +const kDeterminantValues = [-38, -10, -5, -1, 0, 1, 5, 10, 38]; + +const kDeterminantMatrixValues = { + 2: kDeterminantValues.map((f, idx) => [ + [idx % 4 === 0 ? f : idx, idx % 4 === 1 ? f : -idx], + [idx % 4 === 2 ? f : -idx, idx % 4 === 3 ? f : idx]] + ), + 3: kDeterminantValues.map((f, idx) => [ + [idx % 9 === 0 ? f : idx, idx % 9 === 1 ? f : -idx, idx % 9 === 2 ? f : idx], + [idx % 9 === 3 ? f : -idx, idx % 9 === 4 ? f : idx, idx % 9 === 5 ? f : -idx], + [idx % 9 === 6 ? f : idx, idx % 9 === 7 ? f : -idx, idx % 9 === 8 ? f : idx]] + ), + 4: kDeterminantValues.map((f, idx) => [ + [ + idx % 16 === 0 ? f : idx, + idx % 16 === 1 ? f : -idx, + idx % 16 === 2 ? f : idx, + idx % 16 === 3 ? f : -idx], + + [ + idx % 16 === 4 ? f : -idx, + idx % 16 === 5 ? f : idx, + idx % 16 === 6 ? f : -idx, + idx % 16 === 7 ? f : idx], + + [ + idx % 16 === 8 ? f : idx, + idx % 16 === 9 ? f : -idx, + idx % 16 === 10 ? f : idx, + idx % 16 === 11 ? f : -idx], + + [ + idx % 16 === 12 ? f : -idx, + idx % 16 === 13 ? f : idx, + idx % 16 === 14 ? f : -idx, + idx % 16 === 15 ? f : idx]] + + ) +}; + +// Cases: f32_matDxD_[non_]const +const f32_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`f32_mat${dim}x${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateMatrixToScalarCases( + kDeterminantMatrixValues[dim], + nonConst ? 'unfiltered' : 'finite', + FP.f32.determinantInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: f16_matDxD_[non_]const +const f16_cases = [2, 3, 4]. +flatMap((dim) => +[true, false].map((nonConst) => ({ + [`f16_mat${dim}x${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f16.generateMatrixToScalarCases( + kDeterminantMatrixValues[dim], + nonConst ? 'unfiltered' : 'finite', + FP.f16.determinantInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: abstract_matDxD +const abstract_cases = [2, 3, 4]. +map((dim) => ({ + [`abstract_mat${dim}x${dim}`]: () => { + return FP.abstract.generateMatrixToScalarCases( + kDeterminantMatrixValues[dim], + 'finite', + // determinant has an inherited accuracy, so abstract is only expected to be as accurate as f32 + FP.f32.determinantInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('determinant', { + ...f32_cases, + ...f16_cases, + ...abstract_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.spec.js index 730c5b0ca2..92d092c70b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.spec.js @@ -3,107 +3,35 @@ **/export const description = ` Execution tests for the 'determinant' builtin function -T is AbstractFloat, f32, or f16 +T is abstract-float, f32, or f16 @const determinant(e: matCxC ) -> T Returns the determinant of e. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16, TypeMat } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './determinant.cache.js'; export const g = makeTestGroup(GPUTest); -// Accuracy for determinant is only defined for e, where e is an integer and -// |e| < quadroot(2**21) [~38], -// due to computational complexity of calculating the general solution for 4x4, -// so custom matrices are used. -// -// Note: For 2x2 and 3x3 the limits are squareroot and cuberoot instead of -// quadroot, but using the tighter 4x4 limits for all cases for simplicity. -const kDeterminantValues = [-38, -10, -5, -1, 0, 1, 5, 10, 38]; - -const kDeterminantMatrixValues = { - 2: kDeterminantValues.map((f, idx) => [ - [idx % 4 === 0 ? f : idx, idx % 4 === 1 ? f : -idx], - [idx % 4 === 2 ? f : -idx, idx % 4 === 3 ? f : idx]] - ), - 3: kDeterminantValues.map((f, idx) => [ - [idx % 9 === 0 ? f : idx, idx % 9 === 1 ? f : -idx, idx % 9 === 2 ? f : idx], - [idx % 9 === 3 ? f : -idx, idx % 9 === 4 ? f : idx, idx % 9 === 5 ? f : -idx], - [idx % 9 === 6 ? f : idx, idx % 9 === 7 ? f : -idx, idx % 9 === 8 ? f : idx]] - ), - 4: kDeterminantValues.map((f, idx) => [ - [ - idx % 16 === 0 ? f : idx, - idx % 16 === 1 ? f : -idx, - idx % 16 === 2 ? f : idx, - idx % 16 === 3 ? f : -idx], - - [ - idx % 16 === 4 ? f : -idx, - idx % 16 === 5 ? f : idx, - idx % 16 === 6 ? f : -idx, - idx % 16 === 7 ? f : idx], - - [ - idx % 16 === 8 ? f : idx, - idx % 16 === 9 ? f : -idx, - idx % 16 === 10 ? f : idx, - idx % 16 === 11 ? f : -idx], - - [ - idx % 16 === 12 ? f : -idx, - idx % 16 === 13 ? f : idx, - idx % 16 === 14 ? f : -idx, - idx % 16 === 15 ? f : idx]] - - ) -}; - -// Cases: f32_matDxD_[non_]const -const f32_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`f32_mat${dim}x${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateMatrixToScalarCases( - kDeterminantMatrixValues[dim], - nonConst ? 'unfiltered' : 'finite', - FP.f32.determinantInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: f16_matDxD_[non_]const -const f16_cases = [2, 3, 4]. -flatMap((dim) => -[true, false].map((nonConst) => ({ - [`f16_mat${dim}x${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateMatrixToScalarCases( - kDeterminantMatrixValues[dim], - nonConst ? 'unfiltered' : 'finite', - FP.f16.determinantInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('determinant', { - ...f32_cases, - ...f16_cases -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions'). desc(`abstract float tests`). -params((u) => u.combine('inputSource', allInputSources).combine('dimension', [2, 3, 4])). -unimplemented(); +params((u) => u.combine('inputSource', onlyConstInputSource).combine('dim', [2, 3, 4])). +fn(async (t) => { + const dim = t.params.dim; + const cases = await d.get(`abstract_mat${dim}x${dim}`); + await run( + t, + abstractFloatBuiltin('determinant'), + [Type.mat(dim, dim, Type.abstractFloat)], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions'). @@ -116,7 +44,7 @@ fn(async (t) => { `f32_mat${dim}x${dim}_const` : `f32_mat${dim}x${dim}_non_const` ); - await run(t, builtin('determinant'), [TypeMat(dim, dim, TypeF32)], TypeF32, t.params, cases); + await run(t, builtin('determinant'), [Type.mat(dim, dim, Type.f32)], Type.f32, t.params, cases); }); g.test('f16'). @@ -133,5 +61,5 @@ fn(async (t) => { `f16_mat${dim}x${dim}_const` : `f16_mat${dim}x${dim}_non_const` ); - await run(t, builtin('determinant'), [TypeMat(dim, dim, TypeF16)], TypeF16, t.params, cases); + await run(t, builtin('determinant'), [Type.mat(dim, dim, Type.f16)], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.cache.js new file mode 100644 index 0000000000..3e0199304d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.cache.js @@ -0,0 +1,49 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_[non_]const +const scalar_cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarPairToIntervalCases( + FP[trait].scalarRange(), + FP[trait].scalarRange(), + nonConst ? 'unfiltered' : 'finite', + // distance has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].distanceInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: [f32|f16|abstract]_vecN_[non_]const +const vec_cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[2, 3, 4].flatMap((dim) => +[true, false].map((nonConst) => ({ + [`${trait}_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateVectorPairToIntervalCases( + FP[trait].sparseVectorRange(dim), + FP[trait].sparseVectorRange(dim), + nonConst ? 'unfiltered' : 'finite', + // distance has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].distanceInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('distance', { + ...scalar_cases, + ...vec_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.spec.js index bf33822288..7a45853faa 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.spec.js @@ -3,104 +3,84 @@ **/export const description = ` Execution tests for the 'distance' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn distance(e1: T ,e2: T ) -> f32 Returns the distance between e1 and e2 (e.g. length(e1-e2)). `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { - fullF32Range, - fullF16Range, - sparseVectorF32Range, - sparseVectorF16Range } from -'../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; - -import { builtin } from './builtin.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -export const g = makeTestGroup(GPUTest); +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './distance.cache.js'; -// Cases: f32_vecN_[non_]const -const f32_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f32_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorPairToIntervalCases( - sparseVectorF32Range(n), - sparseVectorF32Range(n), - nonConst ? 'unfiltered' : 'finite', - FP.f32.distanceInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: f16_vecN_[non_]const -const f16_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f16_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorPairToIntervalCases( - sparseVectorF16Range(n), - sparseVectorF16Range(n), - nonConst ? 'unfiltered' : 'finite', - FP.f16.distanceInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('distance', { - f32_const: () => { - return FP.f32.generateScalarPairToIntervalCases( - fullF32Range(), - fullF32Range(), - 'finite', - FP.f32.distanceInterval - ); - }, - f32_non_const: () => { - return FP.f32.generateScalarPairToIntervalCases( - fullF32Range(), - fullF32Range(), - 'unfiltered', - FP.f32.distanceInterval - ); - }, - ...f32_vec_cases, - f16_const: () => { - return FP.f16.generateScalarPairToIntervalCases( - fullF16Range(), - fullF16Range(), - 'finite', - FP.f16.distanceInterval - ); - }, - f16_non_const: () => { - return FP.f16.generateScalarPairToIntervalCases( - fullF16Range(), - fullF16Range(), - 'unfiltered', - FP.f16.distanceInterval - ); - }, - ...f16_vec_cases -}); +export const g = makeTestGroup(GPUTest); g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). -params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) -). -unimplemented(); +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('distance'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); + +g.test('abstract_float_vec2'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec2s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec2_const'); + await run( + t, + abstractFloatBuiltin('distance'), + [Type.vec2af, Type.vec2af], + Type.abstractFloat, + t.params, + cases + ); +}); + +g.test('abstract_float_vec3'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec3s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec3_const'); + await run( + t, + abstractFloatBuiltin('distance'), + [Type.vec3af, Type.vec3af], + Type.abstractFloat, + t.params, + cases + ); +}); + +g.test('abstract_float_vec4'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec4s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec4_const'); + await run( + t, + abstractFloatBuiltin('distance'), + [Type.vec4af, Type.vec4af], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). @@ -108,7 +88,7 @@ desc(`f32 tests`). params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('distance'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, builtin('distance'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('f32_vec2'). @@ -119,14 +99,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const' ); - await run( - t, - builtin('distance'), - [TypeVec(2, TypeF32), TypeVec(2, TypeF32)], - TypeF32, - t.params, - cases - ); + await run(t, builtin('distance'), [Type.vec2f, Type.vec2f], Type.f32, t.params, cases); }); g.test('f32_vec3'). @@ -137,14 +110,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const' ); - await run( - t, - builtin('distance'), - [TypeVec(3, TypeF32), TypeVec(3, TypeF32)], - TypeF32, - t.params, - cases - ); + await run(t, builtin('distance'), [Type.vec3f, Type.vec3f], Type.f32, t.params, cases); }); g.test('f32_vec4'). @@ -155,14 +121,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const' ); - await run( - t, - builtin('distance'), - [TypeVec(4, TypeF32), TypeVec(4, TypeF32)], - TypeF32, - t.params, - cases - ); + await run(t, builtin('distance'), [Type.vec4f, Type.vec4f], Type.f32, t.params, cases); }); g.test('f16'). @@ -174,7 +133,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('distance'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, builtin('distance'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('f16_vec2'). @@ -188,14 +147,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec2_const' : 'f16_vec2_non_const' ); - await run( - t, - builtin('distance'), - [TypeVec(2, TypeF16), TypeVec(2, TypeF16)], - TypeF16, - t.params, - cases - ); + await run(t, builtin('distance'), [Type.vec2h, Type.vec2h], Type.f16, t.params, cases); }); g.test('f16_vec3'). @@ -209,14 +161,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec3_const' : 'f16_vec3_non_const' ); - await run( - t, - builtin('distance'), - [TypeVec(3, TypeF16), TypeVec(3, TypeF16)], - TypeF16, - t.params, - cases - ); + await run(t, builtin('distance'), [Type.vec3h, Type.vec3h], Type.f16, t.params, cases); }); g.test('f16_vec4'). @@ -230,12 +175,5 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec4_const' : 'f16_vec4_non_const' ); - await run( - t, - builtin('distance'), - [TypeVec(4, TypeF16), TypeVec(4, TypeF16)], - TypeF16, - t.params, - cases - ); + await run(t, builtin('distance'), [Type.vec4h, Type.vec4h], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.cache.js new file mode 100644 index 0000000000..4bdf75bc31 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.cache.js @@ -0,0 +1,118 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert } from '../../../../../../common/util/util.js';import { kValue } from '../../../../../util/constants.js'; +import { FP } from '../../../../../util/floating_point.js'; +import { + calculatePermutations, + sparseVectorI32Range, + sparseVectorI64Range, + sparseVectorU32Range, + vectorI32Range, + vectorI64Range, + vectorU32Range } from +'../../../../../util/math.js'; +import { + generateVectorVectorToI32Cases, + generateVectorVectorToI64Cases, + generateVectorVectorToU32Cases } from +'../../case.js'; +import { makeCaseCache } from '../../case_cache.js'; + +function ai_dot(x, y) { + assert(x.length === y.length, 'Cannot calculate dot for vectors of different lengths'); + const multiplications = x.map((_, idx) => x[idx] * y[idx]); + if (multiplications.some(kValue.i64.isOOB)) return undefined; + + const result = multiplications.reduce((prev, curr) => prev + curr); + if (kValue.i64.isOOB(result)) return undefined; + + // The spec does not state the ordering of summation, so all the + // permutations are calculated and the intermediate results checked for + // going OOB. vec2 does not need permutations, since a + b === b + a. + // All the end results should be the same regardless of the order if the + // intermediate additions stay inbounds. + if (x.length !== 2) { + let wentOOB = false; + const permutations = calculatePermutations(multiplications); + permutations.forEach((p) => { + if (!wentOOB) { + p.reduce((prev, curr) => { + const next = prev + curr; + if (kValue.i64.isOOB(next)) { + wentOOB = true; + } + return next; + }); + } + }); + + if (wentOOB) return undefined; + } + + return !kValue.i64.isOOB(result) ? result : undefined; +} + +function ci_dot(x, y) { + assert(x.length === y.length, 'Cannot calculate dot for vectors of different lengths'); + return x.reduce((prev, _, idx) => prev + Math.imul(x[idx], y[idx]), 0); +} + +// Cases: [f32|f16|abstract]_vecN_[non_]const +const float_cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[2, 3, 4].flatMap((N) => +[true, false].map((nonConst) => ({ + [`${trait === 'abstract' ? 'abstract_float' : trait}_vec${N}_${ + nonConst ? 'non_const' : 'const' + }`]: () => { + // Emit an empty array for not const abstract float, since they will never be run + if (trait === 'abstract' && nonConst) { + return []; + } + // vec3 and vec4 require calculating all possible permutations, so their runtime is much + // longer per test, so only using sparse vectors for them. + return FP[trait].generateVectorPairToIntervalCases( + N === 2 ? FP[trait].vectorRange(2) : FP[trait].sparseVectorRange(N), + N === 2 ? FP[trait].vectorRange(2) : FP[trait].sparseVectorRange(N), + nonConst ? 'unfiltered' : 'finite', + // dot has an inherited accuracy, so abstract is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].dotInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +const cases = { + ...float_cases, + abstract_int_vec2: () => { + return generateVectorVectorToI64Cases(vectorI64Range(2), vectorI64Range(2), ai_dot); + }, + abstract_int_vec3: () => { + return generateVectorVectorToI64Cases(sparseVectorI64Range(3), sparseVectorI64Range(3), ai_dot); + }, + abstract_int_vec4: () => { + return generateVectorVectorToI64Cases(sparseVectorI64Range(4), sparseVectorI64Range(4), ai_dot); + }, + i32_vec2: () => { + return generateVectorVectorToI32Cases(vectorI32Range(2), vectorI32Range(2), ci_dot); + }, + i32_vec3: () => { + return generateVectorVectorToI32Cases(sparseVectorI32Range(3), sparseVectorI32Range(3), ci_dot); + }, + i32_vec4: () => { + return generateVectorVectorToI32Cases(sparseVectorI32Range(4), sparseVectorI32Range(4), ci_dot); + }, + u32_vec2: () => { + return generateVectorVectorToU32Cases(vectorU32Range(2), vectorU32Range(2), ci_dot); + }, + u32_vec3: () => { + return generateVectorVectorToU32Cases(sparseVectorU32Range(3), sparseVectorU32Range(3), ci_dot); + }, + u32_vec4: () => { + return generateVectorVectorToU32Cases(sparseVectorU32Range(4), sparseVectorU32Range(4), ci_dot); + } +}; + +export const d = makeCaseCache('dot', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.spec.js index def9be1611..76cbb50393 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.spec.js @@ -3,85 +3,180 @@ **/export const description = ` Execution tests for the 'dot' builtin function -T is AbstractInt, AbstractFloat, i32, u32, f32, or f16 +T is Type.abstractInt, Type.abstractFloat, i32, u32, f32, or f16 @const fn dot(e1: vecN,e2: vecN) -> T Returns the dot product of e1 and e2. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { sparseVectorF32Range, vectorF32Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, abstractIntBuiltin, builtin } from './builtin.js'; +import { d } from './dot.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: [f32|f16]_vecN_[non_]const -const cases = ['f32', 'f16']. -flatMap((trait) => -[2, 3, 4].flatMap((N) => -[true, false].map((nonConst) => ({ - [`${trait}_vec${N}_${nonConst ? 'non_const' : 'const'}`]: () => { - // vec3 and vec4 require calculating all possible permutations, so their runtime is much - // longer per test, so only using sparse vectors for them. - return FP[trait].generateVectorPairToIntervalCases( - N === 2 ? vectorF32Range(2) : sparseVectorF32Range(N), - N === 2 ? vectorF32Range(2) : sparseVectorF32Range(N), - nonConst ? 'unfiltered' : 'finite', - FP[trait].dotInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('dot', cases); - -g.test('abstract_int'). -specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). -desc(`abstract int tests`). +g.test('abstract_int_vec2'). +specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). +desc(`abstract integer tests using vec2s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_int_vec2'); + await run( + t, + abstractIntBuiltin('dot'), + [Type.vec(2, Type.abstractInt), Type.vec(2, Type.abstractInt)], + Type.abstractInt, + t.params, + cases + ); +}); + +g.test('abstract_int_vec3'). +specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). +desc(`abstract integer tests using vec3s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_int_vec3'); + await run( + t, + abstractIntBuiltin('dot'), + [Type.vec(3, Type.abstractInt), Type.vec(3, Type.abstractInt)], + Type.abstractInt, + t.params, + cases + ); +}); + +g.test('abstract_int_vec4'). +specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). +desc(`abstract integer tests using vec4s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_int_vec4'); + await run( + t, + abstractIntBuiltin('dot'), + [Type.vec(4, Type.abstractInt), Type.vec(4, Type.abstractInt)], + Type.abstractInt, + t.params, + cases + ); +}); + +g.test('i32_vec2'). +specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). +desc(`i32 tests using vec2s`). params((u) => u.combine('inputSource', allInputSources)). -unimplemented(); +fn(async (t) => { + const cases = await d.get('i32_vec2'); + await run(t, builtin('dot'), [Type.vec2i, Type.vec2i], Type.i32, t.params, cases); +}); -g.test('i32'). +g.test('i32_vec3'). specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). -desc(`i32 tests`). +desc(`i32 tests using vec3s`). params((u) => u.combine('inputSource', allInputSources)). -unimplemented(); +fn(async (t) => { + const cases = await d.get('i32_vec3'); + await run(t, builtin('dot'), [Type.vec3i, Type.vec3i], Type.i32, t.params, cases); +}); -g.test('u32'). +g.test('i32_vec4'). specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). -desc(`u32 tests`). +desc(`i32 tests using vec4s`). params((u) => u.combine('inputSource', allInputSources)). -unimplemented(); +fn(async (t) => { + const cases = await d.get('i32_vec4'); + await run(t, builtin('dot'), [Type.vec4i, Type.vec4i], Type.i32, t.params, cases); +}); -g.test('abstract_float'). +g.test('u32_vec2'). specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). -desc(`abstract float test`). +desc(`u32 tests using vec2s`). params((u) => u.combine('inputSource', allInputSources)). -unimplemented(); +fn(async (t) => { + const cases = await d.get('u32_vec2'); + await run(t, builtin('dot'), [Type.vec2u, Type.vec2u], Type.u32, t.params, cases); +}); -g.test('f32_vec2'). +g.test('u32_vec3'). specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). -desc(`f32 tests using vec2s`). +desc(`u32 tests using vec3s`). params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { - const cases = await d.get( - t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const' + const cases = await d.get('u32_vec3'); + await run(t, builtin('dot'), [Type.vec3u, Type.vec3u], Type.u32, t.params, cases); +}); + +g.test('u32_vec4'). +specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). +desc(`u32 tests using vec4s`). +params((u) => u.combine('inputSource', allInputSources)). +fn(async (t) => { + const cases = await d.get('u32_vec4'); + await run(t, builtin('dot'), [Type.vec4u, Type.vec4u], Type.u32, t.params, cases); +}); + +g.test('abstract_float_vec2'). +specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). +desc(`abstract float tests using vec2s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_float_vec2_const'); + await run( + t, + abstractFloatBuiltin('dot'), + [Type.vec(2, Type.abstractFloat), Type.vec(2, Type.abstractFloat)], + Type.abstractFloat, + t.params, + cases ); +}); + +g.test('abstract_float_vec3'). +specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). +desc(`abstract float tests using vec3s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_float_vec3_const'); await run( t, - builtin('dot'), - [TypeVec(2, TypeF32), TypeVec(2, TypeF32)], - TypeF32, + abstractFloatBuiltin('dot'), + [Type.vec(3, Type.abstractFloat), Type.vec(3, Type.abstractFloat)], + Type.abstractFloat, t.params, cases ); }); +g.test('abstract_float_vec4'). +specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). +desc(`abstract float tests using vec4s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_float_vec4_const'); + await run( + t, + abstractFloatBuiltin('dot'), + [Type.vec(4, Type.abstractFloat), Type.vec(4, Type.abstractFloat)], + Type.abstractFloat, + t.params, + cases + ); +}); + +g.test('f32_vec2'). +specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). +desc(`f32 tests using vec2s`). +params((u) => u.combine('inputSource', allInputSources)). +fn(async (t) => { + const cases = await d.get( + t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const' + ); + await run(t, builtin('dot'), [Type.vec2f, Type.vec2f], Type.f32, t.params, cases); +}); + g.test('f32_vec3'). specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions'). desc(`f32 tests using vec3s`). @@ -90,14 +185,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const' ); - await run( - t, - builtin('dot'), - [TypeVec(3, TypeF32), TypeVec(3, TypeF32)], - TypeF32, - t.params, - cases - ); + await run(t, builtin('dot'), [Type.vec3f, Type.vec3f], Type.f32, t.params, cases); }); g.test('f32_vec4'). @@ -108,14 +196,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const' ); - await run( - t, - builtin('dot'), - [TypeVec(4, TypeF32), TypeVec(4, TypeF32)], - TypeF32, - t.params, - cases - ); + await run(t, builtin('dot'), [Type.vec4f, Type.vec4f], Type.f32, t.params, cases); }); g.test('f16_vec2'). @@ -129,14 +210,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec2_const' : 'f16_vec2_non_const' ); - await run( - t, - builtin('dot'), - [TypeVec(2, TypeF16), TypeVec(2, TypeF16)], - TypeF16, - t.params, - cases - ); + await run(t, builtin('dot'), [Type.vec2h, Type.vec2h], Type.f16, t.params, cases); }); g.test('f16_vec3'). @@ -150,14 +224,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec3_const' : 'f16_vec3_non_const' ); - await run( - t, - builtin('dot'), - [TypeVec(3, TypeF16), TypeVec(3, TypeF16)], - TypeF16, - t.params, - cases - ); + await run(t, builtin('dot'), [Type.vec3h, Type.vec3h], Type.f16, t.params, cases); }); g.test('f16_vec4'). @@ -171,12 +238,5 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec4_const' : 'f16_vec4_non_const' ); - await run( - t, - builtin('dot'), - [TypeVec(4, TypeF16), TypeVec(4, TypeF16)], - TypeF16, - t.params, - cases - ); + await run(t, builtin('dot'), [Type.vec4h, Type.vec4h], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot4I8Packed.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot4I8Packed.spec.js new file mode 100644 index 0000000000..9a2e9eae8d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot4I8Packed.spec.js @@ -0,0 +1,74 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for the 'dot4I8Packed' builtin function + +@const fn dot4I8Packed(e1: u32 ,e2: u32) -> i32 +e1 and e2 are interpreted as vectors with four 8-bit signed integer components. Return the signed +integer dot product of these two vectors. Each component is sign-extended to i32 before performing +the multiply, and then the add operations are done in WGSL i32 with wrapping behaviour. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { Type, i32, u32 } from '../../../../../util/conversion.js'; + +import { allInputSources, run } from '../../expression.js'; + +import { builtin } from './builtin.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('basic'). +specURL('https://www.w3.org/TR/WGSL/#dot4I8Packed-builtin'). +desc( + ` +@const fn dot4I8Packed(e1: u32, e2: u32) -> i32 + ` +). +params((u) => u.combine('inputSource', allInputSources)). +fn(async (t) => { + const cfg = t.params; + + const dot4I8Packed = (e1, e2) => { + let result = 0; + for (let i = 0; i < 4; ++i) { + let e1_i = e1 >> i * 8 & 0xff; + if (e1_i >= 128) { + e1_i -= 256; + } + let e2_i = e2 >> i * 8 & 0xff; + if (e2_i >= 128) { + e2_i -= 256; + } + result += e1_i * e2_i; + } + return result; + }; + + const testInputs = [ + // dot({0, 0, 0, 0}, {0, 0, 0, 0}) + [0, 0], + // dot({127, 127, 127, 127}, {127, 127, 127, 127}) + [0x7f7f7f7f, 0x7f7f7f7f], + // dot({-128, -128, -128, -128}, {-128, -128, -128, -128}) + [0x80808080, 0x80808080], + // dot({127, 127, 127, 127}, {-128, -128, -128, -128}) + [0x7f7f7f7f, 0x80808080], + // dot({1, 2, 3, 4}, {5, 6, 7, 8}) + [0x01020304, 0x05060708], + // dot({1, 2, 3, 4}, {-1, -2, -3, -4}) + [0x01020304, 0xfffefdfc], + // dot({-5, -6, -7, -8}, {5, 6, 7, 8}) + [0xfbfaf9f8, 0x05060708], + // dot({-9, -10, -11, -12}, {-13, -14, -15, -16}) + [0xf7f6f5f4, 0xf3f2f1f0]]; + + + const makeCase = (x, y) => { + return { input: [u32(x), u32(y)], expected: i32(dot4I8Packed(x, y)) }; + }; + const cases = testInputs.flatMap((v) => { + return [makeCase(...v)]; + }); + + await run(t, builtin('dot4I8Packed'), [Type.u32, Type.u32], Type.i32, cfg, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot4U8Packed.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot4U8Packed.spec.js new file mode 100644 index 0000000000..7fd3c08a5f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot4U8Packed.spec.js @@ -0,0 +1,59 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for the 'dot4U8Packed' builtin function + +@const fn dot4U8Packed(e1: u32 ,e2: u32) -> u32 +e1 and e2 are interpreted as vectors with four 8-bit unsigned integer components. Return the +unsigned integer dot product of these two vectors. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { Type, u32 } from '../../../../../util/conversion.js'; + +import { allInputSources, run } from '../../expression.js'; + +import { builtin } from './builtin.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('basic'). +specURL('https://www.w3.org/TR/WGSL/#dot4U8Packed-builtin'). +desc( + ` +@const fn dot4U8Packed(e1: u32, e2: u32) -> u32 + ` +). +params((u) => u.combine('inputSource', allInputSources)). +fn(async (t) => { + const cfg = t.params; + + const dot4U8Packed = (e1, e2) => { + let result = 0; + for (let i = 0; i < 4; ++i) { + const e1_i = e1 >> i * 8 & 0xff; + const e2_i = e2 >> i * 8 & 0xff; + result += e1_i * e2_i; + } + return result; + }; + + const testInputs = [ + // dot({0, 0, 0, 0}, {0, 0, 0, 0}) + [0, 0], + // dot({255u, 255u, 255u, 255u}, {255u, 255u, 255u, 255u}) + [0xffffffff, 0xffffffff], + // dot({1u, 2u, 3u, 4u}, {5u, 6u, 7u, 8u}) + [0x01020304, 0x05060708], + // dot({120u, 90u, 60u, 30u}, {50u, 100u, 150u, 200u}) + [0x785a3c1e, 0x326496c8]]; + + + const makeCase = (x, y) => { + return { input: [u32(x), u32(y)], expected: u32(dot4U8Packed(x, y)) }; + }; + const cases = testInputs.flatMap((v) => { + return [makeCase(...v)]; + }); + + await run(t, builtin('dot4U8Packed'), [Type.u32, Type.u32], Type.u32, cfg, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdx.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdx.spec.js index 9d595f7d23..9ea801316d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdx.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdx.spec.js @@ -10,14 +10,22 @@ The result is the same as either dpdxFine(e) or dpdxCoarse(e). `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { allInputSources } from '../../expression.js'; + +import { d } from './derivatives.cache.js'; +import { runDerivativeTest } from './derivatives.js'; export const g = makeTestGroup(GPUTest); +const builtin = 'dpdx'; + g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions'). -desc(`f32 tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('vectorize', [undefined, 2, 3, 4]). +combine('non_uniform_discard', [false, true]) ). -unimplemented(); \ No newline at end of file +fn(async (t) => { + const cases = await d.get('scalar'); + runDerivativeTest(t, cases, builtin, t.params.non_uniform_discard, t.params.vectorize); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxCoarse.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxCoarse.spec.js index db31f42df1..9b1b78f381 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxCoarse.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxCoarse.spec.js @@ -9,14 +9,22 @@ Returns the partial derivative of e with respect to window x coordinates using l This may result in fewer unique positions that dpdxFine(e). `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { allInputSources } from '../../expression.js'; + +import { d } from './derivatives.cache.js'; +import { runDerivativeTest } from './derivatives.js'; export const g = makeTestGroup(GPUTest); +const builtin = 'dpdxCoarse'; + g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions'). -desc(`f32 tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('vectorize', [undefined, 2, 3, 4]). +combine('non_uniform_discard', [false, true]) ). -unimplemented(); \ No newline at end of file +fn(async (t) => { + const cases = await d.get('scalar'); + runDerivativeTest(t, cases, builtin, t.params.non_uniform_discard, t.params.vectorize); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxFine.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxFine.spec.js index 5eaf792439..25a0436034 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxFine.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxFine.spec.js @@ -8,14 +8,22 @@ fn dpdxFine(e:T) ->T Returns the partial derivative of e with respect to window x coordinates. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { allInputSources } from '../../expression.js'; + +import { d } from './derivatives.cache.js'; +import { runDerivativeTest } from './derivatives.js'; export const g = makeTestGroup(GPUTest); +const builtin = 'dpdxFine'; + g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions'). -desc(`f32 tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('vectorize', [undefined, 2, 3, 4]). +combine('non_uniform_discard', [false, true]) ). -unimplemented(); \ No newline at end of file +fn(async (t) => { + const cases = await d.get('scalar'); + runDerivativeTest(t, cases, builtin, t.params.non_uniform_discard, t.params.vectorize); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdy.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdy.spec.js index edba9b14c1..0f79064b92 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdy.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdy.spec.js @@ -9,14 +9,22 @@ Partial derivative of e with respect to window y coordinates. The result is the same as either dpdyFine(e) or dpdyCoarse(e). `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { allInputSources } from '../../expression.js'; + +import { d } from './derivatives.cache.js'; +import { runDerivativeTest } from './derivatives.js'; export const g = makeTestGroup(GPUTest); +const builtin = 'dpdy'; + g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions'). -desc(`f32 tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('vectorize', [undefined, 2, 3, 4]). +combine('non_uniform_discard', [false, true]) ). -unimplemented(); \ No newline at end of file +fn(async (t) => { + const cases = await d.get('scalar'); + runDerivativeTest(t, cases, builtin, t.params.non_uniform_discard, t.params.vectorize); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyCoarse.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyCoarse.spec.js index f002a587b6..c547896de9 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyCoarse.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyCoarse.spec.js @@ -9,14 +9,22 @@ Returns the partial derivative of e with respect to window y coordinates using l This may result in fewer unique positions that dpdyFine(e). `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { allInputSources } from '../../expression.js'; + +import { d } from './derivatives.cache.js'; +import { runDerivativeTest } from './derivatives.js'; export const g = makeTestGroup(GPUTest); +const builtin = 'dpdyCoarse'; + g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions'). -desc(`f32 test`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('vectorize', [undefined, 2, 3, 4]). +combine('non_uniform_discard', [false, true]) ). -unimplemented(); \ No newline at end of file +fn(async (t) => { + const cases = await d.get('scalar'); + runDerivativeTest(t, cases, builtin, t.params.non_uniform_discard, t.params.vectorize); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyFine.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyFine.spec.js index 405914acf1..85a829ca00 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyFine.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyFine.spec.js @@ -8,14 +8,22 @@ fn dpdyFine(e:T) ->T Returns the partial derivative of e with respect to window y coordinates. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { allInputSources } from '../../expression.js'; + +import { d } from './derivatives.cache.js'; +import { runDerivativeTest } from './derivatives.js'; export const g = makeTestGroup(GPUTest); +const builtin = 'dpdyFine'; + g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions'). -desc(`f32 tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('vectorize', [undefined, 2, 3, 4]). +combine('non_uniform_discard', [false, true]) ). -unimplemented(); \ No newline at end of file +fn(async (t) => { + const cases = await d.get('scalar'); + runDerivativeTest(t, cases, builtin, t.params.non_uniform_discard, t.params.vectorize); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.cache.js new file mode 100644 index 0000000000..00a4cd7d2d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.cache.js @@ -0,0 +1,44 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kValue } from '../../../../../util/constants.js';import { FP } from '../../../../../util/floating_point.js';import { biasedRange, linearRange } from '../../../../../util/math.js'; +import { makeCaseCache } from '../../case_cache.js'; + +// floor(ln(max f32 value)) = 88, so exp(88) will be within range of a f32, but exp(89) will not +// floor(ln(max f64 value)) = 709, so exp(709) can be handled by the testing framework, but exp(710) will misbehave +const f32_inputs = [ +0, // Returns 1 by definition +-89, // Returns subnormal value +kValue.f32.negative.min, // Closest to returning 0 as possible +...biasedRange(kValue.f32.negative.max, -88, 100), +...biasedRange(kValue.f32.positive.min, 88, 100), +...linearRange(89, 709, 10) // Overflows f32, but not f64 +]; + +// floor(ln(max f16 value)) = 11, so exp(11) will be within range of a f16, but exp(12) will not +const f16_inputs = [ +0, // Returns 1 by definition +-12, // Returns subnormal value +kValue.f16.negative.min, // Closest to returning 0 as possible +...biasedRange(kValue.f16.negative.max, -11, 100), +...biasedRange(kValue.f16.positive.min, 11, 100), +...linearRange(12, 709, 10) // Overflows f16, but not f64 +]; + +export const d = makeCaseCache('exp', { + f32_const: () => { + return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.expInterval); + }, + f32_non_const: () => { + return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', FP.f32.expInterval); + }, + f16_const: () => { + return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', FP.f16.expInterval); + }, + f16_non_const: () => { + return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', FP.f16.expInterval); + }, + abstract: () => { + // exp has an ulp accuracy, so is only expected to be as accurate as f32 + return FP.abstract.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.expInterval); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.spec.js index 9eac534ba3..69883e92c0 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.spec.js @@ -3,66 +3,39 @@ **/export const description = ` Execution tests for the 'exp' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn exp(e1: T ) -> T Returns the natural exponentiation of e1 (e.g. e^e1). Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { kValue } from '../../../../../util/constants.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { biasedRange, linearRange } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './exp.cache.js'; export const g = makeTestGroup(GPUTest); -// floor(ln(max f32 value)) = 88, so exp(88) will be within range of a f32, but exp(89) will not -// floor(ln(max f64 value)) = 709, so exp(709) can be handled by the testing framework, but exp(710) will misbehave -const f32_inputs = [ -0, // Returns 1 by definition --89, // Returns subnormal value -kValue.f32.negative.min, // Closest to returning 0 as possible -...biasedRange(kValue.f32.negative.max, -88, 100), -...biasedRange(kValue.f32.positive.min, 88, 100), -...linearRange(89, 709, 10) // Overflows f32, but not f64 -]; - -// floor(ln(max f16 value)) = 11, so exp(11) will be within range of a f16, but exp(12) will not -const f16_inputs = [ -0, // Returns 1 by definition --12, // Returns subnormal value -kValue.f16.negative.min, // Closest to returning 0 as possible -...biasedRange(kValue.f16.negative.max, -11, 100), -...biasedRange(kValue.f16.positive.min, 11, 100), -...linearRange(12, 709, 10) // Overflows f16, but not f64 -]; - -export const d = makeCaseCache('exp', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.expInterval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', FP.f32.expInterval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', FP.f16.expInterval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', FP.f16.expInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('exp'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -72,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('exp'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('exp'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -86,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('exp'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('exp'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.cache.js new file mode 100644 index 0000000000..c001595cc0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.cache.js @@ -0,0 +1,44 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kValue } from '../../../../../util/constants.js';import { FP } from '../../../../../util/floating_point.js';import { biasedRange, linearRange } from '../../../../../util/math.js'; +import { makeCaseCache } from '../../case_cache.js'; + +// floor(log2(max f32 value)) = 127, so exp2(127) will be within range of a f32, but exp2(128) will not +// floor(ln(max f64 value)) = 1023, so exp2(1023) can be handled by the testing framework, but exp2(1024) will misbehave +const f32_inputs = [ +0, // Returns 1 by definition +-128, // Returns subnormal value +kValue.f32.negative.min, // Closest to returning 0 as possible +...biasedRange(kValue.f32.negative.max, -127, 100), +...biasedRange(kValue.f32.positive.min, 127, 100), +...linearRange(128, 1023, 10) // Overflows f32, but not f64 +]; + +// floor(log2(max f16 value)) = 15, so exp2(15) will be within range of a f16, but exp2(15) will not +const f16_inputs = [ +0, // Returns 1 by definition +-16, // Returns subnormal value +kValue.f16.negative.min, // Closest to returning 0 as possible +...biasedRange(kValue.f16.negative.max, -15, 100), +...biasedRange(kValue.f16.positive.min, 15, 100), +...linearRange(16, 1023, 10) // Overflows f16, but not f64 +]; + +export const d = makeCaseCache('exp2', { + f32_const: () => { + return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.exp2Interval); + }, + f32_non_const: () => { + return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', FP.f32.exp2Interval); + }, + f16_const: () => { + return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', FP.f16.exp2Interval); + }, + f16_non_const: () => { + return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', FP.f16.exp2Interval); + }, + abstract: () => { + // exp2 has an ulp accuracy, so is only expected to be as accurate as f32 + return FP.abstract.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.exp2Interval); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.spec.js index 288079ef82..573512cb52 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.spec.js @@ -3,66 +3,39 @@ **/export const description = ` Execution tests for the 'exp2' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn exp2(e: T ) -> T Returns 2 raised to the power e (e.g. 2^e). Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { kValue } from '../../../../../util/constants.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { biasedRange, linearRange } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './exp2.cache.js'; export const g = makeTestGroup(GPUTest); -// floor(log2(max f32 value)) = 127, so exp2(127) will be within range of a f32, but exp2(128) will not -// floor(ln(max f64 value)) = 1023, so exp2(1023) can be handled by the testing framework, but exp2(1024) will misbehave -const f32_inputs = [ -0, // Returns 1 by definition --128, // Returns subnormal value -kValue.f32.negative.min, // Closest to returning 0 as possible -...biasedRange(kValue.f32.negative.max, -127, 100), -...biasedRange(kValue.f32.positive.min, 127, 100), -...linearRange(128, 1023, 10) // Overflows f32, but not f64 -]; - -// floor(log2(max f16 value)) = 15, so exp2(15) will be within range of a f16, but exp2(15) will not -const f16_inputs = [ -0, // Returns 1 by definition --16, // Returns subnormal value -kValue.f16.negative.min, // Closest to returning 0 as possible -...biasedRange(kValue.f16.negative.max, -15, 100), -...biasedRange(kValue.f16.positive.min, 15, 100), -...linearRange(16, 1023, 10) // Overflows f16, but not f64 -]; - -export const d = makeCaseCache('exp2', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.exp2Interval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', FP.f32.exp2Interval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', FP.f16.exp2Interval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', FP.f16.exp2Interval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('exp2'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -72,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('exp2'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('exp2'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -86,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('exp2'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('exp2'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/extractBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/extractBits.spec.js index 3faccc58a7..ea3197696d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/extractBits.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/extractBits.spec.js @@ -33,17 +33,7 @@ Other bits of the result are the same as bit c-1 of the result. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { - i32Bits, - TypeI32, - u32, - TypeU32, - u32Bits, - vec2, - vec3, - vec4, - TypeVec } from -'../../../../../util/conversion.js'; +import { i32Bits, Type, u32, u32Bits, vec2, vec3, vec4 } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -57,7 +47,7 @@ params((u) => u.combine('inputSource', allInputSources).combine('width', [1, 2, fn(async (t) => { const cfg = t.params; - const T = t.params.width === 1 ? TypeU32 : TypeVec(t.params.width, TypeU32); + const T = t.params.width === 1 ? Type.u32 : Type.vec(t.params.width, Type.u32); const V = (x, y, z, w) => { y = y === undefined ? x : y; @@ -193,7 +183,7 @@ fn(async (t) => { ); } - await run(t, builtin('extractBits'), [T, TypeU32, TypeU32], T, cfg, cases); + await run(t, builtin('extractBits'), [T, Type.u32, Type.u32], T, cfg, cases); }); g.test('i32'). @@ -203,7 +193,7 @@ params((u) => u.combine('inputSource', allInputSources).combine('width', [1, 2, fn(async (t) => { const cfg = t.params; - const T = t.params.width === 1 ? TypeI32 : TypeVec(t.params.width, TypeI32); + const T = t.params.width === 1 ? Type.i32 : Type.vec(t.params.width, Type.i32); const V = (x, y, z, w) => { y = y === undefined ? x : y; @@ -333,5 +323,5 @@ fn(async (t) => { ); } - await run(t, builtin('extractBits'), [T, TypeU32, TypeU32], T, cfg, cases); + await run(t, builtin('extractBits'), [T, Type.u32, Type.u32], T, cfg, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.cache.js new file mode 100644 index 0000000000..f2b96e3a5f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.cache.js @@ -0,0 +1,125 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { anyOf } from '../../../../../util/compare.js';import { toVector } from '../../../../../util/conversion.js'; +import { FP } from '../../../../../util/floating_point.js'; +import { cartesianProduct } from '../../../../../util/math.js'; +import { selectNCases } from '../../case.js'; +import { makeCaseCache } from '../../case_cache.js'; + + +// Using a bespoke implementation of make*Case and generate*Cases here +// since faceForwardIntervals is the only builtin with the API signature +// (vec, vec, vec) -> vec +// +// Additionally faceForward has significant complexities around it due to the +// fact that `dot` is calculated in its operation, but the result of dot isn't +// used to calculate the builtin's result. + +/** + * @returns a Case for `faceForward` + * @param argumentKind what kind of floating point numbers being operated on + * @param parameterKind what kind of floating point operation should be performed, + * should be the same as argumentKind, except for abstract + * @param x the `x` param for the case + * @param y the `y` param for the case + * @param z the `z` param for the case + * @param check what interval checking to apply + * */ +function makeCase( +argumentKind, +parameterKind, +x, +y, +z, +check) +{ + const fp = FP[argumentKind]; + x = x.map(fp.quantize); + y = y.map(fp.quantize); + z = z.map(fp.quantize); + + const results = FP[parameterKind].faceForwardIntervals(x, y, z); + if (check === 'finite' && results.some((r) => r === undefined)) { + return undefined; + } + + // Stripping the undefined results, since undefined is used to signal that an OOB + // could occur within the calculation that isn't reflected in the result + // intervals. + const define_results = results.filter((r) => r !== undefined); + + return { + input: [ + toVector(x, fp.scalarBuilder), + toVector(y, fp.scalarBuilder), + toVector(z, fp.scalarBuilder)], + + expected: anyOf(...define_results) + }; +} + +/** + * @returns an array of Cases for `faceForward` + * @param argumentKind what kind of floating point numbers being operated on + * @param parameterKind what kind of floating point operation should be performed, + * should be the same as argumentKind, except for abstract + * @param xs array of inputs to try for the `x` param + * @param ys array of inputs to try for the `y` param + * @param zs array of inputs to try for the `z` param + * @param check what interval checking to apply + */ +function generateCases( +argumentKind, +parameterKind, +xs, +ys, +zs, +check) +{ + // Cannot use `cartesianProduct` here due to heterogeneous param types + return cartesianProduct(xs, ys, zs). + map((e) => makeCase(argumentKind, parameterKind, e[0], e[1], e[2], check)). + filter((c) => c !== undefined); +} + +// Cases: [f32|f16|abstract]_vecN_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[2, 3, 4].flatMap((dim) => +[true, false].map((nonConst) => ({ + [`${trait}_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + if (trait !== 'abstract') { + return generateCases( + trait, + trait, + FP[trait].sparseVectorRange(dim), + FP[trait].sparseVectorRange(dim), + FP[trait].sparseVectorRange(dim), + nonConst ? 'unfiltered' : 'finite' + ); + } else { + // Restricting the number of cases, because a vector of abstract floats needs to be returned, which is costly. + return selectNCases( + 'faceForward', + 20, + generateCases( + trait, + // faceForward has an inherited accuracy, so is only expected to be as accurate as f32 + 'f32', + FP[trait].sparseVectorRange(dim), + FP[trait].sparseVectorRange(dim), + FP[trait].sparseVectorRange(dim), + nonConst ? 'unfiltered' : 'finite' + ) + ); + } + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('faceForward', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.spec.js index 20ac9cbd2c..542bff23f3 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.spec.js @@ -3,140 +3,66 @@ **/export const description = ` Execution tests for the 'faceForward' builtin function -T is vecN, vecN, or vecN +T is vecN, vecN, or vecN @const fn faceForward(e1: T ,e2: T ,e3: T ) -> T Returns e1 if dot(e2,e3) is negative, and -e1 otherwise. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; - import { GPUTest } from '../../../../../gpu_test.js'; -import { anyOf } from '../../../../../util/compare.js'; -import { toVector, TypeF32, TypeF16, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { - cartesianProduct, - sparseVectorF32Range, - sparseVectorF16Range } from -'../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './faceForward.cache.js'; export const g = makeTestGroup(GPUTest); -// Using a bespoke implementation of make*Case and generate*Cases here -// since faceForwardIntervals is the only builtin with the API signature -// (vec, vec, vec) -> vec -// -// Additionally faceForward has significant complexities around it due to the -// fact that `dot` is calculated in it s operation, but the result of dot isn't -// used to calculate the builtin's result. - -/** - * @returns a Case for `faceForward` - * @param kind what kind of floating point numbers being operated on - * @param x the `x` param for the case - * @param y the `y` param for the case - * @param z the `z` param for the case - * @param check what interval checking to apply - * */ -function makeCase( -kind, -x, -y, -z, -check) -{ - const fp = FP[kind]; - x = x.map(fp.quantize); - y = y.map(fp.quantize); - z = z.map(fp.quantize); - - const results = FP[kind].faceForwardIntervals(x, y, z); - if (check === 'finite' && results.some((r) => r === undefined)) { - return undefined; - } - - // Stripping the undefined results, since undefined is used to signal that an OOB - // could occur within the calculation that isn't reflected in the result - // intervals. - const define_results = results.filter((r) => r !== undefined); - - return { - input: [ - toVector(x, fp.scalarBuilder), - toVector(y, fp.scalarBuilder), - toVector(z, fp.scalarBuilder)], - - expected: anyOf(...define_results) - }; -} - -/** - * @returns an array of Cases for `faceForward` - * @param kind what kind of floating point numbers being operated on - * @param xs array of inputs to try for the `x` param - * @param ys array of inputs to try for the `y` param - * @param zs array of inputs to try for the `z` param - * @param check what interval checking to apply - */ -function generateCases( -kind, -xs, -ys, -zs, -check) -{ - // Cannot use `cartesianProduct` here due to heterogeneous param types - return cartesianProduct(xs, ys, zs). - map((e) => makeCase(kind, e[0], e[1], e[2], check)). - filter((c) => c !== undefined); -} - -// Cases: f32_vecN_[non_]const -const f32_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f32_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return generateCases( - 'f32', - sparseVectorF32Range(n), - sparseVectorF32Range(n), - sparseVectorF32Range(n), - nonConst ? 'unfiltered' : 'finite' - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: f16_vecN_[non_]const -const f16_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f16_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return generateCases( - 'f16', - sparseVectorF16Range(n), - sparseVectorF16Range(n), - sparseVectorF16Range(n), - nonConst ? 'unfiltered' : 'finite' - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); +g.test('abstract_float_vec2'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec2s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec2_const'); + await run( + t, + abstractFloatBuiltin('faceForward'), + [Type.vec2af, Type.vec2af, Type.vec2af], + Type.vec2af, + t.params, + cases + ); +}); -export const d = makeCaseCache('faceForward', { - ...f32_vec_cases, - ...f16_vec_cases +g.test('abstract_float_vec3'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec3s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec3_const'); + await run( + t, + abstractFloatBuiltin('faceForward'), + [Type.vec3af, Type.vec3af, Type.vec3af], + Type.vec3af, + t.params, + cases + ); }); -g.test('abstract_float'). -specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). -desc(`abstract float tests`). -params((u) => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4])). -unimplemented(); +g.test('abstract_float_vec4'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec4s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec4_const'); + await run( + t, + abstractFloatBuiltin('faceForward'), + [Type.vec4af, Type.vec4af, Type.vec4af], + Type.vec4af, + t.params, + cases + ); +}); g.test('f32_vec2'). specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). @@ -149,8 +75,8 @@ fn(async (t) => { await run( t, builtin('faceForward'), - [TypeVec(2, TypeF32), TypeVec(2, TypeF32), TypeVec(2, TypeF32)], - TypeVec(2, TypeF32), + [Type.vec2f, Type.vec2f, Type.vec2f], + Type.vec2f, t.params, cases ); @@ -167,8 +93,8 @@ fn(async (t) => { await run( t, builtin('faceForward'), - [TypeVec(3, TypeF32), TypeVec(3, TypeF32), TypeVec(3, TypeF32)], - TypeVec(3, TypeF32), + [Type.vec3f, Type.vec3f, Type.vec3f], + Type.vec3f, t.params, cases ); @@ -185,8 +111,8 @@ fn(async (t) => { await run( t, builtin('faceForward'), - [TypeVec(4, TypeF32), TypeVec(4, TypeF32), TypeVec(4, TypeF32)], - TypeVec(4, TypeF32), + [Type.vec4f, Type.vec4f, Type.vec4f], + Type.vec4f, t.params, cases ); @@ -206,8 +132,8 @@ fn(async (t) => { await run( t, builtin('faceForward'), - [TypeVec(2, TypeF16), TypeVec(2, TypeF16), TypeVec(2, TypeF16)], - TypeVec(2, TypeF16), + [Type.vec2h, Type.vec2h, Type.vec2h], + Type.vec2h, t.params, cases ); @@ -227,8 +153,8 @@ fn(async (t) => { await run( t, builtin('faceForward'), - [TypeVec(3, TypeF16), TypeVec(3, TypeF16), TypeVec(3, TypeF16)], - TypeVec(3, TypeF16), + [Type.vec3h, Type.vec3h, Type.vec3h], + Type.vec3h, t.params, cases ); @@ -248,8 +174,8 @@ fn(async (t) => { await run( t, builtin('faceForward'), - [TypeVec(4, TypeF16), TypeVec(4, TypeF16), TypeVec(4, TypeF16)], - TypeVec(4, TypeF16), + [Type.vec4h, Type.vec4h, Type.vec4h], + Type.vec4h, t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstLeadingBit.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstLeadingBit.spec.js index fd6b6359f1..139e653961 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstLeadingBit.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstLeadingBit.spec.js @@ -16,7 +16,7 @@ Otherwise the position of the most significant bit in e that is different from e Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { i32, i32Bits, TypeI32, u32, TypeU32, u32Bits } from '../../../../../util/conversion.js'; +import { i32, i32Bits, Type, u32, u32Bits } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -31,7 +31,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cfg = t.params; - await run(t, builtin('firstLeadingBit'), [TypeU32], TypeU32, cfg, [ + await run(t, builtin('firstLeadingBit'), [Type.u32], Type.u32, cfg, [ // Zero { input: u32Bits(0b00000000000000000000000000000000), expected: u32(-1) }, @@ -146,7 +146,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cfg = t.params; - await run(t, builtin('firstLeadingBit'), [TypeI32], TypeI32, cfg, [ + await run(t, builtin('firstLeadingBit'), [Type.i32], Type.i32, cfg, [ // Zero { input: i32Bits(0b00000000000000000000000000000000), expected: i32(-1) }, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstTrailingBit.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstTrailingBit.spec.js index 73071c3808..51fa9fa474 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstTrailingBit.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstTrailingBit.spec.js @@ -12,7 +12,7 @@ Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { i32, i32Bits, TypeI32, u32, TypeU32, u32Bits } from '../../../../../util/conversion.js'; +import { i32, i32Bits, Type, u32, u32Bits } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -27,7 +27,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cfg = t.params; - await run(t, builtin('firstTrailingBit'), [TypeU32], TypeU32, cfg, [ + await run(t, builtin('firstTrailingBit'), [Type.u32], Type.u32, cfg, [ // Zero { input: u32Bits(0b00000000000000000000000000000000), expected: u32(-1) }, @@ -142,7 +142,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cfg = t.params; - await run(t, builtin('firstTrailingBit'), [TypeI32], TypeI32, cfg, [ + await run(t, builtin('firstTrailingBit'), [Type.i32], Type.i32, cfg, [ // Zero { input: i32Bits(0b00000000000000000000000000000000), expected: i32(-1) }, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.cache.js new file mode 100644 index 0000000000..a15ef4c952 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.cache.js @@ -0,0 +1,26 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +const kSmallMagnitudeTestValues = [0.1, 0.9, 1.0, 1.1, 1.9, -0.1, -0.9, -1.0, -1.1, -1.9]; + +// See https://github.com/gpuweb/cts/issues/2766 for details +const kIssue2766Value = { + abstract: 0x8000_0000_0000_0000, + f32: 0x8000_0000, + f16: 0x8000 +}; + +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + [...kSmallMagnitudeTestValues, kIssue2766Value[trait], ...FP[trait].scalarRange()], + 'unfiltered', + FP[trait].floorInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('floor', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.spec.js index 322fffe0eb..6274dd75d1 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.spec.js @@ -3,60 +3,20 @@ **/export const description = ` Execution tests for the 'floor' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn floor(e: T ) -> T Returns the floor of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16, TypeAbstractFloat } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range, fullF64Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './floor.cache.js'; export const g = makeTestGroup(GPUTest); -const kSmallMagnitudeTestValues = [0.1, 0.9, 1.0, 1.1, 1.9, -0.1, -0.9, -1.0, -1.1, -1.9]; - -export const d = makeCaseCache('floor', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - [ - ...kSmallMagnitudeTestValues, - ...fullF32Range(), - 0x8000_0000 // https://github.com/gpuweb/cts/issues/2766 - ], - 'unfiltered', - FP.f32.floorInterval - ); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - [ - ...kSmallMagnitudeTestValues, - ...fullF16Range(), - 0x8000 // https://github.com/gpuweb/cts/issues/2766 - ], - 'unfiltered', - FP.f16.floorInterval - ); - }, - abstract: () => { - return FP.abstract.generateScalarToIntervalCases( - [ - ...kSmallMagnitudeTestValues, - ...fullF64Range(), - 0x8000_0000_0000_0000 // https://github.com/gpuweb/cts/issues/2766 - ], - 'unfiltered', - FP.abstract.floorInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). @@ -67,7 +27,14 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const cases = await d.get('abstract'); - await run(t, abstractBuiltin('floor'), [TypeAbstractFloat], TypeAbstractFloat, t.params, cases); + await run( + t, + abstractFloatBuiltin('floor'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); }); g.test('f32'). @@ -78,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('floor'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('floor'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -92,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('floor'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('floor'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.cache.js new file mode 100644 index 0000000000..d8a7da7aab --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.cache.js @@ -0,0 +1,26 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_[non_]const +// abstract_non_const is empty and not used +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarTripleToIntervalCases( + FP[trait].sparseScalarRange(), + FP[trait].sparseScalarRange(), + FP[trait].sparseScalarRange(), + nonConst ? 'unfiltered' : 'finite', + // fma has an inherited accuracy, so abstract is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].fmaInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('fma', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.spec.js index f5bac2d922..ed0203f89f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.spec.js @@ -3,70 +3,20 @@ **/export const description = ` Execution tests for the 'fma' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn fma(e1: T ,e2: T ,e3: T ) -> T Returns e1 * e2 + e3. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16, TypeAbstractFloat } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { sparseF32Range, sparseF16Range, sparseF64Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './fma.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('fma', { - f32_const: () => { - return FP.f32.generateScalarTripleToIntervalCases( - sparseF32Range(), - sparseF32Range(), - sparseF32Range(), - 'finite', - FP.f32.fmaInterval - ); - }, - f32_non_const: () => { - return FP.f32.generateScalarTripleToIntervalCases( - sparseF32Range(), - sparseF32Range(), - sparseF32Range(), - 'unfiltered', - FP.f32.fmaInterval - ); - }, - f16_const: () => { - return FP.f16.generateScalarTripleToIntervalCases( - sparseF16Range(), - sparseF16Range(), - sparseF16Range(), - 'finite', - FP.f16.fmaInterval - ); - }, - f16_non_const: () => { - return FP.f16.generateScalarTripleToIntervalCases( - sparseF16Range(), - sparseF16Range(), - sparseF16Range(), - 'unfiltered', - FP.f16.fmaInterval - ); - }, - abstract: () => { - return FP.abstract.generateScalarTripleToIntervalCases( - sparseF64Range(), - sparseF64Range(), - sparseF64Range(), - 'finite', - FP.abstract.fmaInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). @@ -76,12 +26,12 @@ combine('inputSource', onlyConstInputSource). combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { - const cases = await d.get('abstract'); + const cases = await d.get('abstract_const'); await run( t, - abstractBuiltin('fma'), - [TypeAbstractFloat, TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBuiltin('fma'), + [Type.abstractFloat, Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -95,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('fma'), [TypeF32, TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, builtin('fma'), [Type.f32, Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -109,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('fma'), [TypeF16, TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, builtin('fma'), [Type.f16, Type.f16, Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.cache.js new file mode 100644 index 0000000000..7610605bfa --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.cache.js @@ -0,0 +1,50 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +const kCommonValues = [ +0.5, // 0.5 -> 0.5 +0.9, // ~0.9 -> ~0.9 +1, // 1 -> 0 +2, // 2 -> 0 +1.11, // ~1.11 -> ~0.11 +-0.1, // ~-0.1 -> ~0.9 +-0.5, // -0.5 -> 0.5 +-0.9, // ~-0.9 -> ~0.1 +-1, // -1 -> 0 +-2, // -2 -> 0 +-1.11 // ~-1.11 -> ~0.89 +]; + +const kTraitSpecificValues = { + f32: [ + 10.0001, // ~10.0001 -> ~0.0001 + -10.0001, // -10.0001 -> ~0.9999 + 0x8000_0000 // https://github.com/gpuweb/cts/issues/2766 + ], + f16: [ + 10.0078125, // 10.0078125 -> 0.0078125 + -10.0078125, // -10.0078125 -> 0.9921875 + 658.5, // 658.5 -> 0.5 + 0x8000 // https://github.com/gpuweb/cts/issues/2766 + ], + abstract: [ + 10.0001, // ~10.0001 -> ~0.0001 + -10.0001, // -10.0001 -> ~0.9999 + 0x8000_0000 // https://github.com/gpuweb/cts/issues/2766 + ] +}; + +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + [...kCommonValues, ...kTraitSpecificValues[trait], ...FP[trait].scalarRange()], + trait === 'abstract' ? 'finite' : 'unfiltered', + FP[trait].fractInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('fract', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.spec.js index 8f85d604bc..b556fcf18f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.spec.js @@ -3,79 +3,40 @@ **/export const description = ` Execution tests for the 'fract' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn fract(e: T ) -> T Returns the fractional part of e, computed as e - floor(e). Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './fract.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('fract', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - [ - 0.5, // 0.5 -> 0.5 - 0.9, // ~0.9 -> ~0.9 - 1, // 1 -> 0 - 2, // 2 -> 0 - 1.11, // ~1.11 -> ~0.11 - 10.0001, // ~10.0001 -> ~0.0001 - -0.1, // ~-0.1 -> ~0.9 - -0.5, // -0.5 -> 0.5 - -0.9, // ~-0.9 -> ~0.1 - -1, // -1 -> 0 - -2, // -2 -> 0 - -1.11, // ~-1.11 -> ~0.89 - -10.0001, // -10.0001 -> ~0.9999 - 0x80000000, // https://github.com/gpuweb/cts/issues/2766 - ...fullF32Range()], - - 'unfiltered', - FP.f32.fractInterval - ); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - [ - 0.5, // 0.5 -> 0.5 - 0.9, // ~0.9 -> ~0.9 - 1, // 1 -> 0 - 2, // 2 -> 0 - 1.11, // ~1.11 -> ~0.11 - 10.0078125, // 10.0078125 -> 0.0078125 - -0.1, // ~-0.1 -> ~0.9 - -0.5, // -0.5 -> 0.5 - -0.9, // ~-0.9 -> ~0.1 - -1, // -1 -> 0 - -2, // -2 -> 0 - -1.11, // ~-1.11 -> ~0.89 - -10.0078125, // -10.0078125 -> 0.9921875 - 658.5, // 658.5 -> 0.5 - ...fullF16Range()], - - 'unfiltered', - FP.f16.fractInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('fract'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -85,7 +46,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('fract'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('fract'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -99,5 +60,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('fract'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('fract'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.cache.js new file mode 100644 index 0000000000..11d49dd040 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.cache.js @@ -0,0 +1,103 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { skipUndefined } from '../../../../../util/compare.js';import { + + i32, + toVector, + abstractInt } from +'../../../../../util/conversion.js'; +import { FP } from '../../../../../util/floating_point.js'; +import { frexp } from '../../../../../util/math.js'; + +import { makeCaseCache } from '../../case_cache.js'; + +/* @returns a fract Case for a given scalar or vector input */ +function makeCaseFract(v, trait) { + const fp = FP[trait]; + let toInput; + let toOutput; + if (v instanceof Array) { + // Input is vector + toInput = (n) => toVector(n, fp.scalarBuilder); + toOutput = (n) => toVector(n, fp.scalarBuilder); + } else { + // Input is scalar, also wrap it in an array. + v = [v]; + toInput = (n) => fp.scalarBuilder(n[0]); + toOutput = (n) => fp.scalarBuilder(n[0]); + } + + v = v.map(fp.quantize); + if (v.some((e) => e !== 0 && fp.isSubnormal(e))) { + return { input: toInput(v), expected: skipUndefined(undefined) }; + } + + const fs = v.map((e) => { + return frexp(e, trait !== 'abstract' ? trait : 'f64').fract; + }); + + return { input: toInput(v), expected: toOutput(fs) }; +} + +/* @returns an exp Case for a given scalar or vector input */ +function makeCaseExp(v, trait) { + const fp = FP[trait]; + let toInput; + let toOutput; + if (v instanceof Array) { + // Input is vector + toInput = (n) => toVector(n, fp.scalarBuilder); + toOutput = (n) => + toVector(n, trait !== 'abstract' ? i32 : (n) => abstractInt(BigInt(n))); + } else { + // Input is scalar, also wrap it in an array. + v = [v]; + toInput = (n) => fp.scalarBuilder(n[0]); + toOutput = (n) => + trait !== 'abstract' ? i32(n[0]) : abstractInt(BigInt(n[0])); + } + + v = v.map(fp.quantize); + if (v.some((e) => e !== 0 && fp.isSubnormal(e))) { + return { input: toInput(v), expected: skipUndefined(undefined) }; + } + + const fs = v.map((e) => { + return frexp(e, trait !== 'abstract' ? trait : 'f64').exp; + }); + + return { input: toInput(v), expected: toOutput(fs) }; +} + +// Cases: [f32|f16]_vecN_[exp|whole] +const vec_cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[2, 3, 4].flatMap((dim) => +['exp', 'fract'].map((portion) => ({ + [`${trait}_vec${dim}_${portion}`]: () => { + return FP[trait]. + vectorRange(dim). + map((v) => portion === 'exp' ? makeCaseExp(v, trait) : makeCaseFract(v, trait)); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: [f32|f16]_[exp|whole] +const scalar_cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +['exp', 'fract'].map((portion) => ({ + [`${trait}_${portion}`]: () => { + return FP[trait]. + scalarRange(). + map((v) => portion === 'exp' ? makeCaseExp(v, trait) : makeCaseFract(v, trait)); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('frexp', { + ...scalar_cases, + ...vec_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.spec.js index 962de5456e..b7877a4583 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.spec.js @@ -15,34 +15,19 @@ Returns the result_struct for the appropriate overload. The magnitude of the significand is in the range of [0.5, 1.0) or 0. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { skipUndefined } from '../../../../../util/compare.js'; +import { Type } from '../../../../../util/conversion.js'; import { - i32, - toVector, - TypeF32, - TypeF16, - TypeI32, - TypeVec } from - -'../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { - frexp, - fullF16Range, - fullF32Range, - vectorF16Range, - vectorF32Range } from -'../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, basicExpressionBuilder, - - run } from - + run, + abstractFloatShaderBuilder, + abstractIntShaderBuilder, + onlyConstInputSource } from '../../expression.js'; +import { d } from './frexp.cache.js'; + export const g = makeTestGroup(GPUTest); /* @returns an ShaderBuilder that evaluates frexp and returns .fract from the result structure */ @@ -55,111 +40,158 @@ function expBuilder() { return basicExpressionBuilder((value) => `frexp(${value}).exp`); } -/* @returns a fract Case for a given scalar or vector input */ -function makeVectorCaseFract(v, trait) { - const fp = FP[trait]; - let toInput; - let toOutput; - if (v instanceof Array) { - // Input is vector - toInput = (n) => toVector(n, fp.scalarBuilder); - toOutput = (n) => toVector(n, fp.scalarBuilder); - } else { - // Input is scalar, also wrap it in an array. - v = [v]; - toInput = (n) => fp.scalarBuilder(n[0]); - toOutput = (n) => fp.scalarBuilder(n[0]); - } - - v = v.map(fp.quantize); - if (v.some((e) => e !== 0 && fp.isSubnormal(e))) { - return { input: toInput(v), expected: skipUndefined(undefined) }; - } - - const fs = v.map((e) => { - return frexp(e, trait).fract; - }); - - return { input: toInput(v), expected: toOutput(fs) }; +/* @returns an ShaderBuilder that evaluates frexp and returns .fract from the result structure, for abstract inputs */ +function abstractFractBuilder() { + return abstractFloatShaderBuilder((value) => `frexp(${value}).fract`); +} + +/* @returns an ShaderBuilder that evaluates frexp and returns .exp from the result structure, for abstract inputs */ +function abstractExpBuilder() { + return abstractIntShaderBuilder((value) => `frexp(${value}).exp`); +} + +g.test('abstract_float_fract'). +specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). +desc( + ` +T is AbstractFloat + +struct __frexp_result_abstract { + fract : AbstractFloat, // fract part + exp : AbstractInt // exponent part +} +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_fract'); + await run(t, abstractFractBuilder(), [Type.abstractFloat], Type.abstractFloat, t.params, cases); +}); + +g.test('abstract_float_exp'). +specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). +desc( + ` +T is AbstractFloat + +struct __frexp_result_abstract { + fract : AbstractFloat, // fract part + exp : AbstractInt // exponent part +} +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_exp'); + await run(t, abstractExpBuilder(), [Type.abstractFloat], Type.abstractInt, t.params, cases); +}); + +g.test('abstract_float_vec2_fract'). +specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). +desc( + ` +T is vec2 + +struct __frexp_result_vec2_abstract { + fract : vec2, // fract part + exp : vec2 // exponent part +} +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec2_fract'); + await run(t, abstractFractBuilder(), [Type.vec2af], Type.vec2af, t.params, cases); +}); + +g.test('abstract_float_vec2_exp'). +specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). +desc( + ` +T is vec2 + +struct __frexp_result_vec2_abstract { + fract : vec2, // fractional part + exp : vec2 // exponent part +} +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec2_exp'); + await run(t, abstractExpBuilder(), [Type.vec2af], Type.vec2ai, t.params, cases); +}); + +g.test('abstract_float_vec3_fract'). +specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). +desc( + ` +T is vec3 + +struct __frexp_result_vec3_abstract { + fract : vec3, // fractional part + exp : vec3 // exponent part +} +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec3_fract'); + await run(t, abstractFractBuilder(), [Type.vec3af], Type.vec3af, t.params, cases); +}); + +g.test('abstract_float_vec3_exp'). +specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). +desc( + ` +T is vec3 + +struct __frexp_result_vec3_abstract { + fract : vec3, // fractional part + exp : vec3 // exponent part } +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec3_exp'); + await run(t, abstractExpBuilder(), [Type.vec3af], Type.vec3ai, t.params, cases); +}); -/* @returns an exp Case for a given scalar or vector input */ -function makeVectorCaseExp(v, trait) { - const fp = FP[trait]; - let toInput; - let toOutput; - if (v instanceof Array) { - // Input is vector - toInput = (n) => toVector(n, fp.scalarBuilder); - toOutput = (n) => toVector(n, i32); - } else { - // Input is scalar, also wrap it in an array. - v = [v]; - toInput = (n) => fp.scalarBuilder(n[0]); - toOutput = (n) => i32(n[0]); - } - - v = v.map(fp.quantize); - if (v.some((e) => e !== 0 && fp.isSubnormal(e))) { - return { input: toInput(v), expected: skipUndefined(undefined) }; - } - - const fs = v.map((e) => { - return frexp(e, trait).exp; - }); - - return { input: toInput(v), expected: toOutput(fs) }; +g.test('abstract_float_vec4_fract'). +specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). +desc( + ` +T is vec4 + +struct __frexp_result_vec4_abstract { + fract : vec4, // fractional part + exp : vec4 // exponent part } +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec4_fract'); + await run(t, abstractFractBuilder(), [Type.vec4af], Type.vec4af, t.params, cases); +}); + +g.test('abstract_float_vec4_exp'). +specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). +desc( + ` +T is vec4 -export const d = makeCaseCache('frexp', { - f32_fract: () => { - return fullF32Range().map((v) => makeVectorCaseFract(v, 'f32')); - }, - f32_exp: () => { - return fullF32Range().map((v) => makeVectorCaseExp(v, 'f32')); - }, - f32_vec2_fract: () => { - return vectorF32Range(2).map((v) => makeVectorCaseFract(v, 'f32')); - }, - f32_vec2_exp: () => { - return vectorF32Range(2).map((v) => makeVectorCaseExp(v, 'f32')); - }, - f32_vec3_fract: () => { - return vectorF32Range(3).map((v) => makeVectorCaseFract(v, 'f32')); - }, - f32_vec3_exp: () => { - return vectorF32Range(3).map((v) => makeVectorCaseExp(v, 'f32')); - }, - f32_vec4_fract: () => { - return vectorF32Range(4).map((v) => makeVectorCaseFract(v, 'f32')); - }, - f32_vec4_exp: () => { - return vectorF32Range(4).map((v) => makeVectorCaseExp(v, 'f32')); - }, - f16_fract: () => { - return fullF16Range().map((v) => makeVectorCaseFract(v, 'f16')); - }, - f16_exp: () => { - return fullF16Range().map((v) => makeVectorCaseExp(v, 'f16')); - }, - f16_vec2_fract: () => { - return vectorF16Range(2).map((v) => makeVectorCaseFract(v, 'f16')); - }, - f16_vec2_exp: () => { - return vectorF16Range(2).map((v) => makeVectorCaseExp(v, 'f16')); - }, - f16_vec3_fract: () => { - return vectorF16Range(3).map((v) => makeVectorCaseFract(v, 'f16')); - }, - f16_vec3_exp: () => { - return vectorF16Range(3).map((v) => makeVectorCaseExp(v, 'f16')); - }, - f16_vec4_fract: () => { - return vectorF16Range(4).map((v) => makeVectorCaseFract(v, 'f16')); - }, - f16_vec4_exp: () => { - return vectorF16Range(4).map((v) => makeVectorCaseExp(v, 'f16')); - } +struct __frexp_result_vec4_abstract { + fract : vec4, // fractional part + exp : vec4 // exponent part +} +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec4_exp'); + await run(t, abstractExpBuilder(), [Type.vec4af], Type.vec4ai, t.params, cases); }); g.test('f32_fract'). @@ -177,7 +209,7 @@ struct __frexp_result_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_fract'); - await run(t, fractBuilder(), [TypeF32], TypeF32, t.params, cases); + await run(t, fractBuilder(), [Type.f32], Type.f32, t.params, cases); }); g.test('f32_exp'). @@ -195,7 +227,7 @@ struct __frexp_result_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_exp'); - await run(t, expBuilder(), [TypeF32], TypeI32, t.params, cases); + await run(t, expBuilder(), [Type.f32], Type.i32, t.params, cases); }); g.test('f32_vec2_fract'). @@ -213,7 +245,7 @@ struct __frexp_result_vec2_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec2_fract'); - await run(t, fractBuilder(), [TypeVec(2, TypeF32)], TypeVec(2, TypeF32), t.params, cases); + await run(t, fractBuilder(), [Type.vec2f], Type.vec2f, t.params, cases); }); g.test('f32_vec2_exp'). @@ -231,7 +263,7 @@ struct __frexp_result_vec2_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec2_exp'); - await run(t, expBuilder(), [TypeVec(2, TypeF32)], TypeVec(2, TypeI32), t.params, cases); + await run(t, expBuilder(), [Type.vec2f], Type.vec2i, t.params, cases); }); g.test('f32_vec3_fract'). @@ -249,7 +281,7 @@ struct __frexp_result_vec3_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec3_fract'); - await run(t, fractBuilder(), [TypeVec(3, TypeF32)], TypeVec(3, TypeF32), t.params, cases); + await run(t, fractBuilder(), [Type.vec3f], Type.vec3f, t.params, cases); }); g.test('f32_vec3_exp'). @@ -267,7 +299,7 @@ struct __frexp_result_vec3_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec3_exp'); - await run(t, expBuilder(), [TypeVec(3, TypeF32)], TypeVec(3, TypeI32), t.params, cases); + await run(t, expBuilder(), [Type.vec3f], Type.vec3i, t.params, cases); }); g.test('f32_vec4_fract'). @@ -285,7 +317,7 @@ struct __frexp_result_vec4_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec4_fract'); - await run(t, fractBuilder(), [TypeVec(4, TypeF32)], TypeVec(4, TypeF32), t.params, cases); + await run(t, fractBuilder(), [Type.vec4f], Type.vec4f, t.params, cases); }); g.test('f32_vec4_exp'). @@ -303,7 +335,7 @@ struct __frexp_result_vec4_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec4_exp'); - await run(t, expBuilder(), [TypeVec(4, TypeF32)], TypeVec(4, TypeI32), t.params, cases); + await run(t, expBuilder(), [Type.vec4f], Type.vec4i, t.params, cases); }); g.test('f16_fract'). @@ -324,7 +356,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_fract'); - await run(t, fractBuilder(), [TypeF16], TypeF16, t.params, cases); + await run(t, fractBuilder(), [Type.f16], Type.f16, t.params, cases); }); g.test('f16_exp'). @@ -345,7 +377,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_exp'); - await run(t, expBuilder(), [TypeF16], TypeI32, t.params, cases); + await run(t, expBuilder(), [Type.f16], Type.i32, t.params, cases); }); g.test('f16_vec2_fract'). @@ -366,7 +398,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec2_fract'); - await run(t, fractBuilder(), [TypeVec(2, TypeF16)], TypeVec(2, TypeF16), t.params, cases); + await run(t, fractBuilder(), [Type.vec2h], Type.vec2h, t.params, cases); }); g.test('f16_vec2_exp'). @@ -387,7 +419,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec2_exp'); - await run(t, expBuilder(), [TypeVec(2, TypeF16)], TypeVec(2, TypeI32), t.params, cases); + await run(t, expBuilder(), [Type.vec2h], Type.vec2i, t.params, cases); }); g.test('f16_vec3_fract'). @@ -408,7 +440,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec3_fract'); - await run(t, fractBuilder(), [TypeVec(3, TypeF16)], TypeVec(3, TypeF16), t.params, cases); + await run(t, fractBuilder(), [Type.vec3h], Type.vec3h, t.params, cases); }); g.test('f16_vec3_exp'). @@ -429,7 +461,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec3_exp'); - await run(t, expBuilder(), [TypeVec(3, TypeF16)], TypeVec(3, TypeI32), t.params, cases); + await run(t, expBuilder(), [Type.vec3h], Type.vec3i, t.params, cases); }); g.test('f16_vec4_fract'). @@ -450,7 +482,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec4_fract'); - await run(t, fractBuilder(), [TypeVec(4, TypeF16)], TypeVec(4, TypeF16), t.params, cases); + await run(t, fractBuilder(), [Type.vec4h], Type.vec4h, t.params, cases); }); g.test('f16_vec4_exp'). @@ -471,5 +503,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec4_exp'); - await run(t, expBuilder(), [TypeVec(4, TypeF16)], TypeVec(4, TypeI32), t.params, cases); + await run(t, expBuilder(), [Type.vec4h], Type.vec4i, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/insertBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/insertBits.spec.js index 1af24a5189..5a0a8182d6 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/insertBits.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/insertBits.spec.js @@ -18,17 +18,7 @@ Other bits of the result are copied from e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { - i32Bits, - TypeI32, - u32, - TypeU32, - u32Bits, - vec2, - vec3, - vec4, - TypeVec } from -'../../../../../util/conversion.js'; +import { i32Bits, Type, u32, u32Bits, vec2, vec3, vec4 } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -46,8 +36,8 @@ combine('width', [1, 2, 3, 4]) ). fn(async (t) => { const cfg = t.params; - const scalarType = t.params.signed ? TypeI32 : TypeU32; - const T = t.params.width === 1 ? scalarType : TypeVec(t.params.width, scalarType); + const scalarType = t.params.signed ? Type.i32 : Type.u32; + const T = t.params.width === 1 ? scalarType : Type.vec(t.params.width, scalarType); const V = (x, y, z, w) => { y = y === undefined ? x : y; @@ -382,5 +372,5 @@ fn(async (t) => { ); } - await run(t, builtin('insertBits'), [T, T, TypeU32, TypeU32], T, cfg, cases); + await run(t, builtin('insertBits'), [T, T, Type.u32, Type.u32], T, cfg, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.cache.js new file mode 100644 index 0000000000..883dc14c08 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.cache.js @@ -0,0 +1,44 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kValue } from '../../../../../util/constants.js';import { FP } from '../../../../../util/floating_point.js';import { biasedRange, linearRange } from '../../../../../util/math.js'; +import { makeCaseCache } from '../../case_cache.js'; + +export const d = makeCaseCache('inverseSqrt', { + f32: () => { + return FP.f32.generateScalarToIntervalCases( + [ + // 0 < x <= 1 linearly spread + ...linearRange(kValue.f32.positive.min, 1, 100), + // 1 <= x < 2^32, biased towards 1 + ...biasedRange(1, 2 ** 32, 1000)], + + 'unfiltered', + FP.f32.inverseSqrtInterval + ); + }, + f16: () => { + return FP.f16.generateScalarToIntervalCases( + [ + // 0 < x <= 1 linearly spread + ...linearRange(kValue.f16.positive.min, 1, 100), + // 1 <= x < 2^15, biased towards 1 + ...biasedRange(1, 2 ** 15, 1000)], + + 'unfiltered', + FP.f16.inverseSqrtInterval + ); + }, + abstract: () => { + return FP.abstract.generateScalarToIntervalCases( + [ + // 0 < x <= 1 linearly spread + ...linearRange(kValue.f64.positive.min, 1, 100), + // 1 <= x < 2^64, biased towards 1, only using 100 steps, because af tests are more expensive per case + ...biasedRange(1, 2 ** 64, 100)], + + 'finite', + // inverseSqrt has an ulp accuracy, so is only expected to be as accurate as f32 + FP.f32.inverseSqrtInterval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.spec.js index c24121c716..d22daed907 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.spec.js @@ -3,57 +3,39 @@ **/export const description = ` Execution tests for the 'inverseSqrt' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn inverseSqrt(e: T ) -> T Returns the reciprocal of sqrt(e). Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { kValue } from '../../../../../util/constants.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { biasedRange, linearRange } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './inversesqrt.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('inverseSqrt', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - [ - // 0 < x <= 1 linearly spread - ...linearRange(kValue.f32.positive.min, 1, 100), - // 1 <= x < 2^32, biased towards 1 - ...biasedRange(1, 2 ** 32, 1000)], - - 'unfiltered', - FP.f32.inverseSqrtInterval - ); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - [ - // 0 < x <= 1 linearly spread - ...linearRange(kValue.f16.positive.min, 1, 100), - // 1 <= x < 2^15, biased towards 1 - ...biasedRange(1, 2 ** 15, 1000)], - - 'unfiltered', - FP.f16.inverseSqrtInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('inverseSqrt'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -63,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('inverseSqrt'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('inverseSqrt'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -77,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('inverseSqrt'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('inverseSqrt'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.cache.js new file mode 100644 index 0000000000..bacdae0349 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.cache.js @@ -0,0 +1,61 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert } from '../../../../../../common/util/util.js';import { anyOf } from '../../../../../util/compare.js';import { abstractInt, i32 } from '../../../../../util/conversion.js'; +import { FP } from '../../../../../util/floating_point.js'; +import { biasedRange, quantizeToI32, sparseI32Range } from '../../../../../util/math.js'; + +import { makeCaseCache } from '../../case_cache.js'; + +// ldexpInterval's return interval doesn't cover the flush-to-zero cases when e2 + bias <= 0, thus +// special examination is required. +// See the comment block on ldexpInterval for more details +// e2 is an integer (i32) while e1 is float. +const makeCase = (trait, e1, e2) => { + const FPTrait = FP[trait]; + e1 = FPTrait.quantize(e1); + // e2 should be in i32 range for the convenience. + assert(-2147483648 <= e2 && e2 <= 2147483647, 'e2 should be in i32 range'); + e2 = quantizeToI32(e2); + + const expected = FPTrait.ldexpInterval(e1, e2); + + const e2_scalar = trait === 'abstract' ? abstractInt(BigInt(e2)) : i32(e2); + // Result may be zero if e2 + bias <= 0 + if (e2 + FPTrait.constants().bias <= 0) { + return { + input: [FPTrait.scalarBuilder(e1), e2_scalar], + expected: anyOf(expected, FPTrait.constants().zeroInterval) + }; + } + + return { input: [FPTrait.scalarBuilder(e1), e2_scalar], expected }; +}; + +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (nonConst) { + if (trait === 'abstract') { + return []; + } + return FP[trait]. + sparseScalarRange(). + flatMap((e1) => sparseI32Range().map((e2) => makeCase(trait, e1, e2))); + } + const bias = FP[trait].constants().bias; + // const + return FP[trait]. + sparseScalarRange(). + flatMap((e1) => + biasedRange(-bias - 10, bias + 1, 10).flatMap((e2) => + FP[trait].isFinite(e1 * 2 ** quantizeToI32(e2)) ? makeCase(trait, e1, e2) : [] + ) + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('ldexp', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.spec.js index a91e9d73ff..99bb09d176 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.spec.js @@ -3,87 +3,25 @@ **/export const description = ` Execution tests for the 'ldexp' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN -K is AbstractInt, i32 +K is Type.abstractInt, i32 I is K or vecN, where I is a scalar if T is a scalar, or a vector when T is a vector @const fn ldexp(e1: T ,e2: I ) -> T Returns e1 * 2^e2. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; -import { assert } from '../../../../../../common/util/util.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { anyOf } from '../../../../../util/compare.js'; -import { i32, TypeF32, TypeF16, TypeI32 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { - biasedRange, - quantizeToI32, - sparseF32Range, - sparseI32Range, - sparseF16Range } from -'../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './ldexp.cache.js'; export const g = makeTestGroup(GPUTest); -const bias = { - f32: 127, - f16: 15 -}; - -// ldexpInterval's return interval doesn't cover the flush-to-zero cases when e2 + bias <= 0, thus -// special examination is required. -// See the comment block on ldexpInterval for more details -// e2 is an integer (i32) while e1 is float. -const makeCase = (trait, e1, e2) => { - const FPTrait = FP[trait]; - e1 = FPTrait.quantize(e1); - // e2 should be in i32 range for the convinience. - assert(-2147483648 <= e2 && e2 <= 2147483647, 'e2 should be in i32 range'); - e2 = quantizeToI32(e2); - - const expected = FPTrait.ldexpInterval(e1, e2); - - // Result may be zero if e2 + bias <= 0 - if (e2 + bias[trait] <= 0) { - return { - input: [FPTrait.scalarBuilder(e1), i32(e2)], - expected: anyOf(expected, FPTrait.constants().zeroInterval) - }; - } - - return { input: [FPTrait.scalarBuilder(e1), i32(e2)], expected }; -}; - -export const d = makeCaseCache('ldexp', { - f32_non_const: () => { - return sparseF32Range().flatMap((e1) => sparseI32Range().map((e2) => makeCase('f32', e1, e2))); - }, - f32_const: () => { - return sparseF32Range().flatMap((e1) => - biasedRange(-bias.f32 - 10, bias.f32 + 1, 10).flatMap((e2) => - FP.f32.isFinite(e1 * 2 ** quantizeToI32(e2)) ? makeCase('f32', e1, e2) : [] - ) - ); - }, - f16_non_const: () => { - return sparseF16Range().flatMap((e1) => sparseI32Range().map((e2) => makeCase('f16', e1, e2))); - }, - f16_const: () => { - return sparseF16Range().flatMap((e1) => - biasedRange(-bias.f16 - 10, bias.f16 + 1, 10).flatMap((e2) => - FP.f16.isFinite(e1 * 2 ** quantizeToI32(e2)) ? makeCase('f16', e1, e2) : [] - ) - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc( @@ -91,9 +29,21 @@ desc( ` ). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('ldexp'), + [Type.abstractFloat, Type.abstractInt], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -103,7 +53,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('ldexp'), [TypeF32, TypeI32], TypeF32, t.params, cases); + await run(t, builtin('ldexp'), [Type.f32, Type.i32], Type.f32, t.params, cases); }); g.test('f16'). @@ -117,5 +67,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('ldexp'), [TypeF16, TypeI32], TypeF16, t.params, cases); + await run(t, builtin('ldexp'), [Type.f16, Type.i32], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.cache.js new file mode 100644 index 0000000000..18c15dec5d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.cache.js @@ -0,0 +1,42 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_[non_]const +const scalar_cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + trait !== 'abstract' ? 'unfiltered' : 'finite', + // length has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].lengthInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: [f32|f16|abstract]_vecN_[non_]const +const vec_cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[2, 3, 4].flatMap((dim) => +[true, false].map((nonConst) => ({ + [`${trait}_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateVectorToIntervalCases( + FP[trait].vectorRange(dim), + nonConst ? 'unfiltered' : 'finite', + // length has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].lengthInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('length', { + ...scalar_cases, + ...vec_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.spec.js index fa42f7e504..9aa959e086 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.spec.js @@ -3,83 +3,83 @@ **/export const description = ` Execution tests for the 'length' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn length(e: T ) -> f32 Returns the length of e (e.g. abs(e) if T is a scalar, or sqrt(e[0]^2 + e[1]^2 + ...) if T is a vector). `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { - fullF32Range, - fullF16Range, - vectorF32Range, - vectorF16Range } from -'../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './length.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: f32_vecN_[non_]const -const f32_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f32_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorToIntervalCases( - vectorF32Range(n), - nonConst ? 'unfiltered' : 'finite', - FP.f32.lengthInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); +g.test('abstract_float'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract_float tests`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('length'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); -// Cases: f16_vecN_[non_]const -const f16_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f16_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorToIntervalCases( - vectorF16Range(n), - nonConst ? 'unfiltered' : 'finite', - FP.f16.lengthInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); +g.test('abstract_float_vec2'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec2s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec2_const'); + await run( + t, + abstractFloatBuiltin('length'), + [Type.vec2af], + Type.abstractFloat, + t.params, + cases + ); +}); -export const d = makeCaseCache('length', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - fullF32Range(), - 'unfiltered', - FP.f32.lengthInterval - ); - }, - ...f32_vec_cases, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - fullF16Range(), - 'unfiltered', - FP.f16.lengthInterval - ); - }, - ...f16_vec_cases +g.test('abstract_float_vec3'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract_float tests using vec3s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec3_const'); + await run( + t, + abstractFloatBuiltin('length'), + [Type.vec3af], + Type.abstractFloat, + t.params, + cases + ); }); -g.test('abstract_float'). +g.test('abstract_float_vec4'). specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). -desc(`abstract float tests`). -params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) -). -unimplemented(); +desc(`abstract_float tests using vec4s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec4_const'); + await run( + t, + abstractFloatBuiltin('length'), + [Type.vec4af], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). @@ -87,7 +87,7 @@ desc(`f32 tests`). params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('length'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('length'), [Type.f32], Type.f32, t.params, cases); }); g.test('f32_vec2'). @@ -98,7 +98,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const' ); - await run(t, builtin('length'), [TypeVec(2, TypeF32)], TypeF32, t.params, cases); + await run(t, builtin('length'), [Type.vec2f], Type.f32, t.params, cases); }); g.test('f32_vec3'). @@ -109,7 +109,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const' ); - await run(t, builtin('length'), [TypeVec(3, TypeF32)], TypeF32, t.params, cases); + await run(t, builtin('length'), [Type.vec3f], Type.f32, t.params, cases); }); g.test('f32_vec4'). @@ -120,7 +120,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const' ); - await run(t, builtin('length'), [TypeVec(4, TypeF32)], TypeF32, t.params, cases); + await run(t, builtin('length'), [Type.vec4f], Type.f32, t.params, cases); }); g.test('f16'). @@ -132,7 +132,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('length'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('length'), [Type.f16], Type.f16, t.params, cases); }); g.test('f16_vec2'). @@ -146,7 +146,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec2_const' : 'f16_vec2_non_const' ); - await run(t, builtin('length'), [TypeVec(2, TypeF16)], TypeF16, t.params, cases); + await run(t, builtin('length'), [Type.vec2h], Type.f16, t.params, cases); }); g.test('f16_vec3'). @@ -160,7 +160,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec3_const' : 'f16_vec3_non_const' ); - await run(t, builtin('length'), [TypeVec(3, TypeF16)], TypeF16, t.params, cases); + await run(t, builtin('length'), [Type.vec3h], Type.f16, t.params, cases); }); g.test('f16_vec4'). @@ -174,5 +174,5 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec4_const' : 'f16_vec4_non_const' ); - await run(t, builtin('length'), [TypeVec(4, TypeF16)], TypeF16, t.params, cases); + await run(t, builtin('length'), [Type.vec4h], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.cache.js new file mode 100644 index 0000000000..b984c1f30a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.cache.js @@ -0,0 +1,30 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { biasedRange, linearRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// log's accuracy is defined in three regions { [0, 0.5), [0.5, 2.0], (2.0, +∞] } +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + [ + ...linearRange(FP[trait].constants().positive.min, 0.5, 20), + ...linearRange(0.5, 2.0, 20), + ...biasedRange(2.0, 2 ** 32, 1000), + ...FP[trait].scalarRange()], + + nonConst ? 'unfiltered' : 'finite', + // log has an absolute or ulp accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].logInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('log', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.spec.js index 5135d0ec02..e828fabdbe 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.spec.js @@ -3,59 +3,39 @@ **/export const description = ` Execution tests for the 'log' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn log(e: T ) -> T Returns the natural logarithm of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { kValue } from '../../../../../util/constants.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { biasedRange, fullF32Range, fullF16Range, linearRange } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './log.cache.js'; export const g = makeTestGroup(GPUTest); -// log's accuracy is defined in three regions { [0, 0.5), [0.5, 2.0], (2.0, +∞] } -const f32_inputs = [ -...linearRange(kValue.f32.positive.min, 0.5, 20), -...linearRange(0.5, 2.0, 20), -...biasedRange(2.0, 2 ** 32, 1000), -...fullF32Range()]; - -const f16_inputs = [ -...linearRange(kValue.f16.positive.min, 0.5, 20), -...linearRange(0.5, 2.0, 20), -...biasedRange(2.0, 2 ** 32, 1000), -...fullF16Range()]; - - -export const d = makeCaseCache('log', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.logInterval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', FP.f32.logInterval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', FP.f16.logInterval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', FP.f16.logInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('log'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -71,7 +51,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('log'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('log'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -85,5 +65,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('log'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('log'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.cache.js new file mode 100644 index 0000000000..1ed1f82474 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.cache.js @@ -0,0 +1,30 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { biasedRange, linearRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// log2's accuracy is defined in three regions { [0, 0.5), [0.5, 2.0], (2.0, +∞] } +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + [ + ...linearRange(FP[trait].constants().positive.min, 0.5, 20), + ...linearRange(0.5, 2.0, 20), + ...biasedRange(2.0, 2 ** 32, 1000), + ...FP[trait].scalarRange()], + + nonConst ? 'unfiltered' : 'finite', + // log2 has an absolute or ulp accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].log2Interval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('log2', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.spec.js index c63b2c4224..df280e5965 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.spec.js @@ -3,59 +3,39 @@ **/export const description = ` Execution tests for the 'log2' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn log2(e: T ) -> T Returns the base-2 logarithm of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { kValue } from '../../../../../util/constants.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { biasedRange, fullF32Range, fullF16Range, linearRange } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './log2.cache.js'; export const g = makeTestGroup(GPUTest); -// log2's accuracy is defined in three regions { [0, 0.5), [0.5, 2.0], (2.0, +∞] } -const f32_inputs = [ -...linearRange(kValue.f32.positive.min, 0.5, 20), -...linearRange(0.5, 2.0, 20), -...biasedRange(2.0, 2 ** 32, 1000), -...fullF32Range()]; - -const f16_inputs = [ -...linearRange(kValue.f16.positive.min, 0.5, 20), -...linearRange(0.5, 2.0, 20), -...biasedRange(2.0, 2 ** 32, 1000), -...fullF16Range()]; - - -export const d = makeCaseCache('log2', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'finite', FP.f32.log2Interval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(f32_inputs, 'unfiltered', FP.f32.log2Interval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'finite', FP.f16.log2Interval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(f16_inputs, 'unfiltered', FP.f16.log2Interval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('log2'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -71,7 +51,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('log2'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('log2'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -85,5 +65,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('log2'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('log2'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.cache.js new file mode 100644 index 0000000000..8644a569ac --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.cache.js @@ -0,0 +1,18 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarPairToIntervalCases( + FP[trait].sparseScalarRange(), + FP[trait].sparseScalarRange(), + 'unfiltered', + FP[trait].maxInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('max', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.spec.js index 53abc03c33..a605553a4a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.spec.js @@ -3,12 +3,12 @@ **/export const description = ` Execution tests for the 'max' builtin function -S is AbstractInt, i32, or u32 +S is abstract-int, i32, or u32 T is S or vecN @const fn max(e1: T ,e2: T) -> T Returns e2 if e1 is less than e2, and e1 otherwise. Component-wise when T is a vector. -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is vecN @const fn max(e1: T ,e2: T) -> T Returns e2 if e1 is less than e2, and e1 otherwise. @@ -18,72 +18,50 @@ Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { - i32, - TypeF32, - TypeF16, - TypeI32, - TypeU32, - u32, - TypeAbstractFloat } from -'../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range, sparseF64Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type, i32, u32, abstractInt } from '../../../../../util/conversion.js'; +import { maxBigInt } from '../../../../../util/math.js'; + import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, abstractIntBuiltin, builtin } from './builtin.js'; +import { d } from './max.cache.js'; /** Generate set of max test cases from list of interesting values */ -function generateTestCases( -values, -makeCase) -{ - const cases = new Array(); - values.forEach((e) => { - values.forEach((f) => { - cases.push(makeCase(e, f)); +function generateTestCases(values, makeCase) { + return values.flatMap((e) => { + return values.map((f) => { + return makeCase(e, f); }); }); - return cases; } export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('max', { - f32: () => { - return FP.f32.generateScalarPairToIntervalCases( - fullF32Range(), - fullF32Range(), - 'unfiltered', - FP.f32.maxInterval - ); - }, - f16: () => { - return FP.f16.generateScalarPairToIntervalCases( - fullF16Range(), - fullF16Range(), - 'unfiltered', - FP.f16.maxInterval - ); - }, - abstract: () => { - return FP.abstract.generateScalarPairToIntervalCases( - sparseF64Range(), - sparseF64Range(), - 'unfiltered', - FP.abstract.maxInterval - ); - } -}); - g.test('abstract_int'). specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions'). desc(`abstract int tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const makeCase = (x, y) => { + return { input: [abstractInt(x), abstractInt(y)], expected: abstractInt(maxBigInt(x, y)) }; + }; + + const test_values = [-0x70000000n, -2n, -1n, 0n, 1n, 2n, 0x70000000n]; + const cases = generateTestCases(test_values, makeCase); + + await run( + t, + abstractIntBuiltin('max'), + [Type.abstractInt, Type.abstractInt], + Type.abstractInt, + t.params, + cases + ); +}); g.test('u32'). specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions'). @@ -99,7 +77,7 @@ fn(async (t) => { const test_values = [0, 1, 2, 0x70000000, 0x80000000, 0xffffffff]; const cases = generateTestCases(test_values, makeCase); - await run(t, builtin('max'), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, builtin('max'), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('i32'). @@ -116,7 +94,7 @@ fn(async (t) => { const test_values = [-0x70000000, -2, -1, 0, 1, 2, 0x70000000]; const cases = generateTestCases(test_values, makeCase); - await run(t, builtin('max'), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, builtin('max'), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('abstract_float'). @@ -131,9 +109,9 @@ fn(async (t) => { const cases = await d.get('abstract'); await run( t, - abstractBuiltin('max'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBuiltin('max'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -147,7 +125,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('max'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, builtin('max'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -161,5 +139,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('max'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, builtin('max'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.cache.js new file mode 100644 index 0000000000..482502e390 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.cache.js @@ -0,0 +1,18 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarPairToIntervalCases( + FP[trait].sparseScalarRange(), + FP[trait].sparseScalarRange(), + 'unfiltered', + FP[trait].minInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('min', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.spec.js index 0b1bc58c3e..05bd9dd0e4 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.spec.js @@ -3,12 +3,12 @@ **/export const description = ` Execution tests for the 'min' builtin function -S is AbstractInt, i32, or u32 +S is abstract-int, i32, or u32 T is S or vecN @const fn min(e1: T ,e2: T) -> T Returns e1 if e1 is less than e2, and e2 otherwise. Component-wise when T is a vector. -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn min(e1: T ,e2: T) -> T Returns e2 if e2 is less than e1, and e1 otherwise. @@ -17,72 +17,50 @@ If both operands are NaNs, a NaN is returned. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { - i32, - TypeF32, - TypeF16, - TypeI32, - TypeU32, - u32, - TypeAbstractFloat } from -'../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range, sparseF64Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type, i32, u32, abstractInt } from '../../../../../util/conversion.js'; +import { minBigInt } from '../../../../../util/math.js'; + import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, abstractIntBuiltin, builtin } from './builtin.js'; +import { d } from './min.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('min', { - f32: () => { - return FP.f32.generateScalarPairToIntervalCases( - fullF32Range(), - fullF32Range(), - 'unfiltered', - FP.f32.minInterval - ); - }, - f16: () => { - return FP.f16.generateScalarPairToIntervalCases( - fullF16Range(), - fullF16Range(), - 'unfiltered', - FP.f16.minInterval - ); - }, - abstract: () => { - return FP.abstract.generateScalarPairToIntervalCases( - sparseF64Range(), - sparseF64Range(), - 'unfiltered', - FP.abstract.minInterval - ); - } -}); - /** Generate set of min test cases from list of interesting values */ -function generateTestCases( -values, -makeCase) -{ - const cases = new Array(); - values.forEach((e) => { - values.forEach((f) => { - cases.push(makeCase(e, f)); +function generateTestCases(values, makeCase) { + return values.flatMap((e) => { + return values.map((f) => { + return makeCase(e, f); }); }); - return cases; } g.test('abstract_int'). specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions'). desc(`abstract int tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const makeCase = (x, y) => { + return { input: [abstractInt(x), abstractInt(y)], expected: abstractInt(minBigInt(x, y)) }; + }; + + const test_values = [-0x70000000n, -2n, -1n, 0n, 1n, 2n, 0x70000000n]; + const cases = generateTestCases(test_values, makeCase); + + await run( + t, + abstractIntBuiltin('min'), + [Type.abstractInt, Type.abstractInt], + Type.abstractInt, + t.params, + cases + ); +}); g.test('u32'). specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions'). @@ -98,7 +76,7 @@ fn(async (t) => { const test_values = [0, 1, 2, 0x70000000, 0x80000000, 0xffffffff]; const cases = generateTestCases(test_values, makeCase); - await run(t, builtin('min'), [TypeU32, TypeU32], TypeU32, t.params, cases); + await run(t, builtin('min'), [Type.u32, Type.u32], Type.u32, t.params, cases); }); g.test('i32'). @@ -115,7 +93,7 @@ fn(async (t) => { const test_values = [-0x70000000, -2, -1, 0, 1, 2, 0x70000000]; const cases = generateTestCases(test_values, makeCase); - await run(t, builtin('min'), [TypeI32, TypeI32], TypeI32, t.params, cases); + await run(t, builtin('min'), [Type.i32, Type.i32], Type.i32, t.params, cases); }); g.test('abstract_float'). @@ -130,9 +108,9 @@ fn(async (t) => { const cases = await d.get('abstract'); await run( t, - abstractBuiltin('min'), - [TypeAbstractFloat, TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBuiltin('min'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -146,7 +124,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('min'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, builtin('min'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -160,5 +138,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('min'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, builtin('min'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.cache.js new file mode 100644 index 0000000000..ac1d4cf573 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.cache.js @@ -0,0 +1,56 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { selectNCases } from '../../case.js';import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract]_[non_]const +// abstract_non_const is empty and unused +const scalar_cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + const cases = FP[trait].generateScalarTripleToIntervalCases( + FP[trait].sparseScalarRange(), + FP[trait].sparseScalarRange(), + FP[trait].sparseScalarRange(), + nonConst ? 'unfiltered' : 'finite', + // mix has an inherited accuracy, so abstract is only expected to be as accurate as f32 + ...FP[trait !== 'abstract' ? trait : 'f32'].mixIntervals + ); + return selectNCases('mix_scalar', trait === 'abstract' ? 50 : cases.length, cases); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: [f32|f16]_vecN_scalar_[non_]const +// abstract_vecN_non_const is empty and unused +const vec_scalar_cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[2, 3, 4].flatMap((dim) => +[true, false].map((nonConst) => ({ + [`${trait}_vec${dim}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + const cases = FP[trait].generateVectorPairScalarToVectorComponentWiseCase( + FP[trait].sparseVectorRange(dim), + FP[trait].sparseVectorRange(dim), + FP[trait].sparseScalarRange(), + nonConst ? 'unfiltered' : 'finite', + // mix has an inherited accuracy, so abstract is only expected to be as accurate as f32 + ...FP[trait !== 'abstract' ? trait : 'f32'].mixIntervals + ); + return selectNCases('mix_vector', trait === 'abstract' ? 50 : cases.length, cases); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('mix', { + ...scalar_cases, + ...vec_scalar_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.spec.js index 4466ecd8a7..a118c24978 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.spec.js @@ -3,12 +3,12 @@ **/export const description = ` Execution tests for the 'mix' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn mix(e1: T, e2: T, e3: T) -> T Returns the linear blend of e1 and e2 (e.g. e1*(1-e3)+e2*e3). Component-wise when T is a vector. -T is AbstractFloat, f32, or f16 +T is abstract-float, f32, or f16 T2 is vecN @const fn mix(e1: T2, e2: T2, e3: T) -> T2 Returns the component-wise linear blend of e1 and e2, using scalar blending factor e3 for each component. @@ -16,121 +16,81 @@ Same as mix(e1,e2,T2(e3)). `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeVec, TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { - sparseF32Range, - sparseF16Range, - sparseVectorF32Range, - sparseVectorF16Range } from -'../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './mix.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: f32_vecN_scalar_[non_]const -const f32_vec_scalar_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f32_vec${n}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorPairScalarToVectorComponentWiseCase( - sparseVectorF32Range(n), - sparseVectorF32Range(n), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite', - ...FP.f32.mixIntervals - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: f16_vecN_scalar_[non_]const -const f16_vec_scalar_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f16_vec${n}_scalar_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorPairScalarToVectorComponentWiseCase( - sparseVectorF16Range(n), - sparseVectorF16Range(n), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite', - ...FP.f16.mixIntervals - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('mix', { - f32_const: () => { - return FP.f32.generateScalarTripleToIntervalCases( - sparseF32Range(), - sparseF32Range(), - sparseF32Range(), - 'finite', - ...FP.f32.mixIntervals - ); - }, - f32_non_const: () => { - return FP.f32.generateScalarTripleToIntervalCases( - sparseF32Range(), - sparseF32Range(), - sparseF32Range(), - 'unfiltered', - ...FP.f32.mixIntervals - ); - }, - ...f32_vec_scalar_cases, - f16_const: () => { - return FP.f16.generateScalarTripleToIntervalCases( - sparseF16Range(), - sparseF16Range(), - sparseF16Range(), - 'finite', - ...FP.f16.mixIntervals - ); - }, - f16_non_const: () => { - return FP.f16.generateScalarTripleToIntervalCases( - sparseF16Range(), - sparseF16Range(), - sparseF16Range(), - 'unfiltered', - ...FP.f16.mixIntervals - ); - }, - ...f16_vec_scalar_cases -}); - g.test('abstract_float_matching'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract_float test with matching third param`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('mix'), + [Type.abstractFloat, Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('abstract_float_nonmatching_vec2'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract_float tests with two vec2 params and scalar third param`). -params((u) => u.combine('inputSource', allInputSources)). -unimplemented(); +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec2_scalar_const'); + await run( + t, + abstractFloatBuiltin('mix'), + [Type.vec(2, Type.abstractFloat), Type.vec(2, Type.abstractFloat), Type.abstractFloat], + Type.vec(2, Type.abstractFloat), + t.params, + cases + ); +}); g.test('abstract_float_nonmatching_vec3'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract_float tests with two vec3 params and scalar third param`). -params((u) => u.combine('inputSource', allInputSources)). -unimplemented(); +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec3_scalar_const'); + await run( + t, + abstractFloatBuiltin('mix'), + [Type.vec(3, Type.abstractFloat), Type.vec(3, Type.abstractFloat), Type.abstractFloat], + Type.vec(3, Type.abstractFloat), + t.params, + cases + ); +}); g.test('abstract_float_nonmatching_vec4'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract_float tests with two vec4 params and scalar third param`). -params((u) => u.combine('inputSource', allInputSources)). -unimplemented(); +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec4_scalar_const'); + await run( + t, + abstractFloatBuiltin('mix'), + [Type.vec(4, Type.abstractFloat), Type.vec(4, Type.abstractFloat), Type.abstractFloat], + Type.vec(4, Type.abstractFloat), + t.params, + cases + ); +}); g.test('f32_matching'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -140,7 +100,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('mix'), [TypeF32, TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, builtin('mix'), [Type.f32, Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('f32_nonmatching_vec2'). @@ -151,14 +111,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec2_scalar_const' : 'f32_vec2_scalar_non_const' ); - await run( - t, - builtin('mix'), - [TypeVec(2, TypeF32), TypeVec(2, TypeF32), TypeF32], - TypeVec(2, TypeF32), - t.params, - cases - ); + await run(t, builtin('mix'), [Type.vec2f, Type.vec2f, Type.f32], Type.vec2f, t.params, cases); }); g.test('f32_nonmatching_vec3'). @@ -169,14 +122,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec3_scalar_const' : 'f32_vec3_scalar_non_const' ); - await run( - t, - builtin('mix'), - [TypeVec(3, TypeF32), TypeVec(3, TypeF32), TypeF32], - TypeVec(3, TypeF32), - t.params, - cases - ); + await run(t, builtin('mix'), [Type.vec3f, Type.vec3f, Type.f32], Type.vec3f, t.params, cases); }); g.test('f32_nonmatching_vec4'). @@ -187,14 +133,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec4_scalar_const' : 'f32_vec4_scalar_non_const' ); - await run( - t, - builtin('mix'), - [TypeVec(4, TypeF32), TypeVec(4, TypeF32), TypeF32], - TypeVec(4, TypeF32), - t.params, - cases - ); + await run(t, builtin('mix'), [Type.vec4f, Type.vec4f, Type.f32], Type.vec4f, t.params, cases); }); g.test('f16_matching'). @@ -208,7 +147,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('mix'), [TypeF16, TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, builtin('mix'), [Type.f16, Type.f16, Type.f16], Type.f16, t.params, cases); }); g.test('f16_nonmatching_vec2'). @@ -222,14 +161,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec2_scalar_const' : 'f16_vec2_scalar_non_const' ); - await run( - t, - builtin('mix'), - [TypeVec(2, TypeF16), TypeVec(2, TypeF16), TypeF16], - TypeVec(2, TypeF16), - t.params, - cases - ); + await run(t, builtin('mix'), [Type.vec2h, Type.vec2h, Type.f16], Type.vec2h, t.params, cases); }); g.test('f16_nonmatching_vec3'). @@ -243,14 +175,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec3_scalar_const' : 'f16_vec3_scalar_non_const' ); - await run( - t, - builtin('mix'), - [TypeVec(3, TypeF16), TypeVec(3, TypeF16), TypeF16], - TypeVec(3, TypeF16), - t.params, - cases - ); + await run(t, builtin('mix'), [Type.vec3h, Type.vec3h, Type.f16], Type.vec3h, t.params, cases); }); g.test('f16_nonmatching_vec4'). @@ -264,12 +189,5 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec4_scalar_const' : 'f16_vec4_scalar_non_const' ); - await run( - t, - builtin('mix'), - [TypeVec(4, TypeF16), TypeVec(4, TypeF16), TypeF16], - TypeVec(4, TypeF16), - t.params, - cases - ); + await run(t, builtin('mix'), [Type.vec4h, Type.vec4h, Type.f16], Type.vec4h, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.cache.js new file mode 100644 index 0000000000..63f90ec346 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.cache.js @@ -0,0 +1,75 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { toVector } from '../../../../../util/conversion.js';import { FP } from '../../../../../util/floating_point.js'; +import { makeCaseCache } from '../../case_cache.js'; + +/** @returns a fract Case for a scalar vector input */ +function makeScalarCaseFract(kind, n) { + const fp = FP[kind]; + n = fp.quantize(n); + const result = fp.modfInterval(n).fract; + + return { input: fp.scalarBuilder(n), expected: result }; +} + +/** @returns a whole Case for a scalar vector input */ +function makeScalarCaseWhole(kind, n) { + const fp = FP[kind]; + n = fp.quantize(n); + const result = fp.modfInterval(n).whole; + + return { input: fp.scalarBuilder(n), expected: result }; +} + +/** @returns a fract Case for a given vector input */ +function makeVectorCaseFract(kind, v) { + const fp = FP[kind]; + v = v.map(fp.quantize); + const fs = v.map((e) => { + return fp.modfInterval(e).fract; + }); + + return { input: toVector(v, fp.scalarBuilder), expected: fs }; +} + +/** @returns a whole Case for a given vector input */ +function makeVectorCaseWhole(kind, v) { + const fp = FP[kind]; + v = v.map(fp.quantize); + const ws = v.map((e) => { + return fp.modfInterval(e).whole; + }); + + return { input: toVector(v, fp.scalarBuilder), expected: ws }; +} + +// Cases: [f32|f16|abstract]_[fract|whole] +const scalar_cases = ['f32', 'f16', 'abstract']. +flatMap((kind) => +['whole', 'fract'].map((portion) => ({ + [`${kind}_${portion}`]: () => { + const makeCase = portion === 'whole' ? makeScalarCaseWhole : makeScalarCaseFract; + return FP[kind].scalarRange().map(makeCase.bind(null, kind)); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: [f32|f16|abstract]_vecN_[fract|whole] +const vec_cases = ['f32', 'f16', 'abstract']. +flatMap((kind) => +[2, 3, 4].flatMap((n) => +['whole', 'fract'].map((portion) => ({ + [`${kind}_vec${n}_${portion}`]: () => { + const makeCase = portion === 'whole' ? makeVectorCaseWhole : makeVectorCaseFract; + return FP[kind].vectorRange(n).map(makeCase.bind(null, kind)); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('modf', { + ...scalar_cases, + ...vec_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.spec.js index 4e3f8c0a85..39a3c7f10d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.spec.js @@ -3,13 +3,13 @@ **/export const description = ` Execution tests for the 'modf' builtin function -T is f32 or f16 or AbstractFloat +T is f32 or f16 or Type.abstractFloat @const fn modf(e:T) -> result_struct Splits |e| into fractional and whole number parts. The whole part is (|e| % 1.0), and the fractional part is |e| minus the whole part. Returns the result_struct for the given type. -S is f32 or f16 or AbstractFloat +S is f32 or f16 or Type.abstractFloat T is vecN @const fn modf(e:T) -> result_struct Splits the components of |e| into fractional and whole number parts. @@ -18,33 +18,18 @@ Returns the result_struct for the given type. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { - toVector, - TypeAbstractFloat, - TypeF16, - TypeF32, - TypeVec } from -'../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { - fullF16Range, - fullF32Range, - fullF64Range, - vectorF16Range, - vectorF32Range, - vectorF64Range } from -'../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { abstractFloatShaderBuilder, allInputSources, basicExpressionBuilder, - onlyConstInputSource, run } from '../../expression.js'; +import { d } from './modf.cache.js'; + export const g = makeTestGroup(GPUTest); /** @returns an ShaderBuilder that evaluates modf and returns .whole from the result structure */ @@ -67,101 +52,6 @@ function abstractFractBuilder() { return abstractFloatShaderBuilder((value) => `modf(${value}).fract`); } -/** @returns a fract Case for a scalar vector input */ -function makeScalarCaseFract(kind, n) { - const fp = FP[kind]; - n = fp.quantize(n); - const result = fp.modfInterval(n).fract; - - return { input: fp.scalarBuilder(n), expected: result }; -} - -/** @returns a whole Case for a scalar vector input */ -function makeScalarCaseWhole(kind, n) { - const fp = FP[kind]; - n = fp.quantize(n); - const result = fp.modfInterval(n).whole; - - return { input: fp.scalarBuilder(n), expected: result }; -} - -/** @returns a fract Case for a given vector input */ -function makeVectorCaseFract(kind, v) { - const fp = FP[kind]; - v = v.map(fp.quantize); - const fs = v.map((e) => { - return fp.modfInterval(e).fract; - }); - - return { input: toVector(v, fp.scalarBuilder), expected: fs }; -} - -/** @returns a whole Case for a given vector input */ -function makeVectorCaseWhole(kind, v) { - const fp = FP[kind]; - v = v.map(fp.quantize); - const ws = v.map((e) => { - return fp.modfInterval(e).whole; - }); - - return { input: toVector(v, fp.scalarBuilder), expected: ws }; -} - -const scalar_range = { - f32: fullF32Range(), - f16: fullF16Range(), - abstract: fullF64Range() -}; - -const vector_range = { - f32: { - 2: vectorF32Range(2), - 3: vectorF32Range(3), - 4: vectorF32Range(4) - }, - f16: { - 2: vectorF16Range(2), - 3: vectorF16Range(3), - 4: vectorF16Range(4) - }, - abstract: { - 2: vectorF64Range(2), - 3: vectorF64Range(3), - 4: vectorF64Range(4) - } -}; - -// Cases: [f32|f16|abstract]_[fract|whole] -const scalar_cases = ['f32', 'f16', 'abstract']. -flatMap((kind) => -['whole', 'fract'].map((portion) => ({ - [`${kind}_${portion}`]: () => { - const makeCase = portion === 'whole' ? makeScalarCaseWhole : makeScalarCaseFract; - return scalar_range[kind].map(makeCase.bind(null, kind)); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: [f32|f16|abstract]_vecN_[fract|whole] -const vec_cases = ['f32', 'f16', 'abstract']. -flatMap((kind) => -[2, 3, 4].flatMap((n) => -['whole', 'fract'].map((portion) => ({ - [`${kind}_vec${n}_${portion}`]: () => { - const makeCase = portion === 'whole' ? makeVectorCaseWhole : makeVectorCaseFract; - return vector_range[kind][n].map(makeCase.bind(null, kind)); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('modf', { - ...scalar_cases, - ...vec_cases -}); - g.test('f32_fract'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc( @@ -177,7 +67,7 @@ struct __modf_result_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_fract'); - await run(t, fractBuilder(), [TypeF32], TypeF32, t.params, cases); + await run(t, fractBuilder(), [Type.f32], Type.f32, t.params, cases); }); g.test('f32_whole'). @@ -195,7 +85,7 @@ struct __modf_result_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_whole'); - await run(t, wholeBuilder(), [TypeF32], TypeF32, t.params, cases); + await run(t, wholeBuilder(), [Type.f32], Type.f32, t.params, cases); }); g.test('f32_vec2_fract'). @@ -213,7 +103,7 @@ struct __modf_result_vec2_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec2_fract'); - await run(t, fractBuilder(), [TypeVec(2, TypeF32)], TypeVec(2, TypeF32), t.params, cases); + await run(t, fractBuilder(), [Type.vec2f], Type.vec2f, t.params, cases); }); g.test('f32_vec2_whole'). @@ -231,7 +121,7 @@ struct __modf_result_vec2_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec2_whole'); - await run(t, wholeBuilder(), [TypeVec(2, TypeF32)], TypeVec(2, TypeF32), t.params, cases); + await run(t, wholeBuilder(), [Type.vec2f], Type.vec2f, t.params, cases); }); g.test('f32_vec3_fract'). @@ -249,7 +139,7 @@ struct __modf_result_vec3_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec3_fract'); - await run(t, fractBuilder(), [TypeVec(3, TypeF32)], TypeVec(3, TypeF32), t.params, cases); + await run(t, fractBuilder(), [Type.vec3f], Type.vec3f, t.params, cases); }); g.test('f32_vec3_whole'). @@ -267,7 +157,7 @@ struct __modf_result_vec3_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec3_whole'); - await run(t, wholeBuilder(), [TypeVec(3, TypeF32)], TypeVec(3, TypeF32), t.params, cases); + await run(t, wholeBuilder(), [Type.vec3f], Type.vec3f, t.params, cases); }); g.test('f32_vec4_fract'). @@ -285,7 +175,7 @@ struct __modf_result_vec4_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec4_fract'); - await run(t, fractBuilder(), [TypeVec(4, TypeF32)], TypeVec(4, TypeF32), t.params, cases); + await run(t, fractBuilder(), [Type.vec4f], Type.vec4f, t.params, cases); }); g.test('f32_vec4_whole'). @@ -303,7 +193,7 @@ struct __modf_result_vec4_f32 { params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get('f32_vec4_whole'); - await run(t, wholeBuilder(), [TypeVec(4, TypeF32)], TypeVec(4, TypeF32), t.params, cases); + await run(t, wholeBuilder(), [Type.vec4f], Type.vec4f, t.params, cases); }); g.test('f16_fract'). @@ -324,7 +214,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_fract'); - await run(t, fractBuilder(), [TypeF16], TypeF16, t.params, cases); + await run(t, fractBuilder(), [Type.f16], Type.f16, t.params, cases); }); g.test('f16_whole'). @@ -345,7 +235,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_whole'); - await run(t, wholeBuilder(), [TypeF16], TypeF16, t.params, cases); + await run(t, wholeBuilder(), [Type.f16], Type.f16, t.params, cases); }); g.test('f16_vec2_fract'). @@ -366,7 +256,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec2_fract'); - await run(t, fractBuilder(), [TypeVec(2, TypeF16)], TypeVec(2, TypeF16), t.params, cases); + await run(t, fractBuilder(), [Type.vec2h], Type.vec2h, t.params, cases); }); g.test('f16_vec2_whole'). @@ -387,7 +277,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec2_whole'); - await run(t, wholeBuilder(), [TypeVec(2, TypeF16)], TypeVec(2, TypeF16), t.params, cases); + await run(t, wholeBuilder(), [Type.vec2h], Type.vec2h, t.params, cases); }); g.test('f16_vec3_fract'). @@ -408,7 +298,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec3_fract'); - await run(t, fractBuilder(), [TypeVec(3, TypeF16)], TypeVec(3, TypeF16), t.params, cases); + await run(t, fractBuilder(), [Type.vec3h], Type.vec3h, t.params, cases); }); g.test('f16_vec3_whole'). @@ -429,7 +319,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec3_whole'); - await run(t, wholeBuilder(), [TypeVec(3, TypeF16)], TypeVec(3, TypeF16), t.params, cases); + await run(t, wholeBuilder(), [Type.vec3h], Type.vec3h, t.params, cases); }); g.test('f16_vec4_fract'). @@ -450,7 +340,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec4_fract'); - await run(t, fractBuilder(), [TypeVec(4, TypeF16)], TypeVec(4, TypeF16), t.params, cases); + await run(t, fractBuilder(), [Type.vec4h], Type.vec4h, t.params, cases); }); g.test('f16_vec4_whole'). @@ -471,43 +361,43 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16_vec4_whole'); - await run(t, wholeBuilder(), [TypeVec(4, TypeF16)], TypeVec(4, TypeF16), t.params, cases); + await run(t, wholeBuilder(), [Type.vec4h], Type.vec4h, t.params, cases); }); g.test('abstract_fract'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc( ` -T is AbstractFloat +T is abstract-float struct __modf_result_abstract { - fract : AbstractFloat, // fractional part - whole : AbstractFloat // whole part + fract : Type.abstractFloat, // fractional part + whole : Type.abstractFloat // whole part } ` ). params((u) => u.combine('inputSource', onlyConstInputSource)). fn(async (t) => { const cases = await d.get('abstract_fract'); - await run(t, abstractFractBuilder(), [TypeAbstractFloat], TypeAbstractFloat, t.params, cases); + await run(t, abstractFractBuilder(), [Type.abstractFloat], Type.abstractFloat, t.params, cases); }); g.test('abstract_whole'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc( ` -T is AbstractFloat +T is abstract-float struct __modf_result_abstract { - fract : AbstractFloat, // fractional part - whole : AbstractFloat // whole part + fract : Type.abstractFloat, // fractional part + whole : Type.abstractFloat // whole part } ` ). params((u) => u.combine('inputSource', onlyConstInputSource)). fn(async (t) => { const cases = await d.get('abstract_whole'); - await run(t, abstractWholeBuilder(), [TypeAbstractFloat], TypeAbstractFloat, t.params, cases); + await run(t, abstractWholeBuilder(), [Type.abstractFloat], Type.abstractFloat, t.params, cases); }); g.test('abstract_vec2_fract'). @@ -528,8 +418,8 @@ fn(async (t) => { await run( t, abstractFractBuilder(), - [TypeVec(2, TypeAbstractFloat)], - TypeVec(2, TypeAbstractFloat), + [Type.vec(2, Type.abstractFloat)], + Type.vec(2, Type.abstractFloat), t.params, cases ); @@ -553,8 +443,8 @@ fn(async (t) => { await run( t, abstractWholeBuilder(), - [TypeVec(2, TypeAbstractFloat)], - TypeVec(2, TypeAbstractFloat), + [Type.vec(2, Type.abstractFloat)], + Type.vec(2, Type.abstractFloat), t.params, cases ); @@ -578,8 +468,8 @@ fn(async (t) => { await run( t, abstractFractBuilder(), - [TypeVec(3, TypeAbstractFloat)], - TypeVec(3, TypeAbstractFloat), + [Type.vec(3, Type.abstractFloat)], + Type.vec(3, Type.abstractFloat), t.params, cases ); @@ -603,8 +493,8 @@ fn(async (t) => { await run( t, abstractWholeBuilder(), - [TypeVec(3, TypeAbstractFloat)], - TypeVec(3, TypeAbstractFloat), + [Type.vec(3, Type.abstractFloat)], + Type.vec(3, Type.abstractFloat), t.params, cases ); @@ -628,8 +518,8 @@ fn(async (t) => { await run( t, abstractFractBuilder(), - [TypeVec(4, TypeAbstractFloat)], - TypeVec(4, TypeAbstractFloat), + [Type.vec(4, Type.abstractFloat)], + Type.vec(4, Type.abstractFloat), t.params, cases ); @@ -653,8 +543,8 @@ fn(async (t) => { await run( t, abstractWholeBuilder(), - [TypeVec(4, TypeAbstractFloat)], - TypeVec(4, TypeAbstractFloat), + [Type.vec(4, Type.abstractFloat)], + Type.vec(4, Type.abstractFloat), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.cache.js new file mode 100644 index 0000000000..a1b8b07b9f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.cache.js @@ -0,0 +1,25 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_vecN_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[2, 3, 4].flatMap((dim) => +[true, false].map((nonConst) => ({ + [`${trait}_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateVectorToVectorCases( + FP[trait].vectorRange(dim), + nonConst ? 'unfiltered' : 'finite', + // normalize has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].normalizeInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('normalize', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.spec.js index 3aa17a8ade..8bc4ea7ca8 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.spec.js @@ -3,63 +3,45 @@ **/export const description = ` Execution tests for the 'normalize' builtin function -T is AbstractFloat, f32, or f16 +T is abstract-float, f32, or f16 @const fn normalize(e: vecN ) -> vecN Returns a unit vector in the same direction as e. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { vectorF32Range, vectorF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './normalize.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: f32_vecN_[non_]const -const f32_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f32_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorToVectorCases( - vectorF32Range(n), - nonConst ? 'unfiltered' : 'finite', - FP.f32.normalizeInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: f16_vecN_[non_]const -const f16_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f16_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorToVectorCases( - vectorF16Range(n), - nonConst ? 'unfiltered' : 'finite', - FP.f16.normalizeInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); +g.test('abstract_float_vec2'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec2s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec2_const'); + await run(t, abstractFloatBuiltin('normalize'), [Type.vec2af], Type.vec2af, t.params, cases); +}); -export const d = makeCaseCache('normalize', { - ...f32_vec_cases, - ...f16_vec_cases +g.test('abstract_float_vec3'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec3s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec3_const'); + await run(t, abstractFloatBuiltin('normalize'), [Type.vec3af], Type.vec3af, t.params, cases); }); -g.test('abstract_float'). -specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). -desc(`abstract float tests`). -params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) -). -unimplemented(); +g.test('abstract_float_vec4'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec4s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec4_const'); + await run(t, abstractFloatBuiltin('normalize'), [Type.vec4af], Type.vec4af, t.params, cases); +}); g.test('f32_vec2'). specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). @@ -69,7 +51,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const' ); - await run(t, builtin('normalize'), [TypeVec(2, TypeF32)], TypeVec(2, TypeF32), t.params, cases); + await run(t, builtin('normalize'), [Type.vec2f], Type.vec2f, t.params, cases); }); g.test('f32_vec3'). @@ -80,7 +62,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const' ); - await run(t, builtin('normalize'), [TypeVec(3, TypeF32)], TypeVec(3, TypeF32), t.params, cases); + await run(t, builtin('normalize'), [Type.vec3f], Type.vec3f, t.params, cases); }); g.test('f32_vec4'). @@ -91,7 +73,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const' ); - await run(t, builtin('normalize'), [TypeVec(4, TypeF32)], TypeVec(4, TypeF32), t.params, cases); + await run(t, builtin('normalize'), [Type.vec4f], Type.vec4f, t.params, cases); }); g.test('f16_vec2'). @@ -105,7 +87,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec2_const' : 'f16_vec2_non_const' ); - await run(t, builtin('normalize'), [TypeVec(2, TypeF16)], TypeVec(2, TypeF16), t.params, cases); + await run(t, builtin('normalize'), [Type.vec2h], Type.vec2h, t.params, cases); }); g.test('f16_vec3'). @@ -119,7 +101,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec3_const' : 'f16_vec3_non_const' ); - await run(t, builtin('normalize'), [TypeVec(3, TypeF16)], TypeVec(3, TypeF16), t.params, cases); + await run(t, builtin('normalize'), [Type.vec3h], Type.vec3h, t.params, cases); }); g.test('f16_vec4'). @@ -133,5 +115,5 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec4_const' : 'f16_vec4_non_const' ); - await run(t, builtin('normalize'), [TypeVec(4, TypeF16)], TypeVec(4, TypeF16), t.params, cases); + await run(t, builtin('normalize'), [Type.vec4h], Type.vec4h, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.cache.js new file mode 100644 index 0000000000..ca204e03b6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.cache.js @@ -0,0 +1,55 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { anyOf, skipUndefined } from '../../../../../util/compare.js';import { f32, pack2x16float, u32, vec2 } from '../../../../../util/conversion.js';import { cartesianProduct, quantizeToF32, scalarF32Range } from '../../../../../util/math.js'; + +import { makeCaseCache } from '../../case_cache.js'; + +// pack2x16float has somewhat unusual behaviour, specifically around how it is +// supposed to behave when values go OOB and when they are considered to have +// gone OOB, so has its own bespoke implementation. + +/** + * @returns a Case for `pack2x16float` + * @param param0 first param for the case + * @param param1 second param for the case + * @param filter_undefined should inputs that cause an undefined expectation be + * filtered out, needed for const-eval + */ +function makeCase(param0, param1, filter_undefined) { + param0 = quantizeToF32(param0); + param1 = quantizeToF32(param1); + + const results = pack2x16float(param0, param1); + if (filter_undefined && results.some((r) => r === undefined)) { + return undefined; + } + + return { + input: [vec2(f32(param0), f32(param1))], + expected: anyOf( + ...results.map((r) => r === undefined ? skipUndefined(undefined) : skipUndefined(u32(r))) + ) + }; +} + +/** + * @returns an array of Cases for `pack2x16float` + * @param param0s array of inputs to try for the first param + * @param param1s array of inputs to try for the second param + * @param filter_undefined should inputs that cause an undefined expectation be + * filtered out, needed for const-eval + */ +function generateCases(param0s, param1s, filter_undefined) { + return cartesianProduct(param0s, param1s). + map((e) => makeCase(e[0], e[1], filter_undefined)). + filter((c) => c !== undefined); +} + +export const d = makeCaseCache('pack2x16float', { + f32_const: () => { + return generateCases(scalarF32Range(), scalarF32Range(), true); + }, + f32_non_const: () => { + return generateCases(scalarF32Range(), scalarF32Range(), false); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.spec.js index 1d991dc4f0..e859b1898a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.spec.js @@ -6,74 +6,14 @@ Component e[i] of the input is converted to a IEEE-754 binary16 value, which is then placed in bits 16 × i through 16 × i + 15 of the result. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { anyOf, skipUndefined } from '../../../../../util/compare.js'; -import { - f32, - pack2x16float, - TypeF32, - TypeU32, - TypeVec, - u32, - vec2 } from -'../../../../../util/conversion.js'; -import { cartesianProduct, fullF32Range, quantizeToF32 } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; +import { d } from './pack2x16float.cache.js'; export const g = makeTestGroup(GPUTest); -// pack2x16float has somewhat unusual behaviour, specifically around how it is -// supposed to behave when values go OOB and when they are considered to have -// gone OOB, so has its own bespoke implementation. - -/** - * @returns a Case for `pack2x16float` - * @param param0 first param for the case - * @param param1 second param for the case - * @param filter_undefined should inputs that cause an undefined expectation be - * filtered out, needed for const-eval - */ -function makeCase(param0, param1, filter_undefined) { - param0 = quantizeToF32(param0); - param1 = quantizeToF32(param1); - - const results = pack2x16float(param0, param1); - if (filter_undefined && results.some((r) => r === undefined)) { - return undefined; - } - - return { - input: [vec2(f32(param0), f32(param1))], - expected: anyOf( - ...results.map((r) => r === undefined ? skipUndefined(undefined) : skipUndefined(u32(r))) - ) - }; -} - -/** - * @returns an array of Cases for `pack2x16float` - * @param param0s array of inputs to try for the first param - * @param param1s array of inputs to try for the second param - * @param filter_undefined should inputs that cause an undefined expectation be - * filtered out, needed for const-eval - */ -function generateCases(param0s, param1s, filter_undefined) { - return cartesianProduct(param0s, param1s). - map((e) => makeCase(e[0], e[1], filter_undefined)). - filter((c) => c !== undefined); -} - -export const d = makeCaseCache('pack2x16float', { - f32_const: () => { - return generateCases(fullF32Range(), fullF32Range(), true); - }, - f32_non_const: () => { - return generateCases(fullF32Range(), fullF32Range(), false); - } -}); - g.test('pack'). specURL('https://www.w3.org/TR/WGSL/#pack-builtin-functions'). desc( @@ -84,5 +24,5 @@ desc( params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('pack2x16float'), [TypeVec(2, TypeF32)], TypeU32, t.params, cases); + await run(t, builtin('pack2x16float'), [Type.vec2f], Type.u32, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16snorm.spec.js index fb1ea8a5eb..e9f4b65582 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16snorm.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16snorm.spec.js @@ -8,16 +8,9 @@ bits 16 × i through 16 × i + 15 of the result. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; import { kValue } from '../../../../../util/constants.js'; -import { - f32, - pack2x16snorm, - TypeF32, - TypeU32, - TypeVec, - u32, - vec2 } from -'../../../../../util/conversion.js'; +import { f32, pack2x16snorm, u32, vec2, Type } from '../../../../../util/conversion.js'; import { quantizeToF32, vectorF32Range } from '../../../../../util/math.js'; + import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -51,5 +44,5 @@ fn(async (t) => { }); - await run(t, builtin('pack2x16snorm'), [TypeVec(2, TypeF32)], TypeU32, t.params, cases); + await run(t, builtin('pack2x16snorm'), [Type.vec2f], Type.u32, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16unorm.spec.js index cce847339d..f98d606b8d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16unorm.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16unorm.spec.js @@ -8,16 +8,9 @@ bits 16 × i through 16 × i + 15 of the result. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; import { kValue } from '../../../../../util/constants.js'; -import { - f32, - pack2x16unorm, - TypeF32, - TypeU32, - TypeVec, - u32, - vec2 } from -'../../../../../util/conversion.js'; +import { f32, pack2x16unorm, u32, vec2, Type } from '../../../../../util/conversion.js'; import { quantizeToF32, vectorF32Range } from '../../../../../util/math.js'; + import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -51,5 +44,5 @@ fn(async (t) => { }); - await run(t, builtin('pack2x16unorm'), [TypeVec(2, TypeF32)], TypeU32, t.params, cases); + await run(t, builtin('pack2x16unorm'), [Type.vec2f], Type.u32, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8snorm.spec.js index 60dc348348..42db991e53 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8snorm.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8snorm.spec.js @@ -8,17 +8,9 @@ bits 8 × i through 8 × i + 7 of the result. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; import { kValue } from '../../../../../util/constants.js'; -import { - f32, - pack4x8snorm, - - TypeF32, - TypeU32, - TypeVec, - u32, - vec4 } from -'../../../../../util/conversion.js'; +import { f32, pack4x8snorm, u32, vec4, Type } from '../../../../../util/conversion.js'; import { quantizeToF32, vectorF32Range } from '../../../../../util/math.js'; + import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -36,6 +28,11 @@ params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const makeCase = (vals) => { const vals_f32 = new Array(4); + + + + + for (const idx in vals) { vals[idx] = quantizeToF32(vals[idx]); vals_f32[idx] = f32(vals[idx]); @@ -56,5 +53,5 @@ fn(async (t) => { }); - await run(t, builtin('pack4x8snorm'), [TypeVec(4, TypeF32)], TypeU32, t.params, cases); + await run(t, builtin('pack4x8snorm'), [Type.vec4f], Type.u32, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8unorm.spec.js index 5ef35db626..d0299f973c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8unorm.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8unorm.spec.js @@ -8,17 +8,9 @@ bits 8 × i through 8 × i + 7 of the result. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; import { kValue } from '../../../../../util/constants.js'; -import { - f32, - pack4x8unorm, - - TypeF32, - TypeU32, - TypeVec, - u32, - vec4 } from -'../../../../../util/conversion.js'; +import { f32, pack4x8unorm, u32, vec4, Type } from '../../../../../util/conversion.js'; import { quantizeToF32, vectorF32Range } from '../../../../../util/math.js'; + import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -36,6 +28,11 @@ params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const makeCase = (vals) => { const vals_f32 = new Array(4); + + + + + for (const idx in vals) { vals[idx] = quantizeToF32(vals[idx]); vals_f32[idx] = f32(vals[idx]); @@ -56,5 +53,5 @@ fn(async (t) => { }); - await run(t, builtin('pack4x8unorm'), [TypeVec(4, TypeF32)], TypeU32, t.params, cases); + await run(t, builtin('pack4x8unorm'), [Type.vec4f], Type.u32, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xI8.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xI8.spec.js new file mode 100644 index 0000000000..4ced1a04b4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xI8.spec.js @@ -0,0 +1,69 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for the 'pack4xI8' builtin function + +@const fn pack4xI8(e: vec4) -> u32 +Pack the lower 8 bits of each component of e into a u32 value and drop all the unused bits. +Component e[i] of the input is mapped to bits (8 * i) through (8 * (i + 7)) of the result. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { u32, toVector, i32, Type } from '../../../../../util/conversion.js'; + +import { allInputSources, run } from '../../expression.js'; + +import { builtin } from './builtin.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('basic'). +specURL('https://www.w3.org/TR/WGSL/#pack4xI8-builtin'). +desc( + ` +@const fn pack4xI8(e: vec4) -> u32 + ` +). +params((u) => u.combine('inputSource', allInputSources)). +fn(async (t) => { + const cfg = t.params; + + const pack4xI8 = (vals) => { + const result = new Uint32Array(1); + for (let i = 0; i < 4; ++i) { + result[0] |= (vals[i] & 0xff) << i * 8; + } + return result[0]; + }; + + const testInputs = [ + [0, 0, 0, 0], + [1, 2, 3, 4], + [-1, 2, 3, 4], + [1, -2, 3, 4], + [1, 2, -3, 4], + [1, 2, 3, -4], + [-1, -2, 3, 4], + [-1, 2, -3, 4], + [-1, 2, 3, -4], + [1, -2, -3, 4], + [1, -2, 3, -4], + [1, 2, -3, -4], + [-1, -2, -3, 4], + [-1, -2, 3, -4], + [-1, 2, -3, -4], + [1, -2, -3, -4], + [-1, -2, -3, -4], + [127, 128, -128, -129], + [128, 128, -128, -128], + [32767, 32768, -32768, -32769]]; + + + const makeCase = (vals) => { + return { input: [toVector(vals, i32)], expected: u32(pack4xI8(vals)) }; + }; + const cases = testInputs.flatMap((v) => { + return [makeCase(v)]; + }); + + await run(t, builtin('pack4xI8'), [Type.vec4i], Type.u32, cfg, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xI8Clamp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xI8Clamp.spec.js new file mode 100644 index 0000000000..e7ee33839e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xI8Clamp.spec.js @@ -0,0 +1,73 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for the 'pack4xI8Clamp' builtin function + +@const fn pack4xI8Clamp(e: vec4) -> u32 +Clamp each component of e in the range [-128, 127] and then pack the lower 8 bits of each component +into a u32 value. Component e[i] of the input is mapped to bits (8 * i) through (8 * (i + 7)) of the +result. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { u32, toVector, i32, Type } from '../../../../../util/conversion.js'; +import { clamp } from '../../../../../util/math.js'; + +import { allInputSources, run } from '../../expression.js'; + +import { builtin } from './builtin.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('basic'). +specURL('https://www.w3.org/TR/WGSL/#pack4xI8Clamp-builtin'). +desc( + ` +@const fn pack4xI8Clamp(e: vec4) -> u32 + ` +). +params((u) => u.combine('inputSource', allInputSources)). +fn(async (t) => { + const cfg = t.params; + + const pack4xI8Clamp = (vals) => { + const result = new Uint32Array(1); + for (let i = 0; i < 4; ++i) { + const clampedValue = clamp(vals[i], { min: -128, max: 127 }); + result[0] |= (clampedValue & 0xff) << i * 8; + } + return result[0]; + }; + + const testInputs = [ + [0, 0, 0, 0], + [1, 2, 3, 4], + [-1, 2, 3, 4], + [1, -2, 3, 4], + [1, 2, -3, 4], + [1, 2, 3, -4], + [-1, -2, 3, 4], + [-1, 2, -3, 4], + [-1, 2, 3, -4], + [1, -2, -3, 4], + [1, -2, 3, -4], + [1, 2, -3, -4], + [-1, -2, -3, 4], + [-1, -2, 3, -4], + [-1, 2, -3, -4], + [1, -2, -3, -4], + [-1, -2, -3, -4], + [126, 127, 128, 129], + [-130, -129, -128, -127], + [127, 128, -128, -129], + [32767, 32768, -32768, -32769]]; + + + const makeCase = (vals) => { + return { input: [toVector(vals, i32)], expected: u32(pack4xI8Clamp(vals)) }; + }; + const cases = testInputs.flatMap((v) => { + return [makeCase(v)]; + }); + + await run(t, builtin('pack4xI8Clamp'), [Type.vec4i], Type.u32, cfg, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xU8.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xU8.spec.js new file mode 100644 index 0000000000..e5ace048f7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xU8.spec.js @@ -0,0 +1,54 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for the 'pack4xU8' builtin function + +@const fn pack4xU8(e: vec4) -> u32 +Pack the lower 8 bits of each component of e into a u32 value and drop all the unused bits. +Component e[i] of the input is mapped to bits (8 * i) through (8 * (i + 7)) of the result. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { u32, toVector, Type } from '../../../../../util/conversion.js'; + +import { allInputSources, run } from '../../expression.js'; + +import { builtin } from './builtin.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('basic'). +specURL('https://www.w3.org/TR/WGSL/#pack4xU8-builtin'). +desc( + ` +@const fn pack4xU8(e: vec4) -> u32 + ` +). +params((u) => u.combine('inputSource', allInputSources)). +fn(async (t) => { + const cfg = t.params; + + const pack4xU8 = (vals) => { + const result = new Uint32Array(1); + for (let i = 0; i < 4; ++i) { + result[0] |= (vals[i] & 0xff) << i * 8; + } + return result[0]; + }; + + const testInputs = [ + [0, 0, 0, 0], + [1, 2, 3, 4], + [255, 255, 255, 255], + [254, 255, 256, 257], + [65535, 65536, 255, 254]]; + + + const makeCase = (vals) => { + return { input: [toVector(vals, u32)], expected: u32(pack4xU8(vals)) }; + }; + const cases = testInputs.flatMap((v) => { + return [makeCase(v)]; + }); + + await run(t, builtin('pack4xU8'), [Type.vec4u], Type.u32, cfg, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xU8Clamp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xU8Clamp.spec.js new file mode 100644 index 0000000000..5a68795299 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4xU8Clamp.spec.js @@ -0,0 +1,57 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for the 'pack4xU8Clamp' builtin function + +@const fn pack4xU8Clamp(e: vec4) -> u32 +Clamp each component of e in the range of [0, 255] and then pack the lower 8 bits of each component +into a u32 value. Component e[i] of the input is mapped to bits (8 * i) through (8 * (i + 7)) of the +result. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { u32, toVector, Type } from '../../../../../util/conversion.js'; +import { clamp } from '../../../../../util/math.js'; + +import { allInputSources, run } from '../../expression.js'; + +import { builtin } from './builtin.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('basic'). +specURL('https://www.w3.org/TR/WGSL/#pack4xU8Clamp-builtin'). +desc( + ` +@const fn pack4xU8Clamp(e: vec4) -> u32 + ` +). +params((u) => u.combine('inputSource', allInputSources)). +fn(async (t) => { + const cfg = t.params; + + const pack4xU8Clamp = (vals) => { + const result = new Uint32Array(1); + for (let i = 0; i < 4; ++i) { + const clampedValue = clamp(vals[i], { min: 0, max: 255 }); + result[0] |= clampedValue << i * 8; + } + return result[0]; + }; + + const testInputs = [ + [0, 0, 0, 0], + [1, 2, 3, 4], + [255, 255, 255, 255], + [254, 255, 256, 257], + [65535, 65536, 255, 254]]; + + + const makeCase = (vals) => { + return { input: [toVector(vals, u32)], expected: u32(pack4xU8Clamp(vals)) }; + }; + const cases = testInputs.flatMap((v) => { + return [makeCase(v)]; + }); + + await run(t, builtin('pack4xU8Clamp'), [Type.vec4u], Type.u32, cfg, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.cache.js new file mode 100644 index 0000000000..944c406bd8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.cache.js @@ -0,0 +1,24 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarPairToIntervalCases( + FP[trait].scalarRange(), + FP[trait].scalarRange(), + nonConst ? 'unfiltered' : 'finite', + // pow has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].powInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('pow', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.spec.js index 45703c3df9..562c75de99 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.spec.js @@ -3,64 +3,39 @@ **/export const description = ` Execution tests for the 'pow' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn pow(e1: T ,e2: T ) -> T Returns e1 raised to the power e2. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './pow.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('pow', { - f32_const: () => { - return FP.f32.generateScalarPairToIntervalCases( - fullF32Range(), - fullF32Range(), - 'finite', - FP.f32.powInterval - ); - }, - f32_non_const: () => { - return FP.f32.generateScalarPairToIntervalCases( - fullF32Range(), - fullF32Range(), - 'unfiltered', - FP.f32.powInterval - ); - }, - f16_const: () => { - return FP.f16.generateScalarPairToIntervalCases( - fullF16Range(), - fullF16Range(), - 'finite', - FP.f16.powInterval - ); - }, - f16_non_const: () => { - return FP.f16.generateScalarPairToIntervalCases( - fullF16Range(), - fullF16Range(), - 'unfiltered', - FP.f16.powInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('pow'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -70,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('pow'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, builtin('pow'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -84,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('pow'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, builtin('pow'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.cache.js new file mode 100644 index 0000000000..1613f45143 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.cache.js @@ -0,0 +1,41 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kValue } from '../../../../../util/constants.js';import { FP } from '../../../../../util/floating_point.js';import { scalarF16Range, scalarF32Range } from '../../../../../util/math.js'; +import { makeCaseCache } from '../../case_cache.js'; + +export const d = makeCaseCache('quantizeToF16', { + f32_const: () => { + return FP.f32.generateScalarToIntervalCases( + [ + kValue.f16.negative.min, + kValue.f16.negative.max, + kValue.f16.negative.subnormal.min, + kValue.f16.negative.subnormal.max, + kValue.f16.positive.subnormal.min, + kValue.f16.positive.subnormal.max, + kValue.f16.positive.min, + kValue.f16.positive.max, + ...scalarF16Range()], + + 'finite', + FP.f32.quantizeToF16Interval + ); + }, + f32_non_const: () => { + return FP.f32.generateScalarToIntervalCases( + [ + kValue.f16.negative.min, + kValue.f16.negative.max, + kValue.f16.negative.subnormal.min, + kValue.f16.negative.subnormal.max, + kValue.f16.positive.subnormal.min, + kValue.f16.positive.subnormal.max, + kValue.f16.positive.min, + kValue.f16.positive.max, + ...scalarF32Range()], + + 'unfiltered', + FP.f32.quantizeToF16Interval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.spec.js index 53ccd41cfb..b872d0923f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.spec.js @@ -10,54 +10,14 @@ binary16 value, and then converted back to a IEEE 754 binary32 value. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { kValue } from '../../../../../util/constants.js'; -import { TypeF32 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF16Range, fullF32Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; +import { d } from './quantizeToF16.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('quantizeToF16', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases( - [ - kValue.f16.negative.min, - kValue.f16.negative.max, - kValue.f16.negative.subnormal.min, - kValue.f16.negative.subnormal.max, - kValue.f16.positive.subnormal.min, - kValue.f16.positive.subnormal.max, - kValue.f16.positive.min, - kValue.f16.positive.max, - ...fullF16Range()], - - 'finite', - FP.f32.quantizeToF16Interval - ); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases( - [ - kValue.f16.negative.min, - kValue.f16.negative.max, - kValue.f16.negative.subnormal.min, - kValue.f16.negative.subnormal.max, - kValue.f16.positive.subnormal.min, - kValue.f16.positive.subnormal.max, - kValue.f16.positive.min, - kValue.f16.positive.max, - ...fullF32Range()], - - 'unfiltered', - FP.f32.quantizeToF16Interval - ); - } -}); - g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`f32 tests`). @@ -66,5 +26,5 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('quantizeToF16'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('quantizeToF16'), [Type.f32], Type.f32, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.cache.js new file mode 100644 index 0000000000..d3770a173c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.cache.js @@ -0,0 +1,18 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + trait !== 'abstract' ? 'unfiltered' : 'finite', + // radians has an inherited accuracy, so abstract is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].radiansInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('radians', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.spec.js index 72aea0ee9f..46e8dbb09b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.spec.js @@ -3,47 +3,21 @@ **/export const description = ` Execution tests for the 'radians' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn radians(e1: T ) -> T Converts degrees to radians, approximating e1 * π / 180. Component-wise when T is a vector `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeF16, TypeF32 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF16Range, fullF32Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './radians.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('radians', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - fullF32Range(), - 'unfiltered', - FP.f32.radiansInterval - ); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - fullF16Range(), - 'unfiltered', - FP.f16.radiansInterval - ); - }, - abstract: () => { - return FP.abstract.generateScalarToIntervalCases( - fullF16Range(), - 'unfiltered', - FP.abstract.radiansInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). @@ -56,9 +30,9 @@ fn(async (t) => { const cases = await d.get('abstract'); await run( t, - abstractBuiltin('radians'), - [TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBuiltin('radians'), + [Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -72,7 +46,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('radians'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('radians'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -86,5 +60,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('radians'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('radians'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.cache.js new file mode 100644 index 0000000000..359e731bf2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.cache.js @@ -0,0 +1,26 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_vecN_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[2, 3, 4].flatMap((dim) => +[true, false].map((nonConst) => ({ + [`${trait}_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateVectorPairToVectorCases( + FP[trait].sparseVectorRange(dim), + FP[trait].sparseVectorRange(dim), + nonConst ? 'unfiltered' : 'finite', + // reflect has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].reflectInterval + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('reflect', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.spec.js index 0c3933ce2e..4d1b805e1f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.spec.js @@ -3,64 +3,67 @@ **/export const description = ` Execution tests for the 'reflect' builtin function -T is vecN, vecN, or vecN +T is vecN, vecN, or vecN @const fn reflect(e1: T, e2: T ) -> T For the incident vector e1 and surface orientation e2, returns the reflection direction e1-2*dot(e2,e1)*e2. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { sparseVectorF32Range, sparseVectorF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './reflect.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: f32_vecN_[non_]const -const f32_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f32_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateVectorPairToVectorCases( - sparseVectorF32Range(n), - sparseVectorF32Range(n), - nonConst ? 'unfiltered' : 'finite', - FP.f32.reflectInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: f16_vecN_[non_]const -const f16_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f16_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateVectorPairToVectorCases( - sparseVectorF16Range(n), - sparseVectorF16Range(n), - nonConst ? 'unfiltered' : 'finite', - FP.f16.reflectInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); +g.test('abstract_float_vec2'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec2s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec2_const'); + await run( + t, + abstractFloatBuiltin('reflect'), + [Type.vec2af, Type.vec2af], + Type.vec2af, + t.params, + cases + ); +}); -export const d = makeCaseCache('reflect', { - ...f32_vec_cases, - ...f16_vec_cases +g.test('abstract_float_vec3'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec3s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec3_const'); + await run( + t, + abstractFloatBuiltin('reflect'), + [Type.vec3af, Type.vec3af], + Type.vec3af, + t.params, + cases + ); }); -g.test('abstract_float'). -specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). -desc(`abstract float tests`). -params((u) => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4])). -unimplemented(); +g.test('abstract_float_vec4'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec4s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec4_const'); + await run( + t, + abstractFloatBuiltin('reflect'), + [Type.vec4af, Type.vec4af], + Type.vec4af, + t.params, + cases + ); +}); g.test('f32_vec2'). specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). @@ -70,14 +73,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const' ); - await run( - t, - builtin('reflect'), - [TypeVec(2, TypeF32), TypeVec(2, TypeF32)], - TypeVec(2, TypeF32), - t.params, - cases - ); + await run(t, builtin('reflect'), [Type.vec2f, Type.vec2f], Type.vec2f, t.params, cases); }); g.test('f32_vec3'). @@ -88,14 +84,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const' ); - await run( - t, - builtin('reflect'), - [TypeVec(3, TypeF32), TypeVec(3, TypeF32)], - TypeVec(3, TypeF32), - t.params, - cases - ); + await run(t, builtin('reflect'), [Type.vec3f, Type.vec3f], Type.vec3f, t.params, cases); }); g.test('f32_vec4'). @@ -106,14 +95,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const' ); - await run( - t, - builtin('reflect'), - [TypeVec(4, TypeF32), TypeVec(4, TypeF32)], - TypeVec(4, TypeF32), - t.params, - cases - ); + await run(t, builtin('reflect'), [Type.vec4f, Type.vec4f], Type.vec4f, t.params, cases); }); g.test('f16_vec2'). @@ -127,14 +109,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec2_const' : 'f16_vec2_non_const' ); - await run( - t, - builtin('reflect'), - [TypeVec(2, TypeF16), TypeVec(2, TypeF16)], - TypeVec(2, TypeF16), - t.params, - cases - ); + await run(t, builtin('reflect'), [Type.vec2h, Type.vec2h], Type.vec2h, t.params, cases); }); g.test('f16_vec3'). @@ -148,14 +123,7 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec3_const' : 'f16_vec3_non_const' ); - await run( - t, - builtin('reflect'), - [TypeVec(3, TypeF16), TypeVec(3, TypeF16)], - TypeVec(3, TypeF16), - t.params, - cases - ); + await run(t, builtin('reflect'), [Type.vec3h, Type.vec3h], Type.vec3h, t.params, cases); }); g.test('f16_vec4'). @@ -169,12 +137,5 @@ fn(async (t) => { const cases = await d.get( t.params.inputSource === 'const' ? 'f16_vec4_const' : 'f16_vec4_non_const' ); - await run( - t, - builtin('reflect'), - [TypeVec(4, TypeF16), TypeVec(4, TypeF16)], - TypeVec(4, TypeF16), - t.params, - cases - ); + await run(t, builtin('reflect'), [Type.vec4h, Type.vec4h], Type.vec4h, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.cache.js new file mode 100644 index 0000000000..4f2ce5e2b4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.cache.js @@ -0,0 +1,116 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { toVector } from '../../../../../util/conversion.js';import { FP } from '../../../../../util/floating_point.js'; +import { selectNCases } from '../../case.js'; +import { makeCaseCache } from '../../case_cache.js'; + + +// Using a bespoke implementation of make*Case and generate*Cases here +// since refract is the only builtin with the API signature +// (vec, vec, scalar) -> vec + +/** + * @returns a Case for `refract` + * @param argumentKind what kind of floating point numbers being operated on + * @param parameterKind what kind of floating point operation should be performed, + * should be the same as argumentKind, except for abstract + * @param i the `i` param for the case + * @param s the `s` param for the case + * @param r the `r` param for the case + * @param check what interval checking to apply + * */ +function makeCase( +argumentKind, +parameterKind, +i, +s, +r, +check) +{ + const fp = FP[argumentKind]; + i = i.map(fp.quantize); + s = s.map(fp.quantize); + r = fp.quantize(r); + + const vectors = FP[parameterKind].refractInterval(i, s, r); + if (check === 'finite' && vectors.some((e) => !e.isFinite())) { + return undefined; + } + + return { + input: [toVector(i, fp.scalarBuilder), toVector(s, fp.scalarBuilder), fp.scalarBuilder(r)], + expected: vectors + }; +} + +/** + * @returns an array of Cases for `refract` + * @param argumentKind what kind of floating point numbers being operated on + * @param parameterKind what kind of floating point operation should be performed, + * should be the same as argumentKind, except for abstract + * @param param_is array of inputs to try for the `i` param + * @param param_ss array of inputs to try for the `s` param + * @param param_rs array of inputs to try for the `r` param + * @param check what interval checking to apply + */ +function generateCases( +argumentKind, +parameterKind, +param_is, +param_ss, +param_rs, +check) +{ + // Cannot use `cartesianProduct` here due to heterogeneous param types + return param_is. + flatMap((i) => { + return param_ss.flatMap((s) => { + return param_rs.map((r) => { + return makeCase(argumentKind, parameterKind, i, s, r, check); + }); + }); + }). + filter((c) => c !== undefined); +} + +// Cases: [f32|f16|abstract]_vecN_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[2, 3, 4].flatMap((dim) => +[true, false].map((nonConst) => ({ + [`${trait}_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + if (trait !== 'abstract') { + return generateCases( + trait, + trait, + FP[trait].sparseVectorRange(dim), + FP[trait].sparseVectorRange(dim), + FP[trait].sparseScalarRange(), + nonConst ? 'unfiltered' : 'finite' + ); + } else { + // Restricting the number of cases, because a vector of abstract floats needs to be returned, which is costly. + return selectNCases( + 'faceForward', + 20, + generateCases( + trait, + // refract has an inherited accuracy, so is only expected to be as accurate as f32 + 'f32', + FP[trait].sparseVectorRange(dim), + FP[trait].sparseVectorRange(dim), + FP[trait].sparseScalarRange(), + nonConst ? 'unfiltered' : 'finite' + ) + ); + } + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('refract', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.spec.js index 53ccfb4fed..a2ffec4a1a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.spec.js @@ -4,136 +4,69 @@ Execution tests for the 'refract' builtin function T is vecN -I is AbstractFloat, f32, or f16 +I is abstract-float, f32, or f16 @const fn refract(e1: T ,e2: T ,e3: I ) -> T For the incident vector e1 and surface normal e2, and the ratio of indices of refraction e3, let k = 1.0 -e3*e3* (1.0 - dot(e2,e1) * dot(e2,e1)). If k < 0.0, returns the refraction vector 0.0, otherwise return the refraction vector e3*e1- (e3* dot(e2,e1) + sqrt(k)) *e2. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; - import { GPUTest } from '../../../../../gpu_test.js'; -import { toVector, TypeF32, TypeF16, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { - sparseVectorF32Range, - sparseVectorF16Range, - sparseF32Range, - sparseF16Range } from -'../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './refract.cache.js'; export const g = makeTestGroup(GPUTest); -// Using a bespoke implementation of make*Case and generate*Cases here -// since refract is the only builtin with the API signature -// (vec, vec, scalar) -> vec - -/** - * @returns a Case for `refract` - * @param kind what type of floating point numbers to operate on - * @param i the `i` param for the case - * @param s the `s` param for the case - * @param r the `r` param for the case - * @param check what interval checking to apply - * */ -function makeCase( -kind, -i, -s, -r, -check) -{ - const fp = FP[kind]; - i = i.map(fp.quantize); - s = s.map(fp.quantize); - r = fp.quantize(r); - - const vectors = fp.refractInterval(i, s, r); - if (check === 'finite' && vectors.some((e) => !e.isFinite())) { - return undefined; - } - - return { - input: [toVector(i, fp.scalarBuilder), toVector(s, fp.scalarBuilder), fp.scalarBuilder(r)], - expected: fp.refractInterval(i, s, r) - }; -} - -/** - * @returns an array of Cases for `refract` - * @param kind what type of floating point numbers to operate on - * @param param_is array of inputs to try for the `i` param - * @param param_ss array of inputs to try for the `s` param - * @param param_rs array of inputs to try for the `r` param - * @param check what interval checking to apply - */ -function generateCases( -kind, -param_is, -param_ss, -param_rs, -check) -{ - // Cannot use `cartesianProduct` here due to heterogeneous param types - return param_is. - flatMap((i) => { - return param_ss.flatMap((s) => { - return param_rs.map((r) => { - return makeCase(kind, i, s, r, check); - }); - }); - }). - filter((c) => c !== undefined); -} - -// Cases: f32_vecN_[non_]const -const f32_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f32_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return generateCases( - 'f32', - sparseVectorF32Range(n), - sparseVectorF32Range(n), - sparseF32Range(), - nonConst ? 'unfiltered' : 'finite' - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: f16_vecN_[non_]const -const f16_vec_cases = [2, 3, 4]. -flatMap((n) => -[true, false].map((nonConst) => ({ - [`f16_vec${n}_${nonConst ? 'non_const' : 'const'}`]: () => { - return generateCases( - 'f16', - sparseVectorF16Range(n), - sparseVectorF16Range(n), - sparseF16Range(), - nonConst ? 'unfiltered' : 'finite' - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); +g.test('abstract_float_vec2'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec2s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec2_const'); + await run( + t, + abstractFloatBuiltin('refract'), + [Type.vec2af, Type.vec2af, Type.abstractFloat], + Type.vec2af, + t.params, + cases + ); +}); -export const d = makeCaseCache('refract', { - ...f32_vec_cases, - ...f16_vec_cases +g.test('abstract_float_vec3'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec3s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec3_const'); + await run( + t, + abstractFloatBuiltin('refract'), + [Type.vec3af, Type.vec3af, Type.abstractFloat], + Type.vec3af, + t.params, + cases + ); }); -g.test('abstract_float'). -specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). -desc(`abstract float tests`). -params((u) => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4])). -unimplemented(); +g.test('abstract_float_vec4'). +specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). +desc(`abstract float tests using vec4s`). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract_vec4_const'); + await run( + t, + abstractFloatBuiltin('refract'), + [Type.vec4af, Type.vec4af, Type.abstractFloat], + Type.vec4af, + t.params, + cases + ); +}); g.test('f32_vec2'). specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions'). @@ -146,8 +79,8 @@ fn(async (t) => { await run( t, builtin('refract'), - [TypeVec(2, TypeF32), TypeVec(2, TypeF32), TypeF32], - TypeVec(2, TypeF32), + [Type.vec2f, Type.vec2f, Type.f32], + Type.vec2f, t.params, cases ); @@ -164,8 +97,8 @@ fn(async (t) => { await run( t, builtin('refract'), - [TypeVec(3, TypeF32), TypeVec(3, TypeF32), TypeF32], - TypeVec(3, TypeF32), + [Type.vec3f, Type.vec3f, Type.f32], + Type.vec3f, t.params, cases ); @@ -182,8 +115,8 @@ fn(async (t) => { await run( t, builtin('refract'), - [TypeVec(4, TypeF32), TypeVec(4, TypeF32), TypeF32], - TypeVec(4, TypeF32), + [Type.vec4f, Type.vec4f, Type.f32], + Type.vec4f, t.params, cases ); @@ -203,8 +136,8 @@ fn(async (t) => { await run( t, builtin('refract'), - [TypeVec(2, TypeF16), TypeVec(2, TypeF16), TypeF16], - TypeVec(2, TypeF16), + [Type.vec2h, Type.vec2h, Type.f16], + Type.vec2h, t.params, cases ); @@ -224,8 +157,8 @@ fn(async (t) => { await run( t, builtin('refract'), - [TypeVec(3, TypeF16), TypeVec(3, TypeF16), TypeF16], - TypeVec(3, TypeF16), + [Type.vec3h, Type.vec3h, Type.f16], + Type.vec3h, t.params, cases ); @@ -245,8 +178,8 @@ fn(async (t) => { await run( t, builtin('refract'), - [TypeVec(4, TypeF16), TypeVec(4, TypeF16), TypeF16], - TypeVec(4, TypeF16), + [Type.vec4h, Type.vec4h, Type.f16], + Type.vec4h, t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reverseBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reverseBits.spec.js index fc99867f10..9716dfd108 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reverseBits.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reverseBits.spec.js @@ -10,7 +10,7 @@ Reverses the bits in e: The bit at position k of the result equals the bit at po Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeU32, u32Bits, TypeI32, i32Bits } from '../../../../../util/conversion.js'; +import { u32Bits, i32Bits, Type } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; @@ -26,7 +26,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, fn(async (t) => { const cfg = t.params; - await run(t, builtin('reverseBits'), [TypeU32], TypeU32, cfg, [ + await run(t, builtin('reverseBits'), [Type.u32], Type.u32, cfg, [ // Zero { input: u32Bits(0b00000000000000000000000000000000), expected: u32Bits(0b00000000000000000000000000000000) }, @@ -142,7 +142,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, fn(async (t) => { const cfg = t.params; - await run(t, builtin('reverseBits'), [TypeI32], TypeI32, cfg, [ + await run(t, builtin('reverseBits'), [Type.i32], Type.i32, cfg, [ // Zero { input: i32Bits(0b00000000000000000000000000000000), expected: i32Bits(0b00000000000000000000000000000000) }, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.cache.js new file mode 100644 index 0000000000..12184af16a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.cache.js @@ -0,0 +1,24 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// See https://github.com/gpuweb/cts/issues/2766 for details +const kIssue2766Value = { + abstract: 0x8000_0000_0000_0000, + f32: 0x8000_0000, + f16: 0x8000 +}; + +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + [kIssue2766Value[trait], ...FP[trait].scalarRange()], + 'unfiltered', + FP[trait].roundInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('round', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.spec.js index d5e6eec3aa..b60399773e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.spec.js @@ -3,7 +3,7 @@ **/export const description = ` Execution tests for the 'round' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn round(e: T) -> T Result is the integer k nearest to e, as a floating point value. @@ -12,46 +12,33 @@ and k+1 when k is odd. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './round.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('round', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - [ - 0x80000000, // https://github.com/gpuweb/cts/issues/2766, - ...fullF32Range()], - - 'unfiltered', - FP.f32.roundInterval - ); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - [ - 0x8000, // https://github.com/gpuweb/cts/issues/2766 - ...fullF16Range()], - - 'unfiltered', - FP.f16.roundInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('round'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -61,7 +48,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('round'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('round'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -75,5 +62,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('round'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('round'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.cache.js new file mode 100644 index 0000000000..5552284c2e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.cache.js @@ -0,0 +1,18 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { linearRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + [...linearRange(0.0, 1.0, 20), ...FP[trait].scalarRange()], + 'unfiltered', + FP[trait].saturateInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('saturate', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.spec.js index 1869d9c058..e18f41ae65 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.spec.js @@ -3,58 +3,20 @@ **/export const description = ` Execution tests for the 'saturate' builtin function -S is AbstractFloat, f32, or f16 +S is abstract-float, f32, or f16 T is S or vecN @const fn saturate(e: T) -> T Returns clamp(e, 0.0, 1.0). Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeF16, TypeF32 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF16Range, fullF32Range, fullF64Range, linearRange } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './saturate.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('saturate', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - [ - // Non-clamped values - ...linearRange(0.0, 1.0, 20), - ...fullF32Range()], - - 'unfiltered', - FP.f32.saturateInterval - ); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - [ - // Non-clamped values - ...linearRange(0.0, 1.0, 20), - ...fullF16Range()], - - 'unfiltered', - FP.f16.saturateInterval - ); - }, - abstract: () => { - return FP.abstract.generateScalarToIntervalCases( - [ - // Non-clamped values - ...linearRange(0.0, 1.0, 20), - ...fullF64Range()], - - 'unfiltered', - FP.abstract.saturateInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). @@ -67,9 +29,9 @@ fn(async (t) => { const cases = await d.get('abstract'); await run( t, - abstractBuiltin('saturate'), - [TypeAbstractFloat], - TypeAbstractFloat, + abstractFloatBuiltin('saturate'), + [Type.abstractFloat], + Type.abstractFloat, t.params, cases ); @@ -82,7 +44,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('saturate'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('saturate'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -96,5 +58,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('saturate'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('saturate'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/select.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/select.spec.js index 8248e04dc0..c08f4d5f1b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/select.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/select.spec.js @@ -14,12 +14,6 @@ Component-wise selection. Result component i is evaluated as select(f[i],t[i],co import { GPUTest } from '../../../../../gpu_test.js'; import { - TypeVec, - TypeBool, - TypeF32, - TypeF16, - TypeI32, - TypeU32, f32, f16, i32, @@ -31,11 +25,14 @@ import { vec3, vec4, abstractFloat, - TypeAbstractFloat } from + abstractInt, + + Type } from '../../../../../util/conversion.js'; + import { run, allInputSources } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, abstractIntBuiltin, builtin } from './builtin.js'; export const g = makeTestGroup(GPUTest); @@ -47,28 +44,43 @@ function makeBool(n) { const dataType = { b: { - type: TypeBool, - constructor: makeBool + type: Type.bool, + scalar_builder: makeBool, + shader_builder: builtin('select') }, af: { - type: TypeAbstractFloat, - constructor: abstractFloat + type: Type.abstractFloat, + scalar_builder: abstractFloat, + shader_builder: abstractFloatBuiltin('select') }, f: { - type: TypeF32, - constructor: f32 + type: Type.f32, + scalar_builder: f32, + shader_builder: builtin('select') }, h: { - type: TypeF16, - constructor: f16 + type: Type.f16, + scalar_builder: f16, + shader_builder: builtin('select') + }, + ai: { + type: Type.abstractInt, + // Only ints are used in the tests below, so the conversion to bigint will + // be safe. If a non-int is passed in this will Error. + scalar_builder: (v) => { + return abstractInt(BigInt(v)); + }, + shader_builder: abstractIntBuiltin('select') }, i: { - type: TypeI32, - constructor: i32 + type: Type.i32, + scalar_builder: i32, + shader_builder: builtin('select') }, u: { - type: TypeU32, - constructor: u32 + type: Type.u32, + scalar_builder: u32, + shader_builder: builtin('select') } }; @@ -78,7 +90,7 @@ desc(`scalar tests`). params((u) => u. combine('inputSource', allInputSources). -combine('component', ['b', 'af', 'f', 'h', 'i', 'u']). +combine('component', ['b', 'af', 'f', 'h', 'ai', 'i', 'u']). combine('overload', ['scalar', 'vec2', 'vec3', 'vec4']) ). beforeAllSubcases((t) => { @@ -86,10 +98,11 @@ beforeAllSubcases((t) => { t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); } t.skipIf(t.params.component === 'af' && t.params.inputSource !== 'const'); + t.skipIf(t.params.component === 'ai' && t.params.inputSource !== 'const'); }). fn(async (t) => { const componentType = dataType[t.params.component].type; - const cons = dataType[t.params.component].constructor; + const scalar_builder = dataType[t.params.component].scalar_builder; // Create the scalar values that will be selected from, either as scalars // or vectors. @@ -97,39 +110,40 @@ fn(async (t) => { // Each boolean will select between c[k] and c[k+4]. Those values must // always compare as different. The tricky case is boolean, where the parity // has to be different, i.e. c[k]-c[k+4] must be odd. - const c = [0, 1, 2, 3, 5, 6, 7, 8].map((i) => cons(i)); + const scalars = [0, 1, 2, 3, 5, 6, 7, 8].map((i) => scalar_builder(i)); + // Now form vectors that will have different components from each other. - const v2a = vec2(c[0], c[1]); - const v2b = vec2(c[4], c[5]); - const v3a = vec3(c[0], c[1], c[2]); - const v3b = vec3(c[4], c[5], c[6]); - const v4a = vec4(c[0], c[1], c[2], c[3]); - const v4b = vec4(c[4], c[5], c[6], c[7]); + const v2a = vec2(scalars[0], scalars[1]); + const v2b = vec2(scalars[4], scalars[5]); + const v3a = vec3(scalars[0], scalars[1], scalars[2]); + const v3b = vec3(scalars[4], scalars[5], scalars[6]); + const v4a = vec4(scalars[0], scalars[1], scalars[2], scalars[3]); + const v4b = vec4(scalars[4], scalars[5], scalars[6], scalars[7]); const overloads = { scalar: { type: componentType, cases: [ - { input: [c[0], c[1], False], expected: c[0] }, - { input: [c[0], c[1], True], expected: c[1] }] + { input: [scalars[0], scalars[1], False], expected: scalars[0] }, + { input: [scalars[0], scalars[1], True], expected: scalars[1] }] }, vec2: { - type: TypeVec(2, componentType), + type: Type.vec(2, componentType), cases: [ { input: [v2a, v2b, False], expected: v2a }, { input: [v2a, v2b, True], expected: v2b }] }, vec3: { - type: TypeVec(3, componentType), + type: Type.vec(3, componentType), cases: [ { input: [v3a, v3b, False], expected: v3a }, { input: [v3a, v3b, True], expected: v3b }] }, vec4: { - type: TypeVec(4, componentType), + type: Type.vec(4, componentType), cases: [ { input: [v4a, v4b, False], expected: v4a }, { input: [v4a, v4b, True], expected: v4b }] @@ -140,8 +154,8 @@ fn(async (t) => { await run( t, - t.params.component === 'af' ? abstractBuiltin('select') : builtin('select'), - [overload.type, overload.type, TypeBool], + dataType[t.params.component].shader_builder, + [overload.type, overload.type, Type.bool], overload.type, t.params, overload.cases @@ -154,7 +168,7 @@ desc(`vector tests`). params((u) => u. combine('inputSource', allInputSources). -combine('component', ['b', 'af', 'f', 'h', 'i', 'u']). +combine('component', ['b', 'af', 'f', 'h', 'ai', 'i', 'u']). combine('overload', ['vec2', 'vec3', 'vec4']) ). beforeAllSubcases((t) => { @@ -162,17 +176,18 @@ beforeAllSubcases((t) => { t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); } t.skipIf(t.params.component === 'af' && t.params.inputSource !== 'const'); + t.skipIf(t.params.component === 'ai' && t.params.inputSource !== 'const'); }). fn(async (t) => { const componentType = dataType[t.params.component].type; - const cons = dataType[t.params.component].constructor; + const scalar_builder = dataType[t.params.component].scalar_builder; // Create the scalar values that will be selected from. // // Each boolean will select between c[k] and c[k+4]. Those values must // always compare as different. The tricky case is boolean, where the parity // has to be different, i.e. c[k]-c[k+4] must be odd. - const c = [0, 1, 2, 3, 5, 6, 7, 8].map((i) => cons(i)); + const scalars = [0, 1, 2, 3, 5, 6, 7, 8].map((i) => scalar_builder(i)); const T = True; const F = False; @@ -180,11 +195,11 @@ fn(async (t) => { switch (t.params.overload) { case 'vec2':{ - const a = vec2(c[0], c[1]); - const b = vec2(c[4], c[5]); + const a = vec2(scalars[0], scalars[1]); + const b = vec2(scalars[4], scalars[5]); tests = { - dataType: TypeVec(2, componentType), - boolType: TypeVec(2, TypeBool), + dataType: Type.vec(2, componentType), + boolType: Type.vec(2, Type.bool), cases: [ { input: [a, b, vec2(F, F)], expected: vec2(a.x, a.y) }, { input: [a, b, vec2(F, T)], expected: vec2(a.x, b.y) }, @@ -195,11 +210,11 @@ fn(async (t) => { break; } case 'vec3':{ - const a = vec3(c[0], c[1], c[2]); - const b = vec3(c[4], c[5], c[6]); + const a = vec3(scalars[0], scalars[1], scalars[2]); + const b = vec3(scalars[4], scalars[5], scalars[6]); tests = { - dataType: TypeVec(3, componentType), - boolType: TypeVec(3, TypeBool), + dataType: Type.vec(3, componentType), + boolType: Type.vec(3, Type.bool), cases: [ { input: [a, b, vec3(F, F, F)], expected: vec3(a.x, a.y, a.z) }, { input: [a, b, vec3(F, F, T)], expected: vec3(a.x, a.y, b.z) }, @@ -214,11 +229,11 @@ fn(async (t) => { break; } case 'vec4':{ - const a = vec4(c[0], c[1], c[2], c[3]); - const b = vec4(c[4], c[5], c[6], c[7]); + const a = vec4(scalars[0], scalars[1], scalars[2], scalars[3]); + const b = vec4(scalars[4], scalars[5], scalars[6], scalars[7]); tests = { - dataType: TypeVec(4, componentType), - boolType: TypeVec(4, TypeBool), + dataType: Type.vec(4, componentType), + boolType: Type.vec(4, Type.bool), cases: [ { input: [a, b, vec4(F, F, F, F)], expected: vec4(a.x, a.y, a.z, a.w) }, { input: [a, b, vec4(F, F, F, T)], expected: vec4(a.x, a.y, a.z, b.w) }, @@ -244,7 +259,7 @@ fn(async (t) => { await run( t, - t.params.component === 'af' ? abstractBuiltin('select') : builtin('select'), + dataType[t.params.component].shader_builder, [tests.dataType, tests.dataType, tests.boolType], tests.dataType, t.params, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.cache.js new file mode 100644 index 0000000000..839f97d59a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.cache.js @@ -0,0 +1,31 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { abstractInt, i32 } from '../../../../../util/conversion.js';import { FP } from '../../../../../util/floating_point.js';import { fullI32Range, fullI64Range } from '../../../../../util/math.js'; +import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract] +const fp_cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait === 'abstract' ? 'abstract_float' : trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + 'unfiltered', + FP[trait].signInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('sign', { + ...fp_cases, + i32: () => + fullI32Range().map((i) => { + const signFunc = (i) => i < 0 ? -1 : i > 0 ? 1 : 0; + return { input: [i32(i)], expected: i32(signFunc(i)) }; + }), + abstract_int: () => + fullI64Range().map((i) => { + const signFunc = (i) => i < 0n ? -1n : i > 0n ? 1n : 0n; + return { input: [abstractInt(i)], expected: abstractInt(signFunc(i)) }; + }) +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.spec.js index 5bbc1527e3..7f9218e7ef 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.spec.js @@ -3,54 +3,20 @@ **/export const description = ` Execution tests for the 'sign' builtin function -S is AbstractFloat, AbstractInt, i32, f32, f16 +S is abstract-float, Type.abstractInt, i32, f32, f16 T is S or vecN @const fn sign(e: T ) -> T Returns the sign of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { - i32, - TypeF32, - TypeF16, - TypeI32, - TypeAbstractFloat } from -'../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { - fullF32Range, - fullF16Range, - fullI32Range, - fullF64Range } from -'../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, abstractIntBuiltin, builtin } from './builtin.js'; +import { d } from './sign.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('sign', { - f32: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'unfiltered', FP.f32.signInterval); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'unfiltered', FP.f16.signInterval); - }, - abstract_float: () => { - return FP.abstract.generateScalarToIntervalCases( - fullF64Range(), - 'unfiltered', - FP.abstract.signInterval - ); - }, - i32: () => - fullI32Range().map((i) => { - const signFunc = (i) => i < 0 ? -1 : i > 0 ? 1 : 0; - return { input: [i32(i)], expected: i32(signFunc(i)) }; - }) -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#sign-builtin'). desc(`abstract float tests`). @@ -61,16 +27,28 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const cases = await d.get('abstract_float'); - await run(t, abstractBuiltin('sign'), [TypeAbstractFloat], TypeAbstractFloat, t.params, cases); + await run( + t, + abstractFloatBuiltin('sign'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); }); g.test('abstract_int'). specURL('https://www.w3.org/TR/WGSL/#sign-builtin'). desc(`abstract int tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_int'); + await run(t, abstractIntBuiltin('sign'), [Type.abstractInt], Type.abstractInt, t.params, cases); +}); g.test('i32'). specURL('https://www.w3.org/TR/WGSL/#sign-builtin'). @@ -80,7 +58,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('i32'); - await run(t, builtin('sign'), [TypeI32], TypeI32, t.params, cases); + await run(t, builtin('sign'), [Type.i32], Type.i32, t.params, cases); }); g.test('f32'). @@ -91,7 +69,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('sign'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('sign'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -105,5 +83,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('sign'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('sign'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.cache.js new file mode 100644 index 0000000000..69457c8b27 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.cache.js @@ -0,0 +1,23 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { linearRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + [ + // Well-defined accuracy range + ...linearRange(-Math.PI, Math.PI, 100), + ...FP[trait].scalarRange()], + + trait === 'abstract' ? 'finite' : 'unfiltered', + // sin has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].sinInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('sin', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.spec.js index 776ba690a0..85a7a665f7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.spec.js @@ -3,54 +3,39 @@ **/export const description = ` Execution tests for the 'sin' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn sin(e: T ) -> T Returns the sine of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range, linearRange } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './sin.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('sin', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - [ - // Well-defined accuracy range - ...linearRange(-Math.PI, Math.PI, 1000), - ...fullF32Range()], - - 'unfiltered', - FP.f32.sinInterval - ); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - [ - // Well-defined accuracy range - ...linearRange(-Math.PI, Math.PI, 1000), - ...fullF16Range()], - - 'unfiltered', - FP.f16.sinInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('sin'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -66,7 +51,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('sin'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('sin'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -80,5 +65,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('sin'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('sin'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.cache.js new file mode 100644 index 0000000000..0a9b03fb0a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.cache.js @@ -0,0 +1,23 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + nonConst ? 'unfiltered' : 'finite', + // sinh has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].sinhInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('sinh', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.spec.js index a691680867..c19a84ebc2 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.spec.js @@ -3,44 +3,39 @@ **/export const description = ` Execution tests for the 'sinh' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn sinh(e: T ) -> T Returns the hyperbolic sine of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './sinh.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('sinh', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'finite', FP.f32.sinhInterval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'unfiltered', FP.f32.sinhInterval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'finite', FP.f16.sinhInterval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'unfiltered', FP.f16.sinhInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('sinh'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -50,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('sinh'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('sinh'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -64,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('sinh'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('sinh'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.cache.js new file mode 100644 index 0000000000..9a379eed1d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.cache.js @@ -0,0 +1,25 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarTripleToIntervalCases( + FP[trait].sparseScalarRange(), + FP[trait].sparseScalarRange(), + FP[trait].sparseScalarRange(), + nonConst ? 'unfiltered' : 'finite', + // smoothstep has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].smoothStepInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('smoothstep', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.spec.js index 5a5f113ab8..353f70a00c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.spec.js @@ -3,7 +3,7 @@ **/export const description = ` Execution tests for the 'smoothstep' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn smoothstep(low: T , high: T , x: T ) -> T Returns the smooth Hermite interpolation between 0 and 1. @@ -11,62 +11,33 @@ Component-wise when T is a vector. For scalar T, the result is t * t * (3.0 - 2.0 * t), where t = clamp((x - low) / (high - low), 0.0, 1.0). `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { sparseF32Range, sparseF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './smoothstep.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('smoothstep', { - f32_const: () => { - return FP.f32.generateScalarTripleToIntervalCases( - sparseF32Range(), - sparseF32Range(), - sparseF32Range(), - 'finite', - FP.f32.smoothStepInterval - ); - }, - f32_non_const: () => { - return FP.f32.generateScalarTripleToIntervalCases( - sparseF32Range(), - sparseF32Range(), - sparseF32Range(), - 'unfiltered', - FP.f32.smoothStepInterval - ); - }, - f16_const: () => { - return FP.f16.generateScalarTripleToIntervalCases( - sparseF16Range(), - sparseF16Range(), - sparseF16Range(), - 'finite', - FP.f16.smoothStepInterval - ); - }, - f16_non_const: () => { - return FP.f16.generateScalarTripleToIntervalCases( - sparseF16Range(), - sparseF16Range(), - sparseF16Range(), - 'unfiltered', - FP.f16.smoothStepInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('smoothstep'), + [Type.abstractFloat, Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -76,7 +47,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('smoothstep'), [TypeF32, TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, builtin('smoothstep'), [Type.f32, Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -90,5 +61,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('smoothstep'), [TypeF16, TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, builtin('smoothstep'), [Type.f16, Type.f16, Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.cache.js new file mode 100644 index 0000000000..af8f0ba376 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.cache.js @@ -0,0 +1,23 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16]_[non_]const +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[true, false].map((nonConst) => ({ + [`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + nonConst ? 'unfiltered' : 'finite', + // sqrt has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].sqrtInterval + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('sqrt', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.spec.js index 488db327d7..b2bc38b8ce 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.spec.js @@ -3,44 +3,39 @@ **/export const description = ` Execution tests for the 'sqrt' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn sqrt(e: T ) -> T Returns the square root of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './sqrt.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('sqrt', { - f32_const: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'finite', FP.f32.sqrtInterval); - }, - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'unfiltered', FP.f32.sqrtInterval); - }, - f16_const: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'finite', FP.f16.sqrtInterval); - }, - f16_non_const: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'unfiltered', FP.f16.sqrtInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract_const'); + await run( + t, + abstractFloatBuiltin('sqrt'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -50,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, builtin('sqrt'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('sqrt'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -64,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f16_const' : 'f16_non_const'); - await run(t, builtin('sqrt'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('sqrt'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.cache.js new file mode 100644 index 0000000000..91f05db9d4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.cache.js @@ -0,0 +1,41 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { anyOf } from '../../../../../util/compare.js';import { FP } from '../../../../../util/floating_point.js'; +import { makeCaseCache } from '../../case_cache.js'; + +// stepInterval's return value can't always be interpreted as a single acceptance +// interval, valid result may be 0.0 or 1.0 or both of them, but will never be a +// value in interval (0.0, 1.0). +// See the comment block on stepInterval for more details +const makeCase = (trait, edge, x) => { + const FPTrait = FP[trait]; + edge = FPTrait.quantize(edge); + x = FPTrait.quantize(x); + const expected = FPTrait.stepInterval(edge, x); + + // [0, 0], [1, 1], or [-∞, +∞] cases + if (expected.isPoint() || !expected.isFinite()) { + return { input: [FPTrait.scalarBuilder(edge), FPTrait.scalarBuilder(x)], expected }; + } + + // [0, 1] case, valid result is either 0.0 or 1.0. + const zeroInterval = FPTrait.toInterval(0); + const oneInterval = FPTrait.toInterval(1); + return { + input: [FPTrait.scalarBuilder(edge), FPTrait.scalarBuilder(x)], + expected: anyOf(zeroInterval, oneInterval) + }; +}; + +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait]. + sparseScalarRange(). + flatMap((edge) => FP[trait].sparseScalarRange().map((x) => makeCase(trait, edge, x))); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('step', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.spec.js index e11f25505d..86c7b64ba7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.spec.js @@ -3,63 +3,39 @@ **/export const description = ` Execution tests for the 'step' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn step(edge: T ,x: T ) -> T Returns 1.0 if edge ≤ x, and 0.0 otherwise. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { anyOf } from '../../../../../util/compare.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './step.cache.js'; export const g = makeTestGroup(GPUTest); -// stepInterval's return value can't always be interpreted as a single acceptance -// interval, valid result may be 0.0 or 1.0 or both of them, but will never be a -// value in interval (0.0, 1.0). -// See the comment block on stepInterval for more details -const makeCase = (trait, edge, x) => { - const FPTrait = FP[trait]; - edge = FPTrait.quantize(edge); - x = FPTrait.quantize(x); - const expected = FPTrait.stepInterval(edge, x); - - // [0, 0], [1, 1], or [-∞, +∞] cases - if (expected.isPoint() || !expected.isFinite()) { - return { input: [FPTrait.scalarBuilder(edge), FPTrait.scalarBuilder(x)], expected }; - } - - // [0, 1] case, valid result is either 0.0 or 1.0. - const zeroInterval = FPTrait.toInterval(0); - const oneInterval = FPTrait.toInterval(1); - return { - input: [FPTrait.scalarBuilder(edge), FPTrait.scalarBuilder(x)], - expected: anyOf(zeroInterval, oneInterval) - }; -}; - -export const d = makeCaseCache('step', { - f32: () => { - return fullF32Range().flatMap((edge) => fullF32Range().map((x) => makeCase('f32', edge, x))); - }, - f16: () => { - return fullF16Range().flatMap((edge) => fullF16Range().map((x) => makeCase('f16', edge, x))); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('step'), + [Type.abstractFloat, Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -69,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('step'), [TypeF32, TypeF32], TypeF32, t.params, cases); + await run(t, builtin('step'), [Type.f32, Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -83,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('step'), [TypeF16, TypeF16], TypeF16, t.params, cases); + await run(t, builtin('step'), [Type.f16, Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.cache.js new file mode 100644 index 0000000000..d88c4a2907 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.cache.js @@ -0,0 +1,23 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { linearRange } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + [ + // Well-defined accuracy range + ...linearRange(-Math.PI, Math.PI, 100), + ...FP[trait].scalarRange()], + + 'unfiltered', + // tan has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].tanInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('tan', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.spec.js index 72fa92f5af..af936622e2 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.spec.js @@ -3,54 +3,39 @@ **/export const description = ` Execution tests for the 'tan' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn tan(e: T ) -> T Returns the tangent of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range, linearRange } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './tan.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('tan', { - f32: () => { - return FP.f32.generateScalarToIntervalCases( - [ - // Defined accuracy range - ...linearRange(-Math.PI, Math.PI, 100), - ...fullF32Range()], - - 'unfiltered', - FP.f32.tanInterval - ); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases( - [ - // Defined accuracy range - ...linearRange(-Math.PI, Math.PI, 100), - ...fullF16Range()], - - 'unfiltered', - FP.f16.tanInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('tan'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -60,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('tan'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('tan'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -74,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('tan'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('tan'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.cache.js new file mode 100644 index 0000000000..a1ec6c9e7f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.cache.js @@ -0,0 +1,18 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + 'unfiltered', + // tanh has an inherited accuracy, so is only expected to be as accurate as f32 + FP[trait !== 'abstract' ? trait : 'f32'].tanhInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('tanh', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.spec.js index 41498f4318..9c7b348f10 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.spec.js @@ -3,38 +3,39 @@ **/export const description = ` Execution tests for the 'tanh' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn tanh(e: T ) -> T Returns the hyperbolic tangent of e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeF16 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF16Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; -import { allInputSources, run } from '../../expression.js'; +import { Type } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './tanh.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('tanh', { - f32: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'unfiltered', FP.f32.tanhInterval); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases(fullF16Range(), 'unfiltered', FP.f16.tanhInterval); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); +fn(async (t) => { + const cases = await d.get('abstract'); + await run( + t, + abstractFloatBuiltin('tanh'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); +}); g.test('f32'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). @@ -44,7 +45,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('tanh'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('tanh'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -58,5 +59,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('tanh'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('tanh'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimension.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimension.spec.js deleted file mode 100644 index 8ed1e289ee..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimension.spec.js +++ /dev/null @@ -1,160 +0,0 @@ -/** -* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/export const description = ` -Execution tests for the 'textureDimension' builtin function - -The dimensions of the texture in texels. -For textures based on cubes, the results are the dimensions of each face of the cube. -Cube faces are square, so the x and y components of the result are equal. -If level is outside the range [0, textureNumLevels(t)) then any valid value for the return type may be returned. -`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; -import { GPUTest } from '../../../../../gpu_test.js'; - -export const g = makeTestGroup(GPUTest); - -g.test('sampled'). -specURL('https://www.w3.org/TR/WGSL/#texturedimensions'). -desc( - ` -T: f32, i32, u32 - -fn textureDimensions(t: texture_1d) -> u32 -fn textureDimensions(t: texture_1d, level: u32) -> u32 -fn textureDimensions(t: texture_2d) -> vec2 -fn textureDimensions(t: texture_2d, level: u32) -> vec2 -fn textureDimensions(t: texture_2d_array) -> vec2 -fn textureDimensions(t: texture_2d_array, level: u32) -> vec2 -fn textureDimensions(t: texture_3d) -> vec3 -fn textureDimensions(t: texture_3d, level: u32) -> vec3 -fn textureDimensions(t: texture_cube) -> vec2 -fn textureDimensions(t: texture_cube, level: u32) -> vec2 -fn textureDimensions(t: texture_cube_array) -> vec2 -fn textureDimensions(t: texture_cube_array, level: u32) -> vec2 -fn textureDimensions(t: texture_multisampled_2d)-> vec2 - -Parameters: - * t: the sampled texture - * level: - - The mip level, with level 0 containing a full size version of the texture. - - If omitted, the dimensions of level 0 are returned. -` -). -params((u) => -u. -combine('texture_type', [ -'texture_1d', -'texture_2d', -'texture_2d_array', -'texture_3d', -'texture_cube', -'texture_cube_array', -'texture_multisampled_2d'] -). -beginSubcases(). -combine('sampled_type', ['f32-only', 'i32', 'u32']). -combine('level', [undefined, 0, 1, 'textureNumLevels', 'textureNumLevels+1']) -). -unimplemented(); - -g.test('depth'). -specURL('https://www.w3.org/TR/WGSL/#texturedimensions'). -desc( - ` -fn textureDimensions(t: texture_depth_2d) -> vec2 -fn textureDimensions(t: texture_depth_2d, level: u32) -> vec2 -fn textureDimensions(t: texture_depth_2d_array) -> vec2 -fn textureDimensions(t: texture_depth_2d_array, level: u32) -> vec2 -fn textureDimensions(t: texture_depth_cube) -> vec2 -fn textureDimensions(t: texture_depth_cube, level: u32) -> vec2 -fn textureDimensions(t: texture_depth_cube_array) -> vec2 -fn textureDimensions(t: texture_depth_cube_array, level: u32) -> vec2 -fn textureDimensions(t: texture_depth_multisampled_2d)-> vec2 - -Parameters: - * t: the depth or multisampled texture - * level: - - The mip level, with level 0 containing a full size version of the texture. - - If omitted, the dimensions of level 0 are returned. -` -). -params((u) => -u. -combine('texture_type', [ -'texture_depth_2d', -'texture_depth_2d_array', -'texture_depth_cube', -'texture_depth_cube_array', -'texture_depth_multisampled_2d'] -). -beginSubcases(). -combine('level', [undefined, 0, 1, 'textureNumLevels', 'textureNumLevels+1']) -). -unimplemented(); - -g.test('storage'). -specURL('https://www.w3.org/TR/WGSL/#texturedimensions'). -desc( - ` -F: rgba8unorm - rgba8snorm - rgba8uint - rgba8sint - rgba16uint - rgba16sint - rgba16float - r32uint - r32sint - r32float - rg32uint - rg32sint - rg32float - rgba32uint - rgba32sint - rgba32float -A: read, write, read_write - -fn textureDimensions(t: texture_storage_1d) -> u32 -fn textureDimensions(t: texture_storage_2d) -> vec2 -fn textureDimensions(t: texture_storage_2d_array) -> vec2 -fn textureDimensions(t: texture_storage_3d) -> vec3 - -Parameters: - * t: the storage texture -` -). -params((u) => -u. -combine('texel_format', [ -'rgba8unorm', -'rgba8snorm', -'rgba8uint', -'rgba8sint', -'rgba16uint', -'rgba16sint', -'rgba16float', -'r32uint', -'r32sint', -'r32float', -'rg32uint', -'rg32sint', -'rg32float', -'rgba32uint', -'rgba32sint', -'rgba32float'] -). -beginSubcases(). -combine('access_mode', ['read', 'write', 'read_write']) -). -unimplemented(); - -g.test('external'). -specURL('https://www.w3.org/TR/WGSL/#texturedimensions'). -desc( - ` -fn textureDimensions(t: texture_external) -> vec2 - -Parameters: - * t: the external texture -` -). -unimplemented(); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimensions.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimensions.spec.js new file mode 100644 index 0000000000..f3699e63d9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimensions.spec.js @@ -0,0 +1,518 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for the 'textureDimensions' builtin function + +The dimensions of the texture in texels. +For textures based on cubes, the results are the dimensions of each face of the cube. +Cube faces are square, so the x and y components of the result are equal. +If level is outside the range [0, textureNumLevels(t)) then any valid value for the return type may be returned. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { + kAllTextureFormats, + kColorTextureFormats, + kTextureFormatInfo, + sampleTypeForFormatAndAspect, + textureDimensionAndFormatCompatible } from +'../../../../../format_info.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { align } from '../../../../../util/math.js'; + +export const g = makeTestGroup(GPUTest); + +/// The maximum number of texture mipmap levels to test. +/// Keep this small to reduce memory and test permutations. +const kMaxMipsForTest = 3; + +/// The maximum number of texture samples to test. +const kMaxSamplesForTest = 4; + +/// All the possible GPUTextureViewDimensions. +const kAllViewDimensions = [ +'1d', +'2d', +'2d-array', +'3d', +'cube', +'cube-array']; + + +/** @returns the aspects to test for the given format */ +function aspectsForFormat(format) { + const formatInfo = kTextureFormatInfo[format]; + if (formatInfo.depth !== undefined && formatInfo.stencil !== undefined) { + return ['depth-only', 'stencil-only']; + } + return ['all']; +} + +/** @returns the sample counts to test for the given format */ +function samplesForFormat(format) { + const info = kTextureFormatInfo[format]; + return info.multisample ? [1, kMaxSamplesForTest] : [1]; +} + +/** + * @returns a list of number of texture mipmap levels to test, given the format, view dimensions and + * number of samples. + */ +function textureMipCount(params) + + + +{ + if (params.samples !== undefined && params.samples !== 1) { + // https://www.w3.org/TR/webgpu/#texture-creation + // If descriptor.sampleCount > 1: descriptor.mipLevelCount must be 1. + return [1]; + } + if (textureDimensionsForViewDimensions(params.dimensions) === '1d') { + // https://www.w3.org/TR/webgpu/#dom-gputexturedimension-2d + // Only "2d" textures may have mipmaps, be multisampled, use a compressed or depth/stencil + // format, and be used as a render attachment. + return [1]; + } + return [1, kMaxMipsForTest]; +} + +/** + * @returns a list of GPUTextureViewDescriptor.baseMipLevel to test, give the texture mipmap count. + */ +function baseMipLevel(params) { + const out = []; + for (let i = 0; i < params.textureMipCount; i++) { + out.push(i); + } + return out; +} + +/** + * @returns the argument values for the textureDimensions() `level` parameter to test. + * An `undefined` represents a call to textureDimensions() without the level argument. + */ +function textureDimensionsLevel(params) + + + +{ + if (params.samples !== undefined && params.samples > 1) { + return [undefined]; // textureDimensions() overload with `level` not available. + } + const out = [undefined]; + for (let i = 0; i < params.textureMipCount - params.baseMipLevel; i++) { + out.push(i); + } + return out; +} + +/** @returns the GPUTextureViewDimensions to test for the format and number of samples */ +function viewDimensions(params) + + +{ + if (params.samples !== undefined && params.samples > 1) { + // https://www.w3.org/TR/webgpu/#dom-gputexturedimension-2d + // Only 2d textures can be multisampled + return ['2d']; + } + + return kAllViewDimensions.filter((dim) => + textureDimensionAndFormatCompatible(textureDimensionsForViewDimensions(dim), params.format) + ); +} + +/** @returns the GPUTextureDimension for the GPUTextureViewDimension */ +function textureDimensionsForViewDimensions(dim) { + switch (dim) { + case '1d': + return '1d'; + case '2d': + case '2d-array': + case 'cube': + case 'cube-array': + return '2d'; + case '3d': + return '3d'; + } +} + +/** TestValues holds the texture size and expected return value of textureDimensions() */ + + + + + + + +/** @returns The TestValues to use for the given texture dimensions and format */ +function testValues(params) + + + + +{ + // The minimum dimension length, given the number of mipmap levels that are being tested. + const kMinLen = 1 << kMaxMipsForTest; + const kNumCubeFaces = 6; + + const formatInfo = kTextureFormatInfo[params.format]; + const bw = formatInfo.blockWidth; + const bh = formatInfo.blockHeight; + let mip = params.baseMipLevel; + if (params.textureDimensionsLevel !== undefined) { + mip += params.textureDimensionsLevel; + } + + // Magic constants to multiply the minimum texture dimensions with, to provide + // different dimension values in the test. These could be parameterized, but + // these are currently fixed to reduce the number of test parameterizations. + const kMultipleA = 2; + const kMultipleB = 3; + const kMultipleC = 4; + + switch (params.dimensions) { + case '1d':{ + const w = align(kMinLen, bw) * kMultipleA; + return { size: [w], expected: [w >>> mip] }; + } + case '2d':{ + const w = align(kMinLen, bw) * kMultipleA; + const h = align(kMinLen, bh) * kMultipleB; + return { size: [w, h], expected: [w >>> mip, h >>> mip] }; + } + case '2d-array':{ + const w = align(kMinLen, bw) * kMultipleC; + const h = align(kMinLen, bh) * kMultipleB; + return { size: [w, h, 4], expected: [w >>> mip, h >>> mip] }; + } + case '3d':{ + const w = align(kMinLen, bw) * kMultipleA; + const h = align(kMinLen, bh) * kMultipleB; + const d = kMinLen * kMultipleC; + return { + size: [w, h, d], + expected: [w >>> mip, h >>> mip, d >>> mip] + }; + } + case 'cube':{ + const l = align(kMinLen, bw) * align(kMinLen, bh) * kMultipleB; + return { + size: [l, l, kNumCubeFaces], + expected: [l >>> mip, l >>> mip] + }; + } + case 'cube-array':{ + const l = align(kMinLen, bw) * align(kMinLen, bh) * kMultipleC; + return { + size: [l, l, kNumCubeFaces * 3], + expected: [l >>> mip, l >>> mip] + }; + } + } +} + +/** + * Builds a shader module with the texture view bound to the WGSL texture with the given WGSL type, + * which calls textureDimensions(), assigning the result to an output buffer. + * This shader is executed with a compute shader, and the output buffer is compared to + * `values.expected`. + */ +function run( +t, +view, +textureType, +levelArg, +values) +{ + const outputType = values.expected.length > 1 ? `vec${values.expected.length}u` : 'u32'; + const wgsl = ` +@group(0) @binding(0) var texture : ${textureType}; +@group(0) @binding(1) var output : ${outputType}; + +@compute @workgroup_size(1) +fn main() { +output = ${ + levelArg !== undefined ? + `textureDimensions(texture, ${levelArg})` : + 'textureDimensions(texture)' + }; +} +`; + const module = t.device.createShaderModule({ + code: wgsl + }); + const pipeline = t.device.createComputePipeline({ + compute: { module }, + layout: 'auto' + }); + const outputBuffer = t.device.createBuffer({ + size: 32, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE + }); + const bindgroup = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { binding: 0, resource: view }, + { binding: 1, resource: { buffer: outputBuffer } }] + + }); + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bindgroup); + pass.dispatchWorkgroups(1); + pass.end(); + t.device.queue.submit([encoder.finish()]); + + t.expectGPUBufferValuesEqual(outputBuffer, new Uint32Array(values.expected)); +} + +/** @returns true if the GPUTextureViewDimension is valid for a storage texture */ +function dimensionsValidForStorage(dimensions) { + switch (dimensions) { + case '1d': + case '2d': + case '2d-array': + case '3d': + return true; + default: + return false; + } +} + +g.test('sampled_and_multisampled'). +specURL('https://www.w3.org/TR/WGSL/#texturedimensions'). +desc( + ` +T: f32, i32, u32 + +fn textureDimensions(t: texture_1d) -> u32 +fn textureDimensions(t: texture_1d, level: u32) -> u32 +fn textureDimensions(t: texture_2d) -> vec2 +fn textureDimensions(t: texture_2d, level: u32) -> vec2 +fn textureDimensions(t: texture_2d_array) -> vec2 +fn textureDimensions(t: texture_2d_array, level: u32) -> vec2 +fn textureDimensions(t: texture_3d) -> vec3 +fn textureDimensions(t: texture_3d, level: u32) -> vec3 +fn textureDimensions(t: texture_cube) -> vec2 +fn textureDimensions(t: texture_cube, level: u32) -> vec2 +fn textureDimensions(t: texture_cube_array) -> vec2 +fn textureDimensions(t: texture_cube_array, level: u32) -> vec2 +fn textureDimensions(t: texture_multisampled_2d)-> vec2 + +Parameters: + * t: the sampled texture + * level: + - The mip level, with level 0 containing a full size version of the texture. + - If omitted, the dimensions of level 0 are returned. +` +). +params((u) => +u. +combine('format', kAllTextureFormats). +unless((p) => kTextureFormatInfo[p.format].color?.type === 'unfilterable-float'). +expand('aspect', (u) => aspectsForFormat(u.format)). +expand('samples', (u) => samplesForFormat(u.format)). +beginSubcases(). +expand('dimensions', viewDimensions). +expand('textureMipCount', textureMipCount). +expand('baseMipLevel', baseMipLevel). +expand('textureDimensionsLevel', textureDimensionsLevel) +). +beforeAllSubcases((t) => { + const info = kTextureFormatInfo[t.params.format]; + t.skipIfTextureFormatNotSupported(t.params.format); + t.selectDeviceOrSkipTestCase(info.feature); +}). +fn((t) => { + t.skipIfTextureViewDimensionNotSupported(t.params.dimensions); + const values = testValues(t.params); + const texture = t.device.createTexture({ + size: values.size, + dimension: textureDimensionsForViewDimensions(t.params.dimensions), + ...(t.isCompatibility && { textureBindingViewDimension: t.params.dimensions }), + usage: + t.params.samples === 1 ? + GPUTextureUsage.TEXTURE_BINDING : + GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT, + format: t.params.format, + sampleCount: t.params.samples, + mipLevelCount: t.params.textureMipCount + }); + const textureView = texture.createView({ + dimension: t.params.dimensions, + aspect: t.params.aspect, + baseMipLevel: t.params.baseMipLevel + }); + + function wgslSampledTextureType() { + const base = t.params.samples !== 1 ? 'texture_multisampled' : 'texture'; + const dimensions = t.params.dimensions.replace('-', '_'); + const sampleType = sampleTypeForFormatAndAspect(t.params.format, t.params.aspect); + switch (sampleType) { + case 'depth': + case 'float': + return `${base}_${dimensions}`; + case 'uint': + return `${base}_${dimensions}`; + case 'sint': + return `${base}_${dimensions}`; + case 'unfilterable-float': + throw new Error(`'${t.params.format}' does not support sampling`); + } + } + + run(t, textureView, wgslSampledTextureType(), t.params.textureDimensionsLevel, values); +}); + +g.test('depth'). +specURL('https://www.w3.org/TR/WGSL/#texturedimensions'). +desc( + ` +fn textureDimensions(t: texture_depth_2d) -> vec2 +fn textureDimensions(t: texture_depth_2d, level: u32) -> vec2 +fn textureDimensions(t: texture_depth_2d_array) -> vec2 +fn textureDimensions(t: texture_depth_2d_array, level: u32) -> vec2 +fn textureDimensions(t: texture_depth_cube) -> vec2 +fn textureDimensions(t: texture_depth_cube, level: u32) -> vec2 +fn textureDimensions(t: texture_depth_cube_array) -> vec2 +fn textureDimensions(t: texture_depth_cube_array, level: u32) -> vec2 +fn textureDimensions(t: texture_depth_multisampled_2d)-> vec2 + +Parameters: + * t: the depth or multisampled texture + * level: + - The mip level, with level 0 containing a full size version of the texture. + - If omitted, the dimensions of level 0 are returned. +` +). +params((u) => +u. +combine('format', kAllTextureFormats). +filter((p) => !!kTextureFormatInfo[p.format].depth). +expand('aspect', (u) => aspectsForFormat(u.format)). +unless((u) => u.aspect === 'stencil-only'). +expand('samples', (u) => samplesForFormat(u.format)). +beginSubcases(). +expand('dimensions', viewDimensions). +expand('textureMipCount', textureMipCount). +expand('baseMipLevel', baseMipLevel). +expand('textureDimensionsLevel', textureDimensionsLevel) +). +beforeAllSubcases((t) => { + const info = kTextureFormatInfo[t.params.format]; + t.skipIfTextureFormatNotSupported(t.params.format); + t.selectDeviceOrSkipTestCase(info.feature); +}). +fn((t) => { + t.skipIfTextureViewDimensionNotSupported(t.params.dimensions); + const values = testValues(t.params); + const texture = t.device.createTexture({ + size: values.size, + dimension: textureDimensionsForViewDimensions(t.params.dimensions), + ...(t.isCompatibility && { textureBindingViewDimension: t.params.dimensions }), + usage: + t.params.samples === 1 ? + GPUTextureUsage.TEXTURE_BINDING : + GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT, + format: t.params.format, + sampleCount: t.params.samples, + mipLevelCount: t.params.textureMipCount + }); + const textureView = texture.createView({ + dimension: t.params.dimensions, + aspect: t.params.aspect, + baseMipLevel: t.params.baseMipLevel + }); + + function wgslDepthTextureType() { + const base = t.params.samples !== 1 ? 'texture_depth_multisampled' : 'texture_depth'; + const dimensions = t.params.dimensions.replace('-', '_'); + return `${base}_${dimensions}`; + } + + run(t, textureView, wgslDepthTextureType(), t.params.textureDimensionsLevel, values); +}); + +g.test('storage'). +specURL('https://www.w3.org/TR/WGSL/#texturedimensions'). +desc( + ` +F: rgba8unorm + rgba8snorm + rgba8uint + rgba8sint + rgba16uint + rgba16sint + rgba16float + r32uint + r32sint + r32float + rg32uint + rg32sint + rg32float + rgba32uint + rgba32sint + rgba32float +A: read, write, read_write + +fn textureDimensions(t: texture_storage_1d) -> u32 +fn textureDimensions(t: texture_storage_2d) -> vec2 +fn textureDimensions(t: texture_storage_2d_array) -> vec2 +fn textureDimensions(t: texture_storage_3d) -> vec3 + +Parameters: + * t: the storage texture +` +). +params((u) => +u. +combine('format', kColorTextureFormats). +filter((p) => kTextureFormatInfo[p.format].color?.storage === true). +expand('aspect', (u) => aspectsForFormat(u.format)). +beginSubcases(). +expand('dimensions', (u) => viewDimensions(u).filter(dimensionsValidForStorage)). +expand('textureMipCount', textureMipCount). +expand('baseMipLevel', baseMipLevel) +). +beforeAllSubcases((t) => { + const info = kTextureFormatInfo[t.params.format]; + t.skipIfTextureFormatNotSupported(t.params.format); + t.skipIfTextureFormatNotUsableAsStorageTexture(t.params.format); + t.selectDeviceOrSkipTestCase(info.feature); +}). +fn((t) => { + const values = testValues(t.params); + const texture = t.device.createTexture({ + size: values.size, + dimension: textureDimensionsForViewDimensions(t.params.dimensions), + usage: GPUTextureUsage.STORAGE_BINDING, + format: t.params.format, + mipLevelCount: t.params.textureMipCount + }); + const textureView = texture.createView({ + dimension: t.params.dimensions, + aspect: t.params.aspect, + mipLevelCount: 1, + baseMipLevel: t.params.baseMipLevel + }); + + function wgslStorageTextureType() { + const dimensions = t.params.dimensions.replace('-', '_'); + return `texture_storage_${dimensions}<${t.params.format}, write>`; + } + + run(t, textureView, wgslStorageTextureType(), undefined, values); +}); + +g.test('external'). +specURL('https://www.w3.org/TR/WGSL/#texturedimensions'). +desc( + ` +fn textureDimensions(t: texture_external) -> vec2 + +Parameters: + * t: the external texture +` +). +unimplemented(); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSample.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSample.spec.js index 7e4bbd7744..cec04b8ce8 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSample.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSample.spec.js @@ -2,25 +2,23 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` Samples a texture. - -Must only be used in a fragment shader stage. -Must only be invoked in uniform control flow. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; -import { GPUTest } from '../../../../../gpu_test.js'; +import { kEncodableTextureFormats, kTextureFormatInfo } from '../../../../../format_info.js'; +import { GPUTest, TextureTestMixin } from '../../../../../gpu_test.js'; +import { hashU32 } from '../../../../../util/math.js'; +import { kTexelRepresentationInfo } from '../../../../../util/texture/texel_data.js'; -import { generateCoordBoundaries, generateOffsets } from './utils.js'; +import { -export const g = makeTestGroup(GPUTest); + createRandomTexelView, -g.test('stage'). -specURL('https://www.w3.org/TR/WGSL/#texturesample'). -desc( - ` -Tests that 'textureSample' can only be called in 'fragment' shaders. -` -). -params((u) => u.combine('stage', ['fragment', 'vertex', 'compute'])). -unimplemented(); + putDataInTextureThenDrawAndCheckResults, + generateSamplePoints, + kSamplePointMethods } from +'./texture_utils.js'; +import { generateCoordBoundaries, generateOffsets } from './utils.js'; + +export const g = makeTestGroup(TextureTestMixin(GPUTest)); g.test('control_flow'). specURL('https://www.w3.org/TR/WGSL/#texturesample'). @@ -70,11 +68,74 @@ Parameters: Values outside of this range will result in a shader-creation error. ` ). -paramsSubcasesOnly((u) => +params((u) => u. -combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat']). -combine('coords', generateCoordBoundaries(2)). -combine('offset', generateOffsets(2)) +combine('format', kEncodableTextureFormats). +filter((t) => { + const type = kTextureFormatInfo[t.format].color?.type; + return type === 'float' || type === 'unfilterable-float'; +}). +combine('sample_points', kSamplePointMethods). +combine('addressModeU', ['clamp-to-edge', 'repeat', 'mirror-repeat']). +combine('addressModeV', ['clamp-to-edge', 'repeat', 'mirror-repeat']). +combine('minFilter', ['nearest', 'linear']). +combine('offset', [false, true]) +). +beforeAllSubcases((t) => { + const format = kTexelRepresentationInfo[t.params.format]; + t.skipIfTextureFormatNotSupported(t.params.format); + const hasFloat32 = format.componentOrder.some((c) => { + const info = format.componentInfo[c]; + return info.dataType === 'float' && info.bitLength === 32; + }); + if (hasFloat32) { + t.selectDeviceOrSkipTestCase('float32-filterable'); + } +}). +fn(async (t) => { + const descriptor = { + format: t.params.format, + size: { width: 8, height: 8 }, + usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING + }; + const texelView = createRandomTexelView(descriptor); + const calls = generateSamplePoints(50, t.params.minFilter === 'nearest', { + method: t.params.sample_points, + textureWidth: 8, + textureHeight: 8 + }).map((c, i) => { + const hash = hashU32(i) & 0xff; + return { + builtin: 'textureSample', + coordType: 'f', + coords: c, + offset: t.params.offset ? [(hash & 15) - 8, (hash >> 4) - 8] : undefined + }; + }); + const sampler = { + addressModeU: t.params.addressModeU, + addressModeV: t.params.addressModeV, + minFilter: t.params.minFilter, + magFilter: t.params.minFilter + }; + const res = await putDataInTextureThenDrawAndCheckResults( + t.device, + { texels: texelView, descriptor }, + sampler, + calls + ); + t.expectOK(res); +}); + +g.test('sampled_2d_coords,derivatives'). +specURL('https://www.w3.org/TR/WGSL/#texturesample'). +desc( + ` +fn textureSample(t: texture_2d, s: sampler, coords: vec2) -> vec4 +fn textureSample(t: texture_2d, s: sampler, coords: vec2, offset: vec2) -> vec4 + +test mip level selection based on derivatives + ` ). unimplemented(); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleBias.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleBias.spec.js index 7594f3ad5a..a11274e067 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleBias.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleBias.spec.js @@ -4,8 +4,6 @@ Execution tests for the 'textureSampleBias' builtin function Samples a texture with a bias to the mip level. -Must only be used in a fragment shader stage. -Must only be invoked in uniform control flow. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; @@ -13,26 +11,6 @@ import { generateCoordBoundaries, generateOffsets } from './utils.js'; export const g = makeTestGroup(GPUTest); -g.test('stage'). -specURL('https://www.w3.org/TR/WGSL/#texturesamplebias'). -desc( - ` -Tests that 'textureSampleBias' can only be called in 'fragment' shaders. -` -). -params((u) => u.combine('stage', ['fragment', 'vertex', 'compute'])). -unimplemented(); - -g.test('control_flow'). -specURL('https://www.w3.org/TR/WGSL/#texturesamplebias'). -desc( - ` -Tests that 'textureSampleBias' can only be called in uniform control flow. -` -). -params((u) => u.combine('stage', ['fragment', 'vertex', 'compute'])). -unimplemented(); - g.test('sampled_2d_coords'). specURL('https://www.w3.org/TR/WGSL/#texturesamplebias'). desc( diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompare.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompare.spec.js index 9f90e69f63..cb34aa652c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompare.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompare.spec.js @@ -2,9 +2,6 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` Samples a depth texture and compares the sampled depth values against a reference value. - -Must only be used in a fragment shader stage. -Must only be invoked in uniform control flow. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; @@ -12,26 +9,6 @@ import { generateCoordBoundaries, generateOffsets } from './utils.js'; export const g = makeTestGroup(GPUTest); -g.test('stage'). -specURL('https://www.w3.org/TR/WGSL/#texturesamplecompare'). -desc( - ` -Tests that 'textureSampleCompare' can only be called in 'fragment' shaders. -` -). -params((u) => u.combine('stage', ['fragment', 'vertex', 'compute'])). -unimplemented(); - -g.test('control_flow'). -specURL('https://www.w3.org/TR/WGSL/#texturesamplecompare'). -desc( - ` -Tests that 'textureSampleCompare' can only be called in uniform control flow. -` -). -params((u) => u.combine('stage', ['fragment', 'vertex', 'compute'])). -unimplemented(); - g.test('2d_coords'). specURL('https://www.w3.org/TR/WGSL/#texturesamplecompare'). desc( diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/texture_utils.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/texture_utils.js new file mode 100644 index 0000000000..65c07947d8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/texture_utils.js @@ -0,0 +1,809 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert, range, unreachable } from '../../../../../../common/util/util.js';import { float32ToUint32 } from '../../../../../util/conversion.js'; +import { align, clamp, hashU32, lerp, quantizeToF32 } from '../../../../../util/math.js'; +import { + kTexelRepresentationInfo } from + + +'../../../../../util/texture/texel_data.js'; +import { TexelView } from '../../../../../util/texture/texel_view.js'; +import { createTextureFromTexelView } from '../../../../../util/texture.js'; +import { reifyExtent3D } from '../../../../../util/unions.js'; + +function getLimitValue(v) { + switch (v) { + case Number.POSITIVE_INFINITY: + return 1000; + case Number.NEGATIVE_INFINITY: + return -1000; + default: + return v; + } +} + +function getValueBetweenMinAndMaxTexelValueInclusive( +rep, +normalized) +{ + return lerp( + getLimitValue(rep.numericRange.min), + getLimitValue(rep.numericRange.max), + normalized + ); +} + +/** + * Creates a TexelView filled with random values. + */ +export function createRandomTexelView(info) + + +{ + const rep = kTexelRepresentationInfo[info.format]; + const generator = (coords) => { + const texel = {}; + for (const component of rep.componentOrder) { + const rnd = hashU32(coords.x, coords.y, coords.z, component.charCodeAt(0)); + const normalized = clamp(rnd / 0xffffffff, { min: 0, max: 1 }); + texel[component] = getValueBetweenMinAndMaxTexelValueInclusive(rep, normalized); + } + return quantize(texel, rep); + }; + return TexelView.fromTexelsAsColors(info.format, generator); +} + + + + + + + +const kTextureCallArgNames = [ +'coords', +'mipLevel', +'arrayIndex', +'ddx', +'ddy', +'offset']; + + + + + + + + + + + + + + + + +function toArray(coords) { + if (coords instanceof Array) { + return coords; + } + return [coords]; +} + +function quantize(texel, repl) { + return repl.bitsToNumber(repl.unpackBits(new Uint8Array(repl.pack(repl.encode(texel))))); +} + +function apply(a, b, op) { + assert(a.length === b.length, `apply(${a}, ${b}): arrays must have same length`); + return a.map((v, i) => op(v, b[i])); +} + +const add = (a, b) => apply(a, b, (x, y) => x + y); + + + + + + +/** + * Returns the expect value for a WGSL builtin texture function + */ +export function expected( +call, +texture, +sampler) +{ + const rep = kTexelRepresentationInfo[texture.texels.format]; + const textureExtent = reifyExtent3D(texture.descriptor.size); + const textureSize = [textureExtent.width, textureExtent.height, textureExtent.depthOrArrayLayers]; + const addressMode = [ + sampler.addressModeU ?? 'clamp-to-edge', + sampler.addressModeV ?? 'clamp-to-edge', + sampler.addressModeW ?? 'clamp-to-edge']; + + + const load = (at) => + texture.texels.color({ + x: Math.floor(at[0]), + y: Math.floor(at[1] ?? 0), + z: Math.floor(at[2] ?? 0) + }); + + switch (call.builtin) { + case 'textureSample':{ + const coords = toArray(call.coords); + + // convert normalized to absolute texel coordinate + // ┌───┬───┬───┬───┐ + // │ a │ │ │ │ norm: a = 1/8, b = 7/8 + // ├───┼───┼───┼───┤ abs: a = 0, b = 3 + // │ │ │ │ │ + // ├───┼───┼───┼───┤ + // │ │ │ │ │ + // ├───┼───┼───┼───┤ + // │ │ │ │ b │ + // └───┴───┴───┴───┘ + let at = coords.map((v, i) => v * textureSize[i] - 0.5); + + // Apply offset in whole texel units + if (call.offset !== undefined) { + at = add(at, toArray(call.offset)); + } + + const samples = []; + + const filter = sampler.minFilter; + switch (filter) { + case 'linear':{ + // 'p0' is the lower texel for 'at' + const p0 = at.map((v) => Math.floor(v)); + // 'p1' is the higher texel for 'at' + const p1 = p0.map((v) => v + 1); + + // interpolation weights for p0 and p1 + const p1W = at.map((v, i) => v - p0[i]); + const p0W = p1W.map((v) => 1 - v); + + switch (coords.length) { + case 1: + samples.push({ at: p0, weight: p0W[0] }); + samples.push({ at: p1, weight: p1W[0] }); + break; + case 2:{ + samples.push({ at: p0, weight: p0W[0] * p0W[1] }); + samples.push({ at: [p1[0], p0[1]], weight: p1W[0] * p0W[1] }); + samples.push({ at: [p0[0], p1[1]], weight: p0W[0] * p1W[1] }); + samples.push({ at: p1, weight: p1W[0] * p1W[1] }); + break; + } + } + break; + } + case 'nearest':{ + const p = at.map((v) => Math.round(quantizeToF32(v))); + samples.push({ at: p, weight: 1 }); + break; + } + default: + unreachable(); + } + + const out = {}; + const ss = []; + for (const sample of samples) { + // Apply sampler address mode + const c = sample.at.map((v, i) => { + switch (addressMode[i]) { + case 'clamp-to-edge': + return clamp(v, { min: 0, max: textureSize[i] - 1 }); + case 'mirror-repeat':{ + const n = Math.floor(v / textureSize[i]); + v = v - n * textureSize[i]; + return (n & 1) !== 0 ? textureSize[i] - v - 1 : v; + } + case 'repeat': + return v - Math.floor(v / textureSize[i]) * textureSize[i]; + default: + unreachable(); + } + }); + const v = load(c); + ss.push(v); + for (const component of rep.componentOrder) { + out[component] = (out[component] ?? 0) + v[component] * sample.weight; + } + } + + return out; + } + case 'textureLoad':{ + return load(toArray(call.coords)); + } + } +} + +/** + * Puts random data in a texture, generates a shader that implements `calls` + * such that each call's result is written to the next consecutive texel of + * a rgba32float texture. It then checks the result of each call matches + * the expected result. + */ +export async function putDataInTextureThenDrawAndCheckResults( +device, +texture, +sampler, +calls) +{ + const results = await doTextureCalls(device, texture, sampler, calls); + const errs = []; + const rep = kTexelRepresentationInfo[texture.texels.format]; + for (let callIdx = 0; callIdx < calls.length; callIdx++) { + const call = calls[callIdx]; + const got = results[callIdx]; + const expect = expected(call, texture, sampler); + + const gULP = rep.bitsToULPFromZero(rep.numberToBits(got)); + const eULP = rep.bitsToULPFromZero(rep.numberToBits(expect)); + for (const component of rep.componentOrder) { + const g = got[component]; + const e = expect[component]; + const absDiff = Math.abs(g - e); + const ulpDiff = Math.abs(gULP[component] - eULP[component]); + const relDiff = absDiff / Math.max(Math.abs(g), Math.abs(e)); + if (ulpDiff > 3 && relDiff > 0.03) { + const desc = describeTextureCall(call); + errs.push(`component was not as expected: + call: ${desc} + component: ${component} + got: ${g} + expected: ${e} + abs diff: ${absDiff.toFixed(4)} + rel diff: ${(relDiff * 100).toFixed(2)}% + ulp diff: ${ulpDiff} + sample points: +`); + const expectedSamplePoints = [ + 'expected:', + ...(await identifySamplePoints(texture.descriptor, (texels) => { + return Promise.resolve( + expected(call, { texels, descriptor: texture.descriptor }, sampler) + ); + }))]; + + const gotSamplePoints = [ + 'got:', + ...(await identifySamplePoints( + texture.descriptor, + async (texels) => + ( + await doTextureCalls(device, { texels, descriptor: texture.descriptor }, sampler, [ + call] + ))[ + 0] + ))]; + + errs.push(layoutTwoColumns(expectedSamplePoints, gotSamplePoints).join('\n')); + errs.push('', ''); + } + } + } + + return errs.length > 0 ? new Error(errs.join('\n')) : undefined; +} + +/** + * Generates a text art grid showing which texels were sampled + * followed by a list of the samples and the weights used for each + * component. + * + * Example: + * + * 0 1 2 3 4 5 6 7 + * ┌───┬───┬───┬───┬───┬───┬───┬───┐ + * 0 │ │ │ │ │ │ │ │ │ + * ├───┼───┼───┼───┼───┼───┼───┼───┤ + * 1 │ │ │ │ │ │ │ │ a │ + * ├───┼───┼───┼───┼───┼───┼───┼───┤ + * 2 │ │ │ │ │ │ │ │ b │ + * ├───┼───┼───┼───┼───┼───┼───┼───┤ + * 3 │ │ │ │ │ │ │ │ │ + * ├───┼───┼───┼───┼───┼───┼───┼───┤ + * 4 │ │ │ │ │ │ │ │ │ + * ├───┼───┼───┼───┼───┼───┼───┼───┤ + * 5 │ │ │ │ │ │ │ │ │ + * ├───┼───┼───┼───┼───┼───┼───┼───┤ + * 6 │ │ │ │ │ │ │ │ │ + * ├───┼───┼───┼───┼───┼───┼───┼───┤ + * 7 │ │ │ │ │ │ │ │ │ + * └───┴───┴───┴───┴───┴───┴───┴───┘ + * a: at: [7, 1], weights: [R: 0.75000] + * b: at: [7, 2], weights: [R: 0.25000] + */ +async function identifySamplePoints( +info, +run) +{ + const textureSize = reifyExtent3D(info.size); + const numTexels = textureSize.width * textureSize.height; + const rep = kTexelRepresentationInfo[info.format]; + + // Identify all the texels that are sampled, and their weights. + const sampledTexelWeights = new Map(); + const unclassifiedStack = [new Set(range(numTexels, (v) => v))]; + while (unclassifiedStack.length > 0) { + // Pop the an unclassified texels stack + const unclassified = unclassifiedStack.pop(); + + // Split unclassified texels evenly into two new sets + const setA = new Set(); + const setB = new Set(); + [...unclassified.keys()].forEach((t, i) => ((i & 1) === 0 ? setA : setB).add(t)); + + // Push setB to the unclassified texels stack + if (setB.size > 0) { + unclassifiedStack.push(setB); + } + + // See if any of the texels in setA were sampled. + const results = await run( + TexelView.fromTexelsAsColors( + info.format, + (coords) => { + const isCandidate = setA.has(coords.x + coords.y * textureSize.width); + const texel = {}; + for (const component of rep.componentOrder) { + texel[component] = isCandidate ? 1 : 0; + } + return texel; + } + ) + ); + if (rep.componentOrder.some((c) => results[c] !== 0)) { + // One or more texels of setA were sampled. + if (setA.size === 1) { + // We identified a specific texel was sampled. + // As there was only one texel in the set, results holds the sampling weights. + setA.forEach((texel) => sampledTexelWeights.set(texel, results)); + } else { + // More than one texel in the set. Needs splitting. + unclassifiedStack.push(setA); + } + } + } + + // ┌───┬───┬───┬───┐ + // │ a │ │ │ │ + // ├───┼───┼───┼───┤ + // │ │ │ │ │ + // ├───┼───┼───┼───┤ + // │ │ │ │ │ + // ├───┼───┼───┼───┤ + // │ │ │ │ b │ + // └───┴───┴───┴───┘ + const letter = (idx) => String.fromCharCode(97 + idx); // 97: 'a' + const orderedTexelIndices = []; + const lines = []; + { + let line = ' '; + for (let x = 0; x < textureSize.width; x++) { + line += ` ${x} `; + } + lines.push(line); + } + { + let line = ' ┌'; + for (let x = 0; x < textureSize.width; x++) { + line += x === textureSize.width - 1 ? '───┐' : '───┬'; + } + lines.push(line); + } + for (let y = 0; y < textureSize.height; y++) { + { + let line = `${y} │`; + for (let x = 0; x < textureSize.width; x++) { + const texelIdx = x + y * textureSize.height; + const weight = sampledTexelWeights.get(texelIdx); + if (weight !== undefined) { + line += ` ${letter(orderedTexelIndices.length)} │`; + orderedTexelIndices.push(texelIdx); + } else { + line += ' │'; + } + } + lines.push(line); + } + if (y < textureSize.height - 1) { + let line = ' ├'; + for (let x = 0; x < textureSize.width; x++) { + line += x === textureSize.width - 1 ? '───┤' : '───┼'; + } + lines.push(line); + } + } + { + let line = ' └'; + for (let x = 0; x < textureSize.width; x++) { + line += x === textureSize.width - 1 ? '───┘' : '───┴'; + } + lines.push(line); + } + + orderedTexelIndices.forEach((texelIdx, i) => { + const weights = sampledTexelWeights.get(texelIdx); + const y = Math.floor(texelIdx / textureSize.width); + const x = texelIdx - y * textureSize.height; + const w = rep.componentOrder.map((c) => `${c}: ${weights[c]?.toFixed(5)}`).join(', '); + lines.push(`${letter(i)}: at: [${x}, ${y}], weights: [${w}]`); + }); + return lines; +} + +function layoutTwoColumns(columnA, columnB) { + const widthA = Math.max(...columnA.map((l) => l.length)); + const lines = Math.max(columnA.length, columnB.length); + const out = new Array(lines); + for (let line = 0; line < lines; line++) { + const a = columnA[line] ?? ''; + const b = columnB[line] ?? ''; + out[line] = `${a}${' '.repeat(widthA - a.length)} | ${b}`; + } + return out; +} + +export const kSamplePointMethods = ['texel-centre', 'spiral']; + + +/** + * Generates an array of coordinates at which to sample a texture. + */ +export function generateSamplePoints( +n, +nearest, +args) + + + + + + + + + + + + +{ + const out = []; + switch (args.method) { + case 'texel-centre':{ + for (let i = 0; i < n; i++) { + const r = hashU32(i); + const x = Math.floor(lerp(0, args.textureWidth - 1, (r & 0xffff) / 0xffff)) + 0.5; + const y = Math.floor(lerp(0, args.textureHeight - 1, (r >>> 16) / 0xffff)) + 0.5; + out.push([x / args.textureWidth, y / args.textureHeight]); + } + break; + } + case 'spiral':{ + for (let i = 0; i < n; i++) { + const f = i / (Math.max(n, 2) - 1); + const r = (args.radius ?? 1.5) * f; + const a = (args.loops ?? 2) * 2 * Math.PI * f; + out.push([0.5 + r * Math.cos(a), 0.5 + r * Math.sin(a)]); + } + break; + } + } + // Samplers across devices use different methods to interpolate. + // Quantizing the texture coordinates seems to hit coords that produce + // comparable results to our computed results. + // Note: This value works with 8x8 textures. Other sizes have not been tested. + // Values that worked for reference: + // Win 11, NVidia 2070 Super: 16 + // Linux, AMD Radeon Pro WX 3200: 256 + // MacOS, M1 Mac: 256 + const kSubdivisionsPerTexel = 4; + const q = [args.textureWidth * kSubdivisionsPerTexel, args.textureHeight * kSubdivisionsPerTexel]; + return out.map( + (c) => + c.map((v, i) => { + // Quantize to kSubdivisionsPerPixel + const v1 = Math.floor(v * q[i]); + // If it's nearest and we're on the edge of a texel then move us off the edge + // since the edge could choose one texel or another in nearest mode + const v2 = nearest && v1 % kSubdivisionsPerTexel === 0 ? v1 + 1 : v1; + // Convert back to texture coords + return v2 / q[i]; + }) + ); +} + +function wgslTypeFor(data, type) { + if (data instanceof Array) { + switch (data.length) { + case 2: + return `vec2${type}`; + case 3: + return `vec3${type}`; + } + } + return '${type}32'; +} + +function wgslExpr(data) { + if (data instanceof Array) { + switch (data.length) { + case 2: + return `vec2(${data.map((v) => v.toString()).join(', ')})`; + case 3: + return `vec3(${data.map((v) => v.toString()).join(', ')})`; + } + } + return data.toString(); +} + +function binKey(call) { + const keys = []; + for (const name of kTextureCallArgNames) { + const value = call[name]; + if (value !== undefined) { + if (name === 'offset') { + // offset must be a constant expression + keys.push(`${name}: ${wgslExpr(value)}`); + } else { + keys.push(`${name}: ${wgslTypeFor(value, call.coordType)}`); + } + } + } + return `${call.builtin}(${keys.join(', ')})`; +} + +function buildBinnedCalls(calls) { + const args = ['T']; // All texture builtins take the texture as the first argument + const fields = []; + const data = []; + + const prototype = calls[0]; + if (prototype.builtin.startsWith('textureSample')) { + // textureSample*() builtins take a sampler as the second argument + args.push('S'); + } + + for (const name of kTextureCallArgNames) { + const value = prototype[name]; + if (value !== undefined) { + if (name === 'offset') { + args.push(`/* offset */ ${wgslExpr(value)}`); + } else { + args.push(`args.${name}`); + fields.push(`@align(16) ${name} : ${wgslTypeFor(value, prototype.coordType)}`); + } + } + } + + for (const call of calls) { + for (const name of kTextureCallArgNames) { + const value = call[name]; + assert( + prototype[name] === undefined === (value === undefined), + 'texture calls are not binned correctly' + ); + if (value !== undefined && name !== 'offset') { + const bitcastToU32 = (value) => { + if (calls[0].coordType === 'f') { + return float32ToUint32(value); + } + return value; + }; + if (value instanceof Array) { + for (const c of value) { + data.push(bitcastToU32(c)); + } + } else { + data.push(bitcastToU32(value)); + } + // All fields are aligned to 16 bytes. + while ((data.length & 3) !== 0) { + data.push(0); + } + } + } + } + + const expr = `${prototype.builtin}(${args.join(', ')})`; + + return { expr, fields, data }; +} + +function binCalls(calls) { + const map = new Map(); // key to bin index + const bins = []; + calls.forEach((call, callIdx) => { + const key = binKey(call); + const binIdx = map.get(key); + if (binIdx === undefined) { + map.set(key, bins.length); + bins.push([callIdx]); + } else { + bins[binIdx].push(callIdx); + } + }); + return bins; +} + +export function describeTextureCall(call) { + const args = ['texture: T']; + if (call.builtin.startsWith('textureSample')) { + args.push('sampler: S'); + } + for (const name of kTextureCallArgNames) { + const value = call[name]; + if (value !== undefined) { + args.push(`${name}: ${wgslExpr(value)}`); + } + } + return `${call.builtin}(${args.join(', ')})`; +} + +/** + * Given a list of "calls", each one of which has a texture coordinate, + * generates a fragment shader that uses the fragment position as an index + * (position.y * 256 + position.x) That index is then used to look up a + * coordinate from a storage buffer which is used to call the WGSL texture + * function to read/sample the texture, and then write to an rgba32float + * texture. We then read the rgba32float texture for the per "call" results. + * + * Calls are "binned" by call parameters. Each bin has its own structure and + * field in the storage buffer. This allows the calls to be non-homogenous and + * each have their own data type for coordinates. + */ +export async function doTextureCalls( +device, +texture, +sampler, +calls) +{ + let structs = ''; + let body = ''; + let dataFields = ''; + const data = []; + let callCount = 0; + const binned = binCalls(calls); + binned.forEach((binCalls, binIdx) => { + const b = buildBinnedCalls(binCalls.map((callIdx) => calls[callIdx])); + structs += `struct Args${binIdx} { + ${b.fields.join(', \n')} +} +`; + dataFields += ` args${binIdx} : array, +`; + body += ` + { + let is_active = (frag_idx >= ${callCount}) & (frag_idx < ${callCount + binCalls.length}); + let args = data.args${binIdx}[frag_idx - ${callCount}]; + let call = ${b.expr}; + result = select(result, call, is_active); + } +`; + callCount += binCalls.length; + data.push(...b.data); + }); + + const dataBuffer = device.createBuffer({ + size: data.length * 4, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE + }); + device.queue.writeBuffer(dataBuffer, 0, new Uint32Array(data)); + + const rtWidth = 256; + const renderTarget = device.createTexture({ + format: 'rgba32float', + size: { width: rtWidth, height: Math.ceil(calls.length / rtWidth) }, + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT + }); + + const code = ` +${structs} + +struct Data { +${dataFields} +} + +@vertex +fn vs_main(@builtin(vertex_index) vertex_index : u32) -> @builtin(position) vec4f { + let positions = array( + vec4f(-1, 1, 0, 1), vec4f( 1, 1, 0, 1), + vec4f(-1, -1, 0, 1), vec4f( 1, -1, 0, 1), + ); + return positions[vertex_index]; +} + +@group(0) @binding(0) var T : texture_2d; +@group(0) @binding(1) var S : sampler; +@group(0) @binding(2) var data : Data; + +@fragment +fn fs_main(@builtin(position) frag_pos : vec4f) -> @location(0) vec4f { + let frag_idx = u32(frag_pos.x) + u32(frag_pos.y) * ${renderTarget.width}; + var result : vec4f; +${body} + return result; +} +`; + const shaderModule = device.createShaderModule({ code }); + + const pipeline = device.createRenderPipeline({ + layout: 'auto', + vertex: { module: shaderModule, entryPoint: 'vs_main' }, + fragment: { + module: shaderModule, + entryPoint: 'fs_main', + targets: [{ format: renderTarget.format }] + }, + primitive: { topology: 'triangle-strip', cullMode: 'none' } + }); + + const gpuTexture = createTextureFromTexelView(device, texture.texels, texture.descriptor); + const gpuSampler = device.createSampler(sampler); + + const bindGroup = device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { binding: 0, resource: gpuTexture.createView() }, + { binding: 1, resource: gpuSampler }, + { binding: 2, resource: { buffer: dataBuffer } }] + + }); + + const bytesPerRow = align(16 * renderTarget.width, 256); + const resultBuffer = device.createBuffer({ + size: renderTarget.height * bytesPerRow, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ + }); + const encoder = device.createCommandEncoder(); + + const renderPass = encoder.beginRenderPass({ + colorAttachments: [{ view: renderTarget.createView(), loadOp: 'clear', storeOp: 'store' }] + }); + + renderPass.setPipeline(pipeline); + renderPass.setBindGroup(0, bindGroup); + renderPass.draw(4); + renderPass.end(); + encoder.copyTextureToBuffer( + { texture: renderTarget }, + { buffer: resultBuffer, bytesPerRow }, + { width: renderTarget.width, height: renderTarget.height } + ); + device.queue.submit([encoder.finish()]); + + await resultBuffer.mapAsync(GPUMapMode.READ); + + const view = TexelView.fromTextureDataByReference( + renderTarget.format, + new Uint8Array(resultBuffer.getMappedRange()), + { + bytesPerRow, + rowsPerImage: renderTarget.height, + subrectOrigin: [0, 0, 0], + subrectSize: [renderTarget.width, renderTarget.height] + } + ); + + let outIdx = 0; + const out = new Array(calls.length); + for (const bin of binned) { + for (const callIdx of bin) { + const x = outIdx % rtWidth; + const y = Math.floor(outIdx / rtWidth); + out[callIdx] = view.color({ x, y, z: 0 }); + outIdx++; + } + } + + renderTarget.destroy(); + gpuTexture.destroy(); + resultBuffer.destroy(); + + return out; +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.cache.js new file mode 100644 index 0000000000..a1d6c0d6f6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.cache.js @@ -0,0 +1,27 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract]_matCxR_[non_]const +// abstract_matCxR_non_const is empty and not used +const cases = ['f32', 'f16', 'abstract']. +flatMap((trait) => +[2, 3, 4].flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`${trait}_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateMatrixToMatrixCases( + FP[trait].sparseMatrixRange(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP[trait].transposeInterval + ); + } +})) +) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('transpose', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.spec.js index 0e1003b9d6..8e1c70e37f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.spec.js @@ -3,80 +3,19 @@ **/export const description = ` Execution tests for the 'transpose' builtin function -T is AbstractFloat, f32, or f16 +T is abstract-float, f32, or f16 @const transpose(e: matRxC ) -> matCxR Returns the transpose of e. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeF16, TypeF32, TypeMat } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { - sparseMatrixF16Range, - sparseMatrixF32Range, - sparseMatrixF64Range } from -'../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './transpose.cache.js'; export const g = makeTestGroup(GPUTest); -// Cases: f32_matCxR_[non_]const -const f32_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`f32_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateMatrixToMatrixCases( - sparseMatrixF32Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f32.transposeInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: f16_matCxR_[non_]const -const f16_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`f16_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateMatrixToMatrixCases( - sparseMatrixF16Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f16.transposeInterval - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: abstract_matCxR -const abstract_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].map((rows) => ({ - [`abstract_mat${cols}x${rows}`]: () => { - return FP.abstract.generateMatrixToMatrixCases( - sparseMatrixF64Range(cols, rows), - 'finite', - FP.abstract.transposeInterval - ); - } -})) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('transpose', { - ...f32_cases, - ...f16_cases, - ...abstract_cases -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions'). desc(`abstract float tests`). @@ -89,12 +28,12 @@ combine('rows', [2, 3, 4]) fn(async (t) => { const cols = t.params.cols; const rows = t.params.rows; - const cases = await d.get(`abstract_mat${cols}x${rows}`); + const cases = await d.get(`abstract_mat${cols}x${rows}_const`); await run( t, - abstractBuiltin('transpose'), - [TypeMat(cols, rows, TypeAbstractFloat)], - TypeMat(rows, cols, TypeAbstractFloat), + abstractFloatBuiltin('transpose'), + [Type.mat(cols, rows, Type.abstractFloat)], + Type.mat(rows, cols, Type.abstractFloat), t.params, cases ); @@ -120,8 +59,8 @@ fn(async (t) => { await run( t, builtin('transpose'), - [TypeMat(cols, rows, TypeF32)], - TypeMat(rows, cols, TypeF32), + [Type.mat(cols, rows, Type.f32)], + Type.mat(rows, cols, Type.f32), t.params, cases ); @@ -150,8 +89,8 @@ fn(async (t) => { await run( t, builtin('transpose'), - [TypeMat(cols, rows, TypeF16)], - TypeMat(rows, cols, TypeF16), + [Type.mat(cols, rows, Type.f16)], + Type.mat(rows, cols, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.cache.js new file mode 100644 index 0000000000..33b77ee5d0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.cache.js @@ -0,0 +1,17 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { makeCaseCache } from '../../case_cache.js'; +// Cases: [f32|f16|abstract] +const cases = ['f32', 'f16', 'abstract']. +map((trait) => ({ + [`${trait}`]: () => { + return FP[trait].generateScalarToIntervalCases( + FP[trait].scalarRange(), + 'unfiltered', + FP[trait].truncInterval + ); + } +})). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('trunc', cases); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.spec.js index 042c02875d..b2af7b2e03 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.spec.js @@ -3,39 +3,21 @@ **/export const description = ` Execution tests for the 'trunc' builtin function -S is AbstractFloat, f32, f16 +S is abstract-float, f32, f16 T is S or vecN @const fn trunc(e: T ) -> T Returns the nearest whole number whose absolute value is less than or equal to e. Component-wise when T is a vector. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeAbstractFloat, TypeF16, TypeF32 } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullF32Range, fullF64Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { abstractBuiltin, builtin } from './builtin.js'; +import { abstractFloatBuiltin, builtin } from './builtin.js'; +import { d } from './trunc.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('trunc', { - f32: () => { - return FP.f32.generateScalarToIntervalCases(fullF32Range(), 'unfiltered', FP.f32.truncInterval); - }, - f16: () => { - return FP.f16.generateScalarToIntervalCases(fullF32Range(), 'unfiltered', FP.f16.truncInterval); - }, - abstract: () => { - return FP.abstract.generateScalarToIntervalCases( - fullF64Range(), - 'unfiltered', - FP.abstract.truncInterval - ); - } -}); - g.test('abstract_float'). specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions'). desc(`abstract float tests`). @@ -46,7 +28,14 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const cases = await d.get('abstract'); - await run(t, abstractBuiltin('trunc'), [TypeAbstractFloat], TypeAbstractFloat, t.params, cases); + await run( + t, + abstractFloatBuiltin('trunc'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases + ); }); g.test('f32'). @@ -57,7 +46,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, builtin('trunc'), [TypeF32], TypeF32, t.params, cases); + await run(t, builtin('trunc'), [Type.f32], Type.f32, t.params, cases); }); g.test('f16'). @@ -71,5 +60,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, builtin('trunc'), [TypeF16], TypeF16, t.params, cases); + await run(t, builtin('trunc'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.cache.js new file mode 100644 index 0000000000..d6415bb6d6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.cache.js @@ -0,0 +1,20 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { fullU32Range } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +export const d = makeCaseCache('unpack2x16float', { + u32_const: () => { + return FP.f32.generateU32ToIntervalCases( + fullU32Range(), + 'finite', + FP.f32.unpack2x16floatInterval + ); + }, + u32_non_const: () => { + return FP.f32.generateU32ToIntervalCases( + fullU32Range(), + 'unfiltered', + FP.f32.unpack2x16floatInterval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.spec.js index ca91659889..39e1ca28e5 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.spec.js @@ -7,33 +7,14 @@ Component i of the result is the f32 representation of v, where v is the interpretation of bits 16×i through 16×i+15 of e as an IEEE-754 binary16 value. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeU32, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullU32Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; +import { d } from './unpack2x16float.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unpack2x16float', { - u32_const: () => { - return FP.f32.generateU32ToIntervalCases( - fullU32Range(), - 'finite', - FP.f32.unpack2x16floatInterval - ); - }, - u32_non_const: () => { - return FP.f32.generateU32ToIntervalCases( - fullU32Range(), - 'unfiltered', - FP.f32.unpack2x16floatInterval - ); - } -}); - g.test('unpack'). specURL('https://www.w3.org/TR/WGSL/#unpack-builtin-functions'). desc( @@ -44,5 +25,5 @@ desc( params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const'); - await run(t, builtin('unpack2x16float'), [TypeU32], TypeVec(2, TypeF32), t.params, cases); + await run(t, builtin('unpack2x16float'), [Type.u32], Type.vec2f, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.cache.js new file mode 100644 index 0000000000..f29307ae60 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.cache.js @@ -0,0 +1,20 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { fullU32Range } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +export const d = makeCaseCache('unpack2x16snorm', { + u32_const: () => { + return FP.f32.generateU32ToIntervalCases( + fullU32Range(), + 'finite', + FP.f32.unpack2x16snormInterval + ); + }, + u32_non_const: () => { + return FP.f32.generateU32ToIntervalCases( + fullU32Range(), + 'unfiltered', + FP.f32.unpack2x16snormInterval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.spec.js index d8811b5070..f2b36e2ceb 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.spec.js @@ -7,33 +7,14 @@ Component i of the result is max(v ÷ 32767, -1), where v is the interpretation of bits 16×i through 16×i+15 of e as a twos-complement signed integer. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeU32, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullU32Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; +import { d } from './unpack2x16snorm.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unpack2x16snorm', { - u32_const: () => { - return FP.f32.generateU32ToIntervalCases( - fullU32Range(), - 'finite', - FP.f32.unpack2x16snormInterval - ); - }, - u32_non_const: () => { - return FP.f32.generateU32ToIntervalCases( - fullU32Range(), - 'unfiltered', - FP.f32.unpack2x16snormInterval - ); - } -}); - g.test('unpack'). specURL('https://www.w3.org/TR/WGSL/#unpack-builtin-functions'). desc( @@ -44,5 +25,5 @@ desc( params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const'); - await run(t, builtin('unpack2x16snorm'), [TypeU32], TypeVec(2, TypeF32), t.params, cases); + await run(t, builtin('unpack2x16snorm'), [Type.u32], Type.vec2f, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.cache.js new file mode 100644 index 0000000000..ba72ff60a7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.cache.js @@ -0,0 +1,20 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { fullU32Range } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +export const d = makeCaseCache('unpack2x16unorm', { + u32_const: () => { + return FP.f32.generateU32ToIntervalCases( + fullU32Range(), + 'finite', + FP.f32.unpack2x16unormInterval + ); + }, + u32_non_const: () => { + return FP.f32.generateU32ToIntervalCases( + fullU32Range(), + 'unfiltered', + FP.f32.unpack2x16unormInterval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.spec.js index 3e18938080..37547b1b3c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.spec.js @@ -7,33 +7,14 @@ Component i of the result is v ÷ 65535, where v is the interpretation of bits 16×i through 16×i+15 of e as an unsigned integer. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeU32, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullU32Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; +import { d } from './unpack2x16unorm.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unpack2x16unorm', { - u32_const: () => { - return FP.f32.generateU32ToIntervalCases( - fullU32Range(), - 'finite', - FP.f32.unpack2x16unormInterval - ); - }, - u32_non_const: () => { - return FP.f32.generateU32ToIntervalCases( - fullU32Range(), - 'unfiltered', - FP.f32.unpack2x16unormInterval - ); - } -}); - g.test('unpack'). specURL('https://www.w3.org/TR/WGSL/#unpack-builtin-functions'). desc( @@ -44,5 +25,5 @@ desc( params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const'); - await run(t, builtin('unpack2x16unorm'), [TypeU32], TypeVec(2, TypeF32), t.params, cases); + await run(t, builtin('unpack2x16unorm'), [Type.u32], Type.vec2f, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.cache.js new file mode 100644 index 0000000000..aa9331fa49 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.cache.js @@ -0,0 +1,20 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { fullU32Range } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +export const d = makeCaseCache('unpack4x8snorm', { + u32_const: () => { + return FP.f32.generateU32ToIntervalCases( + fullU32Range(), + 'finite', + FP.f32.unpack4x8snormInterval + ); + }, + u32_non_const: () => { + return FP.f32.generateU32ToIntervalCases( + fullU32Range(), + 'unfiltered', + FP.f32.unpack4x8snormInterval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.spec.js index 3684db6474..59043efbfa 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.spec.js @@ -7,33 +7,14 @@ Component i of the result is max(v ÷ 127, -1), where v is the interpretation of bits 8×i through 8×i+7 of e as a twos-complement signed integer. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeU32, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullU32Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; +import { d } from './unpack4x8snorm.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unpack4x8snorm', { - u32_const: () => { - return FP.f32.generateU32ToIntervalCases( - fullU32Range(), - 'finite', - FP.f32.unpack4x8snormInterval - ); - }, - u32_non_const: () => { - return FP.f32.generateU32ToIntervalCases( - fullU32Range(), - 'unfiltered', - FP.f32.unpack4x8snormInterval - ); - } -}); - g.test('unpack'). specURL('https://www.w3.org/TR/WGSL/#unpack-builtin-functions'). desc( @@ -44,5 +25,5 @@ desc( params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const'); - await run(t, builtin('unpack4x8snorm'), [TypeU32], TypeVec(4, TypeF32), t.params, cases); + await run(t, builtin('unpack4x8snorm'), [Type.u32], Type.vec4f, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.cache.js new file mode 100644 index 0000000000..c012505d3a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.cache.js @@ -0,0 +1,20 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../../util/floating_point.js';import { fullU32Range } from '../../../../../util/math.js';import { makeCaseCache } from '../../case_cache.js'; + +export const d = makeCaseCache('unpack4x8unorm', { + u32_const: () => { + return FP.f32.generateU32ToIntervalCases( + fullU32Range(), + 'finite', + FP.f32.unpack4x8unormInterval + ); + }, + u32_non_const: () => { + return FP.f32.generateU32ToIntervalCases( + fullU32Range(), + 'unfiltered', + FP.f32.unpack4x8unormInterval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.spec.js index 80330885ad..755c490c0c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.spec.js @@ -7,33 +7,14 @@ Component i of the result is v ÷ 255, where v is the interpretation of bits 8× through 8×i+7 of e as an unsigned integer. `;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF32, TypeU32, TypeVec } from '../../../../../util/conversion.js'; -import { FP } from '../../../../../util/floating_point.js'; -import { fullU32Range } from '../../../../../util/math.js'; -import { makeCaseCache } from '../../case_cache.js'; +import { Type } from '../../../../../util/conversion.js'; import { allInputSources, run } from '../../expression.js'; import { builtin } from './builtin.js'; +import { d } from './unpack4x8unorm.cache.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unpack4x8unorm', { - u32_const: () => { - return FP.f32.generateU32ToIntervalCases( - fullU32Range(), - 'finite', - FP.f32.unpack4x8unormInterval - ); - }, - u32_non_const: () => { - return FP.f32.generateU32ToIntervalCases( - fullU32Range(), - 'unfiltered', - FP.f32.unpack4x8unormInterval - ); - } -}); - g.test('unpack'). specURL('https://www.w3.org/TR/WGSL/#unpack-builtin-functions'). desc( @@ -44,5 +25,5 @@ desc( params((u) => u.combine('inputSource', allInputSources)). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const'); - await run(t, builtin('unpack4x8unorm'), [TypeU32], TypeVec(4, TypeF32), t.params, cases); + await run(t, builtin('unpack4x8unorm'), [Type.u32], Type.vec4f, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4xI8.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4xI8.spec.js new file mode 100644 index 0000000000..30bd91d235 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4xI8.spec.js @@ -0,0 +1,56 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for the 'unpack4xI8' builtin function + +@const fn unpack4xI8(e: u32) -> vec4 +e is interpreted as a vector with four 8-bit signed integer components. Unpack e into a vec4 +with sign extension. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { u32, toVector, i32, Type } from '../../../../../util/conversion.js'; + +import { allInputSources, run } from '../../expression.js'; + +import { builtin } from './builtin.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('basic'). +specURL('https://www.w3.org/TR/WGSL/#unpack4xI8-builtin'). +desc( + ` +@const fn unpack4xI8(e: u32) -> vec4 + ` +). +params((u) => u.combine('inputSource', allInputSources)). +fn(async (t) => { + const cfg = t.params; + + const unpack4xI8 = (e) => { + const result = [0, 0, 0, 0]; + for (let i = 0; i < 4; ++i) { + let intValue = e >> 8 * i & 0xff; + if (intValue > 127) { + intValue -= 256; + } + result[i] = intValue; + } + return result; + }; + + const testInputs = [ + 0, 0x01020304, 0xfcfdfeff, 0x040302ff, 0x0403fe01, 0x04fd0201, 0xfc030201, 0xfcfdfe01, + 0xfcfd02ff, 0xfc03feff, 0x04fdfeff, 0x0403feff, 0x04fd02ff, 0xfc0302ff, 0x04fdfe01, + 0xfc03fe01, 0xfcfd0201, 0x80817f7e]; + + + const makeCase = (e) => { + return { input: [u32(e)], expected: toVector(unpack4xI8(e), i32) }; + }; + const cases = testInputs.flatMap((v) => { + return [makeCase(v)]; + }); + + await run(t, builtin('unpack4xI8'), [Type.u32], Type.vec4i, cfg, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4xU8.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4xU8.spec.js new file mode 100644 index 0000000000..9711650ec0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4xU8.spec.js @@ -0,0 +1,48 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for the 'unpack4xU8' builtin function + +@const fn unpack4xU8(e: u32) -> vec4 +e is interpreted as a vector with four 8-bit unsigned integer components. Unpack e into a vec4 +with zero extension. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { u32, toVector, Type } from '../../../../../util/conversion.js'; + +import { allInputSources, run } from '../../expression.js'; + +import { builtin } from './builtin.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('basic'). +specURL('https://www.w3.org/TR/WGSL/#unpack4xU8-builtin'). +desc( + ` +@const fn unpack4xU8(e: u32) -> vec4 + ` +). +params((u) => u.combine('inputSource', allInputSources)). +fn(async (t) => { + const cfg = t.params; + + const unpack4xU8 = (e) => { + const result = [0, 0, 0, 0]; + for (let i = 0; i < 4; ++i) { + result[i] = e >> 8 * i & 0xff; + } + return result; + }; + + const testInputs = [0, 0x08060402, 0xffffffff, 0xfefdfcfb]; + + const makeCase = (e) => { + return { input: [u32(e)], expected: toVector(unpack4xU8(e), u32) }; + }; + const cases = testInputs.flatMap((v) => { + return [makeCase(v)]; + }); + + await run(t, builtin('unpack4xU8'), [Type.u32], Type.vec4u, cfg, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/workgroupUniformLoad.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/workgroupUniformLoad.spec.js new file mode 100644 index 0000000000..0a08baba0d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/workgroupUniformLoad.spec.js @@ -0,0 +1,182 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Executes a control barrier synchronization function that affects memory and atomic operations in the workgroup address space. +`; // NOTE: The control barrier executed by this builtin is tested in the memory_model tests. + +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { + + + iterRange } from +'../../../../../../common/util/util.js'; +import { GPUTest } from '../../../../../gpu_test.js'; +import { checkElementsEqualGenerated } from '../../../../../util/check_contents.js'; + +export const g = makeTestGroup(GPUTest); + + + + + + + + + + + + + + +// A list of types configurations used for the workgroup variable. +const kTypes = { + bool: { + store_val: `true`, + expected: new Uint32Array([1]), + host_type: 'u32', + to_host: (x) => `u32(${x})` + }, + u32: { + store_val: `42`, + expected: new Uint32Array([42]) + }, + vec4u: { + store_val: `vec4u(42, 1, 0xffffffff, 777)`, + expected: new Uint32Array([42, 1, 0xffffffff, 777]) + }, + mat3x2f: { + store_val: `mat3x2(42, 1, 65536, -42, -1, -65536)`, + expected: new Float32Array([42, 1, 65536, -42, -1, -65536]) + }, + 'array': { + store_val: `array(42, 1, 0xffffffff, 777)`, + expected: new Uint32Array([42, 1, 0xffffffff, 777]) + }, + SimpleStruct: { + decls: 'struct SimpleStruct { a: u32, b: u32, c: u32, d: u32, }', + store_val: `SimpleStruct(42, 1, 0xffffffff, 777)`, + expected: new Uint32Array([42, 1, 0xffffffff, 777]) + }, + ComplexStruct: { + decls: `struct Inner { v: vec4u, } + struct ComplexStruct { + a: array, + @size(28) b: vec4u, + c: u32 + } + const v = vec4(42, 1, 0xffffffff, 777); + const rhs = ComplexStruct( + array(Inner(v.xyzw), Inner(v.yzwx), Inner(v.zwxy), Inner(v.wxyz)), + v.xzxz, + 0x12345678, + );`, + store_val: `rhs`, + expected: new Uint32Array([ + // v.xyzw + 42, 1, 0xffffffff, 777, + // v.yzwx + 1, 0xffffffff, 777, 42, + // v.zwxy + 0xffffffff, 777, 42, 1, + // v.wxyz + 777, 42, 1, 0xffffffff, + // v.xzxz + 42, 0xffffffff, 42, 0xffffffff, + // 12 bytes of padding + 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x12345678] + ) + } +}; + +g.test('types'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#workgroupUniformLoad-builtin'). +desc( + `Test that the result of a workgroupUniformLoad is the value previously stored to the workgroup variable, for a variety of types. + ` +). +params((u) => +u.combine('type', keysOf(kTypes)).combine('wgsize', [ +[1, 1], +[3, 7], +[1, 128], +[16, 16]] +) +). +fn((t) => { + const type = kTypes[t.params.type]; + const wgsize_x = t.params.wgsize[0]; + const wgsize_y = t.params.wgsize[1]; + const num_invocations = wgsize_x * wgsize_y; + const num_words_per_invocation = type.expected.length; + const total_host_words = num_invocations * num_words_per_invocation; + + t.skipIf( + num_invocations > t.device.limits.maxComputeInvocationsPerWorkgroup, + `num_invocations (${num_invocations}) > maxComputeInvocationsPerWorkgroup (${t.device.limits.maxComputeInvocationsPerWorkgroup})` + ); + + let load = `workgroupUniformLoad(&wgvar)`; + if (type.to_host) { + load = type.to_host(load); + } + + // Construct a shader that stores a value to workgroup variable and then loads it using + // workgroupUniformLoad() in every invocation, copying the results back to a storage buffer. + const code = ` + ${type.decls ? type.decls : ''} + + @group(0) @binding(0) var buffer : array<${ + type.host_type ? type.host_type : t.params.type + }, ${num_invocations}>; + + var wgvar : ${t.params.type}; + + @compute @workgroup_size(${wgsize_x}, ${wgsize_y}) + fn main(@builtin(local_invocation_index) lid: u32) { + if (lid == ${num_invocations - 1}) { + wgvar = ${type.store_val}; + } + buffer[lid] = ${load}; + } + `; + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ code }), + entryPoint: 'main' + } + }); + + // Allocate a buffer and fill it with 0xdeadbeef values. + const outputBuffer = t.makeBufferWithContents( + new Uint32Array([...iterRange(total_host_words, (_i) => 0xdeadbeef)]), + GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC + ); + const bindGroup = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [{ binding: 0, resource: { buffer: outputBuffer } }] + }); + + // Run the shader. + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bindGroup); + pass.dispatchWorkgroups(1); + pass.end(); + t.queue.submit([encoder.finish()]); + + // Check that the output matches the expected values for each invocation. + t.expectGPUBufferValuesPassCheck( + outputBuffer, + (data) => + checkElementsEqualGenerated(data, (i) => { + return Number(type.expected[i % num_words_per_invocation]); + }), + { + type: type.expected.constructor, + typedLength: total_host_words + } + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/user/ptr_params.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/user/ptr_params.spec.js new file mode 100644 index 0000000000..af36316c7d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/user/ptr_params.spec.js @@ -0,0 +1,849 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +User function call tests for pointer parameters. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../../gpu_test.js'; + +export const g = makeTestGroup(GPUTest); + +function wgslTypeDecl(kind) { + switch (kind) { + case 'vec4i': + return ` +alias T = vec4i; +`; + case 'array': + return ` +alias T = array; +`; + case 'struct': + return ` +struct S { +a : i32, +b : u32, +c : i32, +d : u32, +} +alias T = S; +`; + } +} + +function valuesForType(kind) { + switch (kind) { + case 'vec4i': + return new Uint32Array([1, 2, 3, 4]); + case 'array': + return new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); + case 'struct': + return new Uint32Array([1, 2, 3, 4]); + } +} + +function run( +t, +wgsl, +inputUsage, +input, +expected) +{ + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ code: wgsl }), + entryPoint: 'main' + } + }); + + const inputBuffer = t.makeBufferWithContents( + input, + inputUsage === 'uniform' ? GPUBufferUsage.UNIFORM : GPUBufferUsage.STORAGE + ); + + const outputBuffer = t.device.createBuffer({ + size: expected.buffer.byteLength, + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC + }); + + const bindGroup = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { binding: 0, resource: { buffer: inputBuffer } }, + { binding: 1, resource: { buffer: outputBuffer } }] + + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bindGroup); + pass.dispatchWorkgroups(1); + pass.end(); + t.queue.submit([encoder.finish()]); + + t.expectGPUBufferValuesEqual(outputBuffer, expected); +} + +g.test('read_full_object'). +desc('Test a pointer parameter can be read by a callee function'). +params((u) => +u. +combine('address_space', ['function', 'private', 'workgroup', 'storage', 'uniform']). +combine('call_indirection', [0, 1, 2]). +combine('type', ['vec4i', 'array', 'struct']) +). +fn((t) => { + switch (t.params.address_space) { + case 'workgroup': + case 'storage': + case 'uniform': + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + } + + const main = { + function: ` +@compute @workgroup_size(1) +fn main() { + var F : T = input; + f0(&F); +} +`, + private: ` +var P : T; +@compute @workgroup_size(1) +fn main() { + P = input; + f0(&P); +} +`, + workgroup: ` +var W : T; +@compute @workgroup_size(1) +fn main() { + W = input; + f0(&W); +} +`, + storage: ` +@compute @workgroup_size(1) +fn main() { + f0(&input); +} +`, + uniform: ` +@compute @workgroup_size(1) +fn main() { + f0(&input); +} +` + }[t.params.address_space]; + + let call_chain = ''; + for (let i = 0; i < t.params.call_indirection; i++) { + call_chain += ` +fn f${i}(p : ptr<${t.params.address_space}, T>) { + f${i + 1}(p); +} +`; + } + + const inputVar = + t.params.address_space === 'uniform' ? + `@binding(0) @group(0) var input : T;` : + `@binding(0) @group(0) var input : T;`; + + const wgsl = ` +${wgslTypeDecl(t.params.type)} + +${inputVar} + +@binding(1) @group(0) var output : T; + +fn f${t.params.call_indirection}(p : ptr<${t.params.address_space}, T>) { + output = *p; +} + +${call_chain} + +${main} +`; + + const values = valuesForType(t.params.type); + + run(t, wgsl, t.params.address_space === 'uniform' ? 'uniform' : 'storage', values, values); +}); + +g.test('read_ptr_to_member'). +desc('Test a pointer parameter to a member of a structure can be read by a callee function'). +params((u) => +u.combine('address_space', ['function', 'private', 'workgroup', 'storage', 'uniform']) +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const main = { + function: ` +@compute @workgroup_size(1) +fn main() { + var v : S = input; + output = f0(&v); +} +`, + private: ` +var P : S; +@compute @workgroup_size(1) +fn main() { + P = input; + output = f0(&P); +} +`, + workgroup: ` +var W : S; +@compute @workgroup_size(1) +fn main() { + W = input; + output = f0(&W); +} +`, + storage: ` +@compute @workgroup_size(1) +fn main() { + output = f0(&input); +} +`, + uniform: ` +@compute @workgroup_size(1) +fn main() { + output = f0(&input); +} +` + }[t.params.address_space]; + + const inputVar = + t.params.address_space === 'uniform' ? + `@binding(0) @group(0) var input : S;` : + `@binding(0) @group(0) var input : S;`; + + const wgsl = ` +struct S { + a : vec4i, + b : T, + c : vec4i, +} + +struct T { + a : vec4i, + b : vec4i, +} + + +${inputVar} +@binding(1) @group(0) var output : T; + +fn f2(p : ptr<${t.params.address_space}, T>) -> T { + return *p; +} + +fn f1(p : ptr<${t.params.address_space}, S>) -> T { + return f2(&(*p).b); +} + +fn f0(p : ptr<${t.params.address_space}, S>) -> T { + return f1(p); +} + +${main} +`; + + + const input = new Uint32Array([ + /* S.a */1, 2, 3, 4, + /* S.b.a */5, 6, 7, 8, + /* S.b.b */9, 10, 11, 12, + /* S.c */13, 14, 15, 16] + ); + + + const expected = new Uint32Array([ + /* S.b.a */5, 6, 7, 8, + /* S.b.b */9, 10, 11, 12] + ); + + run(t, wgsl, t.params.address_space === 'uniform' ? 'uniform' : 'storage', input, expected); +}); + +g.test('read_ptr_to_element'). +desc('Test a pointer parameter to an element of an array can be read by a callee function'). +params((u) => +u.combine('address_space', ['function', 'private', 'workgroup', 'storage', 'uniform']) +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const main = { + function: ` +@compute @workgroup_size(1) +fn main() { + var v : T = input; + output = f0(&v); +} +`, + private: ` +var P : T; +@compute @workgroup_size(1) +fn main() { + P = input; + output = f0(&P); +} +`, + workgroup: ` +var W : T; +@compute @workgroup_size(1) +fn main() { + W = input; + output = f0(&W); +} +`, + storage: ` +@compute @workgroup_size(1) +fn main() { + output = f0(&input); +} +`, + uniform: ` +@compute @workgroup_size(1) +fn main() { + output = f0(&input); +} +` + }[t.params.address_space]; + + const inputVar = + t.params.address_space === 'uniform' ? + `@binding(0) @group(0) var input : T;` : + `@binding(0) @group(0) var input : T;`; + + const wgsl = ` +alias T3 = vec4i; +alias T2 = array; +alias T1 = array; +alias T = array; + +${inputVar} +@binding(1) @group(0) var output : T3; + +fn f2(p : ptr<${t.params.address_space}, T2>) -> T3 { + return (*p)[1]; +} + +fn f1(p : ptr<${t.params.address_space}, T1>) -> T3 { + return f2(&(*p)[0]) + f2(&(*p)[2]); +} + +fn f0(p : ptr<${t.params.address_space}, T>) -> T3 { + return f1(&(*p)[0]); +} + +${main} +`; + + + const input = new Uint32Array([ + /* [0][0][0] */1, 2, 3, 4, + /* [0][0][1] */5, 6, 7, 8, + /* [0][1][0] */9, 10, 11, 12, + /* [0][1][1] */13, 14, 15, 16, + /* [0][2][0] */17, 18, 19, 20, + /* [0][2][1] */21, 22, 23, 24, + /* [1][0][0] */25, 26, 27, 28, + /* [1][0][1] */29, 30, 31, 32, + /* [1][1][0] */33, 34, 35, 36, + /* [1][1][1] */37, 38, 39, 40, + /* [1][2][0] */41, 42, 43, 44, + /* [1][2][1] */45, 46, 47, 48] + ); + const expected = new Uint32Array([/* [0][0][1] + [0][2][1] */5 + 21, 6 + 22, 7 + 23, 8 + 24]); + + run(t, wgsl, t.params.address_space === 'uniform' ? 'uniform' : 'storage', input, expected); +}); + +g.test('write_full_object'). +desc('Test a pointer parameter can be written to by a callee function'). +params((u) => +u. +combine('address_space', ['function', 'private', 'workgroup', 'storage']). +combine('call_indirection', [0, 1, 2]). +combine('type', ['vec4i', 'array', 'struct']) +). +fn((t) => { + switch (t.params.address_space) { + case 'workgroup': + case 'storage': + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + } + + const ptr = + t.params.address_space === 'storage' ? + `ptr` : + `ptr<${t.params.address_space}, T>`; + + const main = { + function: ` +@compute @workgroup_size(1) +fn main() { + var F : T; + f0(&F); + output = F; +} +`, + private: ` +var P : T; +@compute @workgroup_size(1) +fn main() { + f0(&P); + output = P; +} +`, + workgroup: ` +var W : T; +@compute @workgroup_size(1) +fn main() { + f0(&W); + output = W; +} +`, + storage: ` +@compute @workgroup_size(1) +fn main() { + f0(&output); +} +` + }[t.params.address_space]; + + let call_chain = ''; + for (let i = 0; i < t.params.call_indirection; i++) { + call_chain += ` +fn f${i}(p : ${ptr}) { + f${i + 1}(p); +} +`; + } + + const wgsl = ` +${wgslTypeDecl(t.params.type)} + +@binding(0) @group(0) var input : T; +@binding(1) @group(0) var output : T; + +fn f${t.params.call_indirection}(p : ${ptr}) { + *p = input; +} + +${call_chain} + +${main} +`; + + const values = valuesForType(t.params.type); + + run(t, wgsl, 'uniform', values, values); +}); + +g.test('write_ptr_to_member'). +desc( + 'Test a pointer parameter to a member of a structure can be written to by a callee function' +). +params((u) => u.combine('address_space', ['function', 'private', 'workgroup', 'storage'])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const main = { + function: ` +@compute @workgroup_size(1) +fn main() { + var v : S; + f0(&v); + output = v; +} +`, + private: ` +var P : S; +@compute @workgroup_size(1) +fn main() { + f0(&P); + output = P; +} +`, + workgroup: ` +var W : S; +@compute @workgroup_size(1) +fn main() { + f0(&W); + output = W; +} +`, + storage: ` +@compute @workgroup_size(1) +fn main() { + f1(&output); +} +` + }[t.params.address_space]; + + const ptr = (ty) => + t.params.address_space === 'storage' ? + `ptr` : + `ptr<${t.params.address_space}, ${ty}>`; + + const wgsl = ` +struct S { + a : vec4i, + b : T, + c : vec4i, +} + +struct T { + a : vec4i, + b : vec4i, +} + + +@binding(0) @group(0) var input : T; +@binding(1) @group(0) var output : S; + +fn f2(p : ${ptr('T')}) { + *p = input; +} + +fn f1(p : ${ptr('S')}) { + f2(&(*p).b); +} + +fn f0(p : ${ptr('S')}) { + f1(p); +} + +${main} +`; + + + const input = new Uint32Array([ + /* S.b.a */5, 6, 7, 8, + /* S.b.b */9, 10, 11, 12] + ); + + + const expected = new Uint32Array([ + /* S.a */0, 0, 0, 0, + /* S.b.a */5, 6, 7, 8, + /* S.b.b */9, 10, 11, 12, + /* S.c */0, 0, 0, 0] + ); + + run(t, wgsl, 'storage', input, expected); +}); + +g.test('write_ptr_to_element'). +desc('Test a pointer parameter to an element of an array can be written to by a callee function'). +params((u) => u.combine('address_space', ['function', 'private', 'workgroup', 'storage'])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const main = { + function: ` +@compute @workgroup_size(1) +fn main() { + var v : T; + f0(&v); + output = v; +} +`, + private: ` +var P : T; +@compute @workgroup_size(1) +fn main() { + f0(&P); + output = P; +} +`, + workgroup: ` +var W : T; +@compute @workgroup_size(1) +fn main() { + f0(&W); + output = W; +} +`, + storage: ` +@compute @workgroup_size(1) +fn main() { + f0(&output); +} +` + }[t.params.address_space]; + + const ptr = (ty) => + t.params.address_space === 'storage' ? + `ptr` : + `ptr<${t.params.address_space}, ${ty}>`; + + const wgsl = ` +alias T3 = vec4i; +alias T2 = array; +alias T1 = array; +alias T = array; + +@binding(0) @group(0) var input : T3; +@binding(1) @group(0) var output : T; + +fn f2(p : ${ptr('T2')}) { + (*p)[1] = input; +} + +fn f1(p : ${ptr('T1')}) { + f2(&(*p)[0]); + f2(&(*p)[2]); +} + +fn f0(p : ${ptr('T')}) { + f1(&(*p)[0]); +} + +${main} +`; + + const input = new Uint32Array([1, 2, 3, 4]); + + + const expected = new Uint32Array([ + /* [0][0][0] */0, 0, 0, 0, + /* [0][0][1] */1, 2, 3, 4, + /* [0][1][0] */0, 0, 0, 0, + /* [0][1][1] */0, 0, 0, 0, + /* [0][2][0] */0, 0, 0, 0, + /* [0][2][1] */1, 2, 3, 4, + /* [1][0][0] */0, 0, 0, 0, + /* [1][0][1] */0, 0, 0, 0, + /* [1][1][0] */0, 0, 0, 0, + /* [1][1][1] */0, 0, 0, 0, + /* [1][2][0] */0, 0, 0, 0, + /* [1][2][1] */0, 0, 0, 0] + ); + + run(t, wgsl, 'storage', input, expected); +}); + +g.test('atomic_ptr_to_element'). +desc( + 'Test a pointer parameter to an atomic of an array can be read from and written to by a callee function' +). +params((u) => u.combine('address_space', ['workgroup', 'storage'])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const main = { + workgroup: ` +var W_input : T; +var W_output : T; +@compute @workgroup_size(1) +fn main() { + // Copy input -> W_input + for (var i = 0; i < 2; i++) { + for (var j = 0; j < 3; j++) { + for (var k = 0; k < 2; k++) { + atomicStore(&W_input[k][j][i], atomicLoad(&input[k][j][i])); + } + } + } + + f0(&W_input, &W_output); + + // Copy W_output -> output + for (var i = 0; i < 2; i++) { + for (var j = 0; j < 3; j++) { + for (var k = 0; k < 2; k++) { + atomicStore(&output[k][j][i], atomicLoad(&W_output[k][j][i])); + } + } + } +} +`, + storage: ` +@compute @workgroup_size(1) +fn main() { + f0(&input, &output); +} +` + }[t.params.address_space]; + + const ptr = (ty) => + t.params.address_space === 'storage' ? + `ptr` : + `ptr<${t.params.address_space}, ${ty}>`; + + const wgsl = ` +alias T3 = atomic; +alias T2 = array; +alias T1 = array; +alias T = array; + +@binding(0) @group(0) var input : T; +@binding(1) @group(0) var output : T; + +fn f2(in : ${ptr('T2')}, out : ${ptr('T2')}) { + let v = atomicLoad(&(*in)[0]); + atomicStore(&(*out)[1], v); +} + +fn f1(in : ${ptr('T1')}, out : ${ptr('T1')}) { + f2(&(*in)[0], &(*out)[1]); + f2(&(*in)[2], &(*out)[0]); +} + +fn f0(in : ${ptr('T')}, out : ${ptr('T')}) { + f1(&(*in)[1], &(*out)[0]); +} + +${main} +`; + + + const input = new Uint32Array([ + /* [0][0][0] */1, + /* [0][0][1] */2, + /* [0][1][0] */3, + /* [0][1][1] */4, + /* [0][2][0] */5, + /* [0][2][1] */6, + /* [1][0][0] */7, // -> [0][1][1] + /* [1][0][1] */8, + /* [1][1][0] */9, + /* [1][1][1] */10, + /* [1][2][0] */11, // -> [0][0][1] + /* [1][2][1] */12] + ); + + + const expected = new Uint32Array([ + /* [0][0][0] */0, + /* [0][0][1] */11, + /* [0][1][0] */0, + /* [0][1][1] */7, + /* [0][2][0] */0, + /* [0][2][1] */0, + /* [1][0][0] */0, + /* [1][0][1] */0, + /* [1][1][0] */0, + /* [1][1][1] */0, + /* [1][2][0] */0, + /* [1][2][1] */0] + ); + + run(t, wgsl, 'storage', input, expected); +}); + +g.test('array_length'). +desc( + 'Test a pointer parameter to a runtime sized array can be used by arrayLength() in a callee function' +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const wgsl = ` +@binding(0) @group(0) var arr : array; +@binding(1) @group(0) var output : u32; + +fn f2(p : ptr, read>) -> u32 { + return arrayLength(p); +} + +fn f1(p : ptr, read>) -> u32 { + return f2(p); +} + +fn f0(p : ptr, read>) -> u32 { + return f1(p); +} + +@compute @workgroup_size(1) +fn main() { + output = f0(&arr); +} +`; + + const input = new Uint32Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); + const expected = new Uint32Array([12]); + + run(t, wgsl, 'storage', input, expected); +}); + +g.test('mixed_ptr_parameters'). +desc('Test that functions can accept multiple, mixed pointer parameters'). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const wgsl = ` +@binding(0) @group(0) var input : array; +@binding(1) @group(0) var output : array; + +fn sum(f : ptr, + w : ptr>, + p : ptr, + u : ptr) -> vec4i { + + return vec4(*f + atomicLoad(w) + *p) + *u; +} + +struct S { + i : i32, +} + +var P0 = S(0); +var P1 = S(10); +var P2 = 20; +var P3 = 30; + +struct T { + i : atomic, +} + +var W0 : T; +var W1 : atomic; +var W2 : T; +var W3 : atomic; + +@compute @workgroup_size(1) +fn main() { + atomicStore(&W0.i, 0); + atomicStore(&W1, 100); + atomicStore(&W2.i, 200); + atomicStore(&W3, 300); + + var F = array(0, 1000, 2000, 3000); + + output[0] = sum(&F[2], &W3, &P1.i, &input[0]); // vec4(2310) + vec4(1, 2, 3, 4) + output[1] = sum(&F[1], &W2.i, &P0.i, &input[1]); // vec4(1200) + vec4(4, 3, 2, 1) + output[2] = sum(&F[3], &W0.i, &P3, &input[2]); // vec4(3030) + vec4(2, 4, 1, 3) + output[3] = sum(&F[2], &W1, &P2, &input[3]); // vec4(2120) + vec4(4, 1, 2, 3) +} +`; + + + const input = new Uint32Array([ + /* [0] */1, 2, 3, 4, + /* [1] */4, 3, 2, 1, + /* [2] */2, 4, 1, 3, + /* [3] */4, 1, 2, 3] + ); + + + const expected = new Uint32Array([ + /* [0] */2311, 2312, 2313, 2314, + /* [1] */1204, 1203, 1202, 1201, + /* [2] */3032, 3034, 3031, 3033, + /* [3] */2124, 2121, 2122, 2123] + ); + + run(t, wgsl, 'uniform', input, expected); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case.js new file mode 100644 index 0000000000..d2d3a019de --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case.js @@ -0,0 +1,440 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { crc32 } from '../../../../common/util/crc32.js';import { assert } from '../../../../common/util/util.js'; +import { + abstractInt, + i32, + + u32, + + VectorValue } from +'../../../util/conversion.js'; +import { + cartesianProduct, + + quantizeToI32, + quantizeToI64, + quantizeToU32 } from +'../../../util/math.js'; + + + +function notUndefined(value) { + return value !== undefined; +} + +/** Case is a single expression test case. */ + + + + + + + +/** + * Filters a given set of Cases down to a target number of cases by + * randomly selecting which Cases to return. + * + * The selection algorithm is deterministic and stable for a case's + * inputs. + * + * This means that if a specific case is selected is not affected by the + * presence of other cases in the list, so in theory it is possible to create a + * pathological set of cases such that all or not of the cases are selected + * in spite of the target number. + * + * This is a trade-off from guaranteeing stability of the selected cases over + * small changes, so the target number of cases is more of a suggestion. It is + * still guaranteed that if you set n0 < n1, then the invocation with n0 will + * return at most the number of cases that n1 does, it just isn't guaranteed to + * be less. + * + * @param dis is a string provided for additional hashing information to avoid + * systemic bias in the selection process across different test + * suites. Specifically every Case with the same input values being + * included or skipped regardless of the operation that they are + * testing. This string should be something like the name of the case + * cache the values are for or the operation under test. + * @param n number of cases targeted be returned. Expected to be a positive + * integer. If equal or greater than the number of cases, then all the + * cases are returned. 0 is not allowed, since it is likely a + * programming error, because if the caller intentionally wants 0 + * items, they can just use []. + * @param cases list of Cases to be selected from. + */ +export function selectNCases(dis, n, cases) { + assert(n > 0 && Math.round(n) === n, `n ${n} is expected to be a positive integer`); + const count = cases.length; + if (n >= count) { + return cases; + } + const dis_crc32 = crc32(dis); + return cases.filter( + (c) => Math.trunc(n / count * 0xffff_ffff) > (crc32(c.input.toString()) ^ dis_crc32) >>> 0 + ); +} + +/** + * A function that performs a binary operation on x and y, and returns the + * expected result. + */ + + + + +/** + * A function that performs a vector-vector operation on x and y, and returns the + * expected result. + */ + + + + +/** + * @returns a Case for the input params with op applied + * @param scalar scalar param + * @param vector vector param (2, 3, or 4 elements) + * @param op the op to apply to scalar and vector + * @param quantize function to quantize all values in vectors and scalars + * @param scalarize function to convert numbers to Scalars + */ +function makeScalarVectorBinaryToVectorCase( +scalar, +vector, +op, +quantize, +scalarize) +{ + scalar = quantize(scalar); + vector = vector.map(quantize); + const result = vector.map((v) => op(scalar, v)); + if (result.includes(undefined)) { + return undefined; + } + return { + input: [scalarize(scalar), new VectorValue(vector.map(scalarize))], + expected: new VectorValue(result.filter(notUndefined).map(scalarize)) + }; +} + +/** + * @returns array of Case for the input params with op applied + * @param scalars array of scalar params + * @param vectors array of vector params (2, 3, or 4 elements) + * @param op the op to apply to each pair of scalar and vector + * @param quantize function to quantize all values in vectors and scalars + * @param scalarize function to convert numbers to Scalars + */ +function generateScalarVectorBinaryToVectorCases( +scalars, +vectors, +op, +quantize, +scalarize) +{ + return scalars.flatMap((s) => { + return vectors. + map((v) => { + return makeScalarVectorBinaryToVectorCase(s, v, op, quantize, scalarize); + }). + filter(notUndefined); + }); +} + +/** + * @returns a Case for the input params with op applied + * @param vector vector param (2, 3, or 4 elements) + * @param scalar scalar param + * @param op the op to apply to vector and scalar + * @param quantize function to quantize all values in vectors and scalars + * @param scalarize function to convert numbers to Scalars + */ +function makeVectorScalarBinaryToVectorCase( +vector, +scalar, +op, +quantize, +scalarize) +{ + vector = vector.map(quantize); + scalar = quantize(scalar); + const result = vector.map((v) => op(v, scalar)); + if (result.includes(undefined)) { + return undefined; + } + return { + input: [new VectorValue(vector.map(scalarize)), scalarize(scalar)], + expected: new VectorValue(result.filter(notUndefined).map(scalarize)) + }; +} + +/** + * @returns array of Case for the input params with op applied + * @param vectors array of vector params (2, 3, or 4 elements) + * @param scalars array of scalar params + * @param op the op to apply to each pair of vector and scalar + * @param quantize function to quantize all values in vectors and scalars + * @param scalarize function to convert numbers to Scalars + */ +function generateVectorScalarBinaryToVectorCases( +vectors, +scalars, +op, +quantize, +scalarize) +{ + return scalars.flatMap((s) => { + return vectors. + map((v) => { + return makeVectorScalarBinaryToVectorCase(v, s, op, quantize, scalarize); + }). + filter(notUndefined); + }); +} + +/** + * @returns array of Case for the input params with op applied + * @param scalars array of scalar params + * @param vectors array of vector params (2, 3, or 4 elements) + * @param op he op to apply to each pair of scalar and vector + */ +export function generateU32VectorBinaryToVectorCases( +scalars, +vectors, +op) +{ + return generateScalarVectorBinaryToVectorCases(scalars, vectors, op, quantizeToU32, u32); +} + +/** + * @returns array of Case for the input params with op applied + * @param vectors array of vector params (2, 3, or 4 elements) + * @param scalars array of scalar params + * @param op he op to apply to each pair of vector and scalar + */ +export function generateVectorU32BinaryToVectorCases( +vectors, +scalars, +op) +{ + return generateVectorScalarBinaryToVectorCases(vectors, scalars, op, quantizeToU32, u32); +} + +/** + * @returns array of Case for the input params with op applied + * @param scalars array of scalar params + * @param vectors array of vector params (2, 3, or 4 elements) + * @param op he op to apply to each pair of scalar and vector + */ +export function generateI32VectorBinaryToVectorCases( +scalars, +vectors, +op) +{ + return generateScalarVectorBinaryToVectorCases(scalars, vectors, op, quantizeToI32, i32); +} + +/** + * @returns array of Case for the input params with op applied + * @param vectors array of vector params (2, 3, or 4 elements) + * @param scalars array of scalar params + * @param op he op to apply to each pair of vector and scalar + */ +export function generateVectorI32BinaryToVectorCases( +vectors, +scalars, +op) +{ + return generateVectorScalarBinaryToVectorCases(vectors, scalars, op, quantizeToI32, i32); +} + +/** + * @returns array of Case for the input params with op applied + * @param scalars array of scalar params + * @param vectors array of vector params (2, 3, or 4 elements) + * @param op he op to apply to each pair of scalar and vector + */ +export function generateI64VectorBinaryToVectorCases( +scalars, +vectors, +op) +{ + return generateScalarVectorBinaryToVectorCases(scalars, vectors, op, quantizeToI64, abstractInt); +} + +/** + * @returns array of Case for the input params with op applied + * @param vectors array of vector params (2, 3, or 4 elements) + * @param scalars array of scalar params + * @param op he op to apply to each pair of vector and scalar + */ +export function generateVectorI64BinaryToVectorCases( +vectors, +scalars, +op) +{ + return generateVectorScalarBinaryToVectorCases(vectors, scalars, op, quantizeToI64, abstractInt); +} + +/** + * @returns array of Case for the input params with op applied + * @param param0s array of inputs to try for the first param + * @param param1s array of inputs to try for the second param + * @param op callback called on each pair of inputs to produce each case + * @param quantize function to quantize all values + * @param scalarize function to convert numbers to Scalars + */ +function generateScalarBinaryToScalarCases( +param0s, +param1s, +op, +quantize, +scalarize) +{ + param0s = param0s.map(quantize); + param1s = param1s.map(quantize); + return cartesianProduct(param0s, param1s).reduce((cases, e) => { + const expected = op(e[0], e[1]); + if (expected !== undefined) { + cases.push({ input: [scalarize(e[0]), scalarize(e[1])], expected: scalarize(expected) }); + } + return cases; + }, new Array()); +} + +/** + * @returns an array of Cases for operations over a range of inputs + * @param param0s array of inputs to try for the first param + * @param param1s array of inputs to try for the second param + * @param op callback called on each pair of inputs to produce each case + */ +export function generateBinaryToI32Cases( +param0s, +param1s, +op) +{ + return generateScalarBinaryToScalarCases(param0s, param1s, op, quantizeToI32, i32); +} + +/** + * @returns an array of Cases for operations over a range of inputs + * @param param0s array of inputs to try for the first param + * @param param1s array of inputs to try for the second param + * @param op callback called on each pair of inputs to produce each case + */ +export function generateBinaryToU32Cases( +param0s, +param1s, +op) +{ + return generateScalarBinaryToScalarCases(param0s, param1s, op, quantizeToU32, u32); +} + +/** + * @returns an array of Cases for operations over a range of inputs + * @param param0s array of inputs to try for the first param + * @param param1s array of inputs to try for the second param + * @param op callback called on each pair of inputs to produce each case + */ +export function generateBinaryToI64Cases( +param0s, +param1s, +op) +{ + return generateScalarBinaryToScalarCases(param0s, param1s, op, quantizeToI64, abstractInt); +} + +/** + * @returns a Case for the input params with op applied + * @param param0 vector param (2, 3, or 4 elements) for the first param + * @param param1 vector param (2, 3, or 4 elements) for the second param + * @param op the op to apply to each pair of vectors + * @param quantize function to quantize all values in vectors and scalars + * @param scalarize function to convert numbers to Scalars + */ +function makeVectorVectorToScalarCase( +param0, +param1, +op, +quantize, +scalarize) +{ + const param0_quantized = param0.map(quantize); + const param1_quantized = param1.map(quantize); + const result = op(param0_quantized, param1_quantized); + if (result === undefined) return undefined; + + return { + input: [ + new VectorValue(param0_quantized.map(scalarize)), + new VectorValue(param1_quantized.map(scalarize))], + + expected: scalarize(result) + }; +} + +/** + * @returns array of Case for the input params with op applied + * @param param0s array of vector params (2, 3, or 4 elements) for the first param + * @param param1s array of vector params (2, 3, or 4 elements) for the second param + * @param op the op to apply to each pair of vectors + * @param quantize function to quantize all values in vectors and scalars + * @param scalarize function to convert numbers to Scalars + */ +function generateVectorVectorToScalarCases( +param0s, +param1s, +op, +quantize, +scalarize) +{ + return param0s.flatMap((param0) => { + return param1s. + map((param1) => { + return makeVectorVectorToScalarCase(param0, param1, op, quantize, scalarize); + }). + filter(notUndefined); + }); +} + +/** + * @returns array of Case for the input params with op applied + * @param param0s array of vector params (2, 3, or 4 elements) for the first param + * @param param1s array of vector params (2, 3, or 4 elements) for the second param + * @param op the op to apply to each pair of vectors + */ +export function generateVectorVectorToI32Cases( +param0s, +param1s, +op) +{ + return generateVectorVectorToScalarCases(param0s, param1s, op, quantizeToI32, i32); +} + +/** + * @returns array of Case for the input params with op applied + * @param param0s array of vector params (2, 3, or 4 elements) for the first param + * @param param1s array of vector params (2, 3, or 4 elements) for the second param + * @param op the op to apply to each pair of vectors + */ +export function generateVectorVectorToU32Cases( +param0s, +param1s, +op) +{ + return generateVectorVectorToScalarCases(param0s, param1s, op, quantizeToU32, u32); +} + +/** + * @returns array of Case for the input params with op applied + * @param param0s array of vector params (2, 3, or 4 elements) for the first param + * @param param1s array of vector params (2, 3, or 4 elements) for the second param + * @param op the op to apply to each pair of vectors + */ +export function generateVectorVectorToI64Cases( +param0s, +param1s, +op) +{ + return generateVectorVectorToScalarCases(param0s, param1s, op, quantizeToI64, abstractInt); +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case_cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case_cache.js index 6b3cb1a4c2..41857ad8fa 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case_cache.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case_cache.js @@ -3,21 +3,22 @@ **/import { dataCache } from '../../../../common/framework/data_cache.js';import { unreachable } from '../../../../common/util/util.js';import BinaryStream from '../../../util/binary_stream.js'; import { deserializeComparator, serializeComparator } from '../../../util/compare.js'; import { - Scalar, - Vector, - serializeValue, - deserializeValue, - Matrix } from + MatrixValue, + VectorValue, + deserializeValue, + isScalarValue, + serializeValue } from '../../../util/conversion.js'; import { - deserializeFPInterval, FPInterval, + deserializeFPInterval, serializeFPInterval } from '../../../util/floating_point.js'; import { flatten2DArray, unflatten2DArray } from '../../../util/math.js'; -import { isComparator } from './expression.js';var + +import { isComparator } from './expectation.js';var SerializedExpectationKind = /*#__PURE__*/function (SerializedExpectationKind) {SerializedExpectationKind[SerializedExpectationKind["Value"] = 0] = "Value";SerializedExpectationKind[SerializedExpectationKind["Interval"] = 1] = "Interval";SerializedExpectationKind[SerializedExpectationKind["Interval1DArray"] = 2] = "Interval1DArray";SerializedExpectationKind[SerializedExpectationKind["Interval2DArray"] = 3] = "Interval2DArray";SerializedExpectationKind[SerializedExpectationKind["Array"] = 4] = "Array";SerializedExpectationKind[SerializedExpectationKind["Comparator"] = 5] = "Comparator";return SerializedExpectationKind;}(SerializedExpectationKind || {}); @@ -30,7 +31,7 @@ SerializedExpectationKind = /*#__PURE__*/function (SerializedExpectationKind) {S /** serializeExpectation() serializes an Expectation to a BinaryStream */ export function serializeExpectation(s, e) { - if (e instanceof Scalar || e instanceof Vector || e instanceof Matrix) { + if (isScalarValue(e) || e instanceof VectorValue || e instanceof MatrixValue) { s.writeU8(SerializedExpectationKind.Value); serializeValue(s, e); return; @@ -122,11 +123,11 @@ export function deserializeCase(s) { return { input, expected }; } -/** CaseListBuilder is a function that builds a CaseList */ +/** CaseListBuilder is a function that builds a list of cases, Case[] */ /** - * CaseCache is a cache of CaseList. + * CaseCache is a cache of Case[]. * CaseCache implements the Cacheable interface, so the cases can be pre-built * and stored in the data cache, reducing computation costs at CTS runtime. */ @@ -137,7 +138,7 @@ export class CaseCache { * @param builders a Record of case-list name to case-list builder. */ constructor(name, builders) { - this.path = `webgpu/shader/execution/case-cache/${name}.bin`; + this.path = `webgpu/shader/execution/${name}.bin`; this.builders = builders; } diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/constructor/non_zero.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/constructor/non_zero.spec.js new file mode 100644 index 0000000000..83da4e63c0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/constructor/non_zero.spec.js @@ -0,0 +1,797 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for value constructors from components +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { + ArrayValue, + + + Type, + + + + scalarTypeOf, + vec2, + vec3 } from +'../../../../util/conversion.js'; +import { FP } from '../../../../util/floating_point.js'; +import { allInputSources, basicExpressionBuilder, run } from '../expression.js'; + +export const g = makeTestGroup(GPUTest); + +/** @returns true if 'v' is 'min' or 'max' */ +function isMinOrMax(v) { + return v === 'min' || v === 'max'; +} + +/** A list of concrete types to test for the given abstract-numeric type */ +const kConcreteTypesForAbstractType = { + 'abstract-float': ['f32', 'f16'], + 'abstract-int': ['f32', 'f16', 'i32', 'u32'], + 'vec3': ['vec3f', 'vec3h', 'vec3i', 'vec3u'], + 'vec4': ['vec4f', 'vec4h'], + 'mat2x3': ['mat2x3f', 'mat2x3h'] +}; + +/** + * @returns the lowest finite value for 'kind' if 'v' is 'min', + * the highest finite value for 'kind' if 'v' is 'max', + * otherwise returns 'v' + */ +function valueFor(v, kind) { + if (!isMinOrMax(v)) { + return v; + } + switch (kind) { + case 'bool': + return v === 'min' ? 0 : 1; + case 'i32': + return v === 'min' ? -0x80000000 : 0x7fffffff; + case 'u32': + return v === 'min' ? 0 : 0xffffffff; + case 'f32': + return v === 'min' ? FP['f32'].constants().negative.min : FP['f32'].constants().positive.max; + case 'f16': + return v === 'min' ? FP['f16'].constants().negative.min : FP['f16'].constants().positive.max; + } +} + +g.test('scalar_identity'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a scalar constructed from a value of the same type produces the expected value`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('type', ['bool', 'i32', 'u32', 'f32', 'f16']). +combine('value', ['min', 'max', 1, 2, 5, 100]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } + t.skipIf(t.params.type === 'bool' && !isMinOrMax(t.params.value)); +}). +fn(async (t) => { + const type = Type[t.params.type]; + const value = valueFor(t.params.value, t.params.type); + await run( + t, + basicExpressionBuilder((ops) => `${type}(${ops[0]})`), + [type], + type, + t.params, + [{ input: [type.create(value)], expected: type.create(value) }] + ); +}); + +g.test('vector_identity'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a vector constructed from a value of the same type produces the expected value`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('type', ['bool', 'i32', 'u32', 'f32', 'f16']). +combine('width', [2, 3, 4]). +combine('infer_type', [false, true]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.type]; + const vectorType = Type.vec(t.params.width, elementType); + const elements = []; + const fn = t.params.infer_type ? `vec${t.params.width}` : `${vectorType}`; + for (let i = 0; i < t.params.width; i++) { + if (t.params.type === 'bool') { + elements.push(i & 1); + } else { + elements.push((i + 1) * 10); + } + } + + await run( + t, + basicExpressionBuilder((ops) => `${fn}(${ops[0]})`), + [vectorType], + vectorType, + t.params, + [ + { + input: vectorType.create(elements), + expected: vectorType.create(elements) + }] + + ); +}); + +g.test('concrete_vector_splat'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a vector constructed from a single concrete scalar produces the expected value`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('type', ['bool', 'i32', 'u32', 'f32', 'f16']). +combine('value', ['min', 'max', 1, 2, 5, 100]). +combine('width', [2, 3, 4]). +combine('infer_type', [false, true]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } + t.skipIf(t.params.type === 'bool' && !isMinOrMax(t.params.value)); +}). +fn(async (t) => { + const value = valueFor(t.params.value, t.params.type); + const elementType = Type[t.params.type]; + const vectorType = Type.vec(t.params.width, elementType); + const fn = t.params.infer_type ? `vec${t.params.width}` : `${vectorType}`; + await run( + t, + basicExpressionBuilder((ops) => `${fn}(${ops[0]})`), + [elementType], + vectorType, + t.params, + [{ input: [elementType.create(value)], expected: vectorType.create(value) }] + ); +}); + +g.test('abstract_vector_splat'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a vector constructed from a single abstract scalar produces the expected value`). +params((u) => +u. +combine('abstract_type', ['abstract-int', 'abstract-float']). +expand('concrete_type', (t) => kConcreteTypesForAbstractType[t.abstract_type]). +combine('value', [1, 2, 5, 100]). +combine('width', [2, 3, 4]) +). +beforeAllSubcases((t) => { + if (t.params.concrete_type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const suffix = t.params.abstract_type === 'abstract-float' ? '.0' : ''; + const concreteElementType = Type[t.params.concrete_type]; + const concreteVectorType = Type.vec(t.params.width, concreteElementType); + const fn = `vec${t.params.width}`; + await run( + t, + basicExpressionBuilder((_) => `${fn}(${t.params.value * 0x100000000}${suffix}) / 0x100000000`), + [], + concreteVectorType, + { inputSource: 'const' }, + [{ input: [], expected: concreteVectorType.create(t.params.value) }] + ); +}); + +g.test('concrete_vector_elements'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a vector constructed from concrete element values produces the expected value`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('type', ['bool', 'i32', 'u32', 'f32', 'f16']). +combine('width', [2, 3, 4]). +combine('infer_type', [false, true]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.type]; + const vectorType = Type.vec(t.params.width, elementType); + const elements = []; + const fn = t.params.infer_type ? `vec${t.params.width}` : `${vectorType}`; + for (let i = 0; i < t.params.width; i++) { + if (t.params.type === 'bool') { + elements.push(i & 1); + } else { + elements.push((i + 1) * 10); + } + } + + await run( + t, + basicExpressionBuilder((ops) => `${fn}(${ops.join(', ')})`), + elements.map((e) => elementType), + vectorType, + t.params, + [ + { + input: elements.map((v) => elementType.create(v)), + expected: vectorType.create(elements) + }] + + ); +}); + +g.test('abstract_vector_elements'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a vector constructed from abstract element values produces the expected value`). +params((u) => +u. +combine('abstract_type', ['abstract-int', 'abstract-float']). +expand('concrete_type', (t) => kConcreteTypesForAbstractType[t.abstract_type]). +combine('width', [2, 3, 4]) +). +beforeAllSubcases((t) => { + if (t.params.concrete_type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const suffix = t.params.abstract_type === 'abstract-float' ? '.0' : ''; + const concreteElementType = Type[t.params.concrete_type]; + const concreteVectorType = Type.vec(t.params.width, concreteElementType); + const fn = `vec${t.params.width}`; + const elements = []; + for (let i = 0; i < t.params.width; i++) { + elements.push((i + 1) * 10); + } + await run( + t, + basicExpressionBuilder( + (_) => `${fn}(${elements.map((v) => `${v * 0x100000000}${suffix}`).join(', ')}) / 0x100000000` + ), + [], + concreteVectorType, + { inputSource: 'const' }, + [{ input: [], expected: concreteVectorType.create(elements) }] + ); +}); + +const kMixSignatures = [ +'2s', // [vec2, scalar] +'s2', // [scalar, vec2] +'2ss', // [vec2, scalar, scalar] +'s2s', // [scalar, vec2, scalar] +'ss2', // [scalar, scalar, vec2 ] +'22', // [vec2, vec2] +'3s', // [vec3, scalar] +'s3' // [scalar, vec3] +]; + +g.test('concrete_vector_mix'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc( + `Test that a vector constructed from a mix of concrete element values and sub-vectors produces the expected value` +). +params((u) => +u. +combine('inputSource', allInputSources). +combine('type', ['bool', 'i32', 'u32', 'f32', 'f16']). +combine('signature', kMixSignatures). +combine('infer_type', [false, true]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.type]; + let width = 0; + const elementValue = (i) => t.params.type === 'bool' ? i & 1 : (i + 1) * 10; + const elements = []; + const nextValue = () => { + const value = elementValue(width++); + elements.push(value); + return elementType.create(value); + }; + const args = []; + for (const c of t.params.signature) { + switch (c) { + case '2': + args.push(vec2(nextValue(), nextValue())); + break; + case '3': + args.push(vec3(nextValue(), nextValue(), nextValue())); + break; + case 's': + args.push(nextValue()); + break; + } + } + const vectorType = Type.vec(width, elementType); + const fn = t.params.infer_type ? `vec${width}` : `${vectorType}`; + await run( + t, + basicExpressionBuilder((ops) => `${fn}(${ops.join(', ')})`), + args.map((e) => e.type), + vectorType, + t.params, + [ + { + input: args, + expected: vectorType.create(elements) + }] + + ); +}); + +g.test('abstract_vector_mix'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc( + `Test that a vector constructed from a mix of abstract element values and sub-vectors produces the expected value` +). +params((u) => +u. +combine('abstract_type', ['abstract-int', 'abstract-float']). +expand('concrete_type', (t) => kConcreteTypesForAbstractType[t.abstract_type]). +combine('signature', kMixSignatures) +). +beforeAllSubcases((t) => { + if (t.params.concrete_type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + let width = 0; + const suffix = t.params.abstract_type === 'abstract-float' ? '.0' : ''; + const concreteElementType = Type[t.params.concrete_type]; + const elementValue = (i) => (i + 1) * 10; + const elements = []; + const nextValue = () => { + const value = elementValue(width++); + elements.push(value); + return `${value * 0x100000000}${suffix}`; + }; + const args = []; + for (const c of t.params.signature) { + switch (c) { + case '2': + args.push(`vec2(${nextValue()}, ${nextValue()})`); + break; + case '3': + args.push(`vec3(${nextValue()}, ${nextValue()}, ${nextValue()})`); + break; + case 's': + args.push(`${nextValue()}`); + break; + } + } + const concreteVectorType = Type.vec(width, concreteElementType); + const fn = `vec${width}`; + await run( + t, + basicExpressionBuilder((_) => `${fn}(${args.join(', ')}) / 0x100000000`), + [], + concreteVectorType, + { inputSource: 'const' }, + [ + { + input: [], + expected: concreteVectorType.create(elements) + }] + + ); +}); + +g.test('matrix_identity'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a matrix constructed from a value of the same type produces the expected value`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('type', ['f32', 'f16']). +combine('columns', [2, 3, 4]). +combine('rows', [2, 3, 4]). +combine('infer_type', [false, true]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.type]; + const matrixType = Type.mat(t.params.columns, t.params.rows, elementType); + const elements = []; + for (let column = 0; column < t.params.columns; column++) { + for (let row = 0; row < t.params.rows; row++) { + elements.push((column + 1) * 10 + (row + 1)); + } + } + const fn = t.params.infer_type ? `mat${t.params.columns}x${t.params.rows}` : `${matrixType}`; + await run( + t, + basicExpressionBuilder((ops) => `${fn}(${ops[0]})`), + [matrixType], + matrixType, + t.params, + [ + { + input: matrixType.create(elements), + expected: matrixType.create(elements) + }] + + ); +}); + +g.test('concrete_matrix_elements'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a matrix constructed from concrete element values produces the expected value`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('type', ['f32', 'f16']). +combine('columns', [2, 3, 4]). +combine('rows', [2, 3, 4]). +combine('infer_type', [false, true]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.type]; + const matrixType = Type.mat(t.params.columns, t.params.rows, elementType); + const elements = []; + for (let column = 0; column < t.params.columns; column++) { + for (let row = 0; row < t.params.rows; row++) { + elements.push((column + 1) * 10 + (row + 1)); + } + } + const fn = t.params.infer_type ? `mat${t.params.columns}x${t.params.rows}` : `${matrixType}`; + await run( + t, + basicExpressionBuilder((ops) => `${fn}(${ops.join(', ')})`), + elements.map((e) => elementType), + matrixType, + t.params, + [ + { + input: elements.map((e) => elementType.create(e)), + expected: matrixType.create(elements) + }] + + ); +}); + +g.test('abstract_matrix_elements'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a matrix constructed from concrete element values produces the expected value`). +params((u) => +u. +combine('concrete_type', ['f32', 'f16']). +combine('columns', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +beforeAllSubcases((t) => { + if (t.params.concrete_type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const concreteElementType = Type[t.params.concrete_type]; + const concreteMatrixType = Type.mat(t.params.columns, t.params.rows, concreteElementType); + const elements = []; + for (let column = 0; column < t.params.columns; column++) { + for (let row = 0; row < t.params.rows; row++) { + elements.push((column + 1) * 10 + (row + 1)); + } + } + const fn = `mat${t.params.columns}x${t.params.rows}`; + await run( + t, + basicExpressionBuilder( + (_) => `${fn}(${elements.map((v) => `${v * 0x100000000}.0`).join(', ')}) * (1.0 / 0x100000000)` + ), + [], + concreteMatrixType, + { inputSource: 'const' }, + [ + { + input: [], + expected: concreteMatrixType.create(elements) + }] + + ); +}); + +g.test('concrete_matrix_column_vectors'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a matrix constructed from concrete column vectors produces the expected value`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('type', ['f32', 'f16']). +combine('columns', [2, 3, 4]). +combine('rows', [2, 3, 4]). +combine('infer_type', [false, true]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.type]; + const columnType = Type.vec(t.params.rows, elementType); + const matrixType = Type.mat(t.params.columns, t.params.rows, elementType); + const elements = []; + const columnVectors = []; + for (let column = 0; column < t.params.columns; column++) { + const columnElements = []; + for (let row = 0; row < t.params.rows; row++) { + const v = (column + 1) * 10 + (row + 1); + elements.push(v); + columnElements.push(v); + } + columnVectors.push(columnType.create(columnElements)); + } + const fn = t.params.infer_type ? `mat${t.params.columns}x${t.params.rows}` : `${matrixType}`; + await run( + t, + basicExpressionBuilder((ops) => `${fn}(${ops.join(', ')})`), + columnVectors.map((v) => v.type), + matrixType, + t.params, + [ + { + input: columnVectors, + expected: matrixType.create(elements) + }] + + ); +}); + +g.test('abstract_matrix_column_vectors'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that a matrix constructed from abstract column vectors produces the expected value`). +params((u) => +u. +combine('concrete_type', ['f32', 'f16']). +combine('columns', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +beforeAllSubcases((t) => { + if (t.params.concrete_type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const concreteElementType = Type[t.params.concrete_type]; + const concreteMatrixType = Type.mat(t.params.columns, t.params.rows, concreteElementType); + const elements = []; + const columnVectors = []; + for (let column = 0; column < t.params.columns; column++) { + const columnElements = []; + for (let row = 0; row < t.params.rows; row++) { + const v = (column + 1) * 10 + (row + 1); + elements.push(v); + columnElements.push(`${v * 0x100000000}`); + } + columnVectors.push(`vec${t.params.rows}(${columnElements.join(', ')})`); + } + const fn = `mat${t.params.columns}x${t.params.rows}`; + await run( + t, + basicExpressionBuilder((_) => `${fn}(${columnVectors.join(', ')}) * (1.0 / 0x100000000)`), + [], + concreteMatrixType, + { inputSource: 'const' }, + [ + { + input: [], + expected: concreteMatrixType.create(elements) + }] + + ); +}); + +g.test('concrete_array_elements'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that an array constructed from concrete element values produces the expected value`). +params((u) => +u. +combine('inputSource', allInputSources). +combine('type', ['bool', 'i32', 'u32', 'f32', 'f16', 'vec3f', 'vec4i']). +combine('length', [1, 5, 10]). +combine('infer_type', [false, true]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const elementType = Type[t.params.type]; + const arrayType = Type.array(t.params.length, elementType); + const elements = []; + for (let i = 0; i < t.params.length; i++) { + elements.push((i + 1) * 10); + } + const fn = t.params.infer_type ? `array` : `${arrayType}`; + await run( + t, + basicExpressionBuilder((ops) => `${fn}(${ops.join(', ')})`), + elements.map((e) => elementType), + arrayType, + t.params, + [ + { + input: elements.map((e) => elementType.create(e)), + expected: arrayType.create(elements) + }] + + ); +}); + +g.test('abstract_array_elements'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that an array constructed from element values produces the expected value`). +params((u) => +u. +combine('abstract_type', [ +'abstract-int', +'abstract-float', +'vec3', +'vec4', +'mat2x3'] +). +expand('concrete_type', (t) => kConcreteTypesForAbstractType[t.abstract_type]). +combine('length', [1, 5, 10]) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(Type[t.params.concrete_type]).kind === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const count = t.params.length; + const concreteElementType = Type[t.params.concrete_type]; + const concreteArrayType = Type.array(count, concreteElementType); + const elements = []; + let i = 0; + const nextValue = () => ++i * 10; + for (let i = 0; i < count; i++) { + switch (t.params.abstract_type) { + case 'abstract-int':{ + const value = nextValue(); + elements.push({ args: `${value}`, value: concreteElementType.create(value) }); + break; + } + case 'abstract-float':{ + const value = nextValue(); + elements.push({ args: `${value}.0`, value: concreteElementType.create(value) }); + break; + } + case 'vec3':{ + const x = nextValue(); + const y = nextValue(); + const z = nextValue(); + elements.push({ + args: `vec3(${x}, ${y}, ${z})`, + value: concreteElementType.create([x, y, z]) + }); + break; + } + case 'vec4':{ + const x = nextValue(); + const y = nextValue(); + const z = nextValue(); + const w = nextValue(); + elements.push({ + args: `vec4(${x}.0, ${y}.0, ${z}.0, ${w}.0)`, + value: concreteElementType.create([x, y, z, w]) + }); + break; + } + case 'mat2x3':{ + const e00 = nextValue(); + const e01 = nextValue(); + const e02 = nextValue(); + const e10 = nextValue(); + const e11 = nextValue(); + const e12 = nextValue(); + elements.push({ + args: `mat2x3(vec3(${e00}.0, ${e01}.0, ${e02}.0), vec3(${e10}.0, ${e11}.0, ${e12}.0))`, + value: concreteElementType.create([e00, e01, e02, e10, e11, e12]) + }); + break; + } + } + } + const fn = `array`; + await run( + t, + basicExpressionBuilder((_) => `${fn}(${elements.map((e) => e.args).join(', ')})`), + [], + concreteArrayType, + { inputSource: 'const' }, + [ + { + input: [], + expected: new ArrayValue(elements.map((e) => e.value)) + }] + + ); +}); + +g.test('structure'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc(`Test that an structure constructed from element values produces the expected value`). +params((u) => +u. +combine('member_types', [ +['bool'], +['u32'], +['vec3f'], +['i32', 'u32'], +['i32', 'f16', 'vec4i', 'mat3x2f'], +['bool', 'u32', 'f16', 'vec3f', 'vec2i'], +['i32', 'u32', 'f32', 'f16', 'vec3f', 'vec4i']] +). +combine('nested', [false, true]). +beginSubcases(). +expand('member_index', (t) => t.member_types.map((_, i) => i)) +). +beforeAllSubcases((t) => { + if (t.params.member_types.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const memberType = Type[t.params.member_types[t.params.member_index]]; + const values = t.params.member_types.map((ty, i) => Type[ty].create(i)); + + const builder = basicExpressionBuilder((ops) => + t.params.nested ? + `OuterStruct(10, MyStruct(${ops.join(', ')}), 20).inner.member_${t.params.member_index}` : + `MyStruct(${ops.join(', ')}).member_${t.params.member_index}` + ); + await run( + t, + (parameterTypes, resultType, cases, inputSource) => { + return ` +${t.params.member_types.includes('f16') ? 'enable f16;' : ''} + +${builder(parameterTypes, resultType, cases, inputSource)} + +struct MyStruct { +${t.params.member_types.map((ty, i) => ` member_${i} : ${ty},`).join('\n')} +}; +struct OuterStruct { + pre : i32, + inner : MyStruct, + post : i32, +}; +`; + }, + t.params.member_types.map((ty) => Type[ty]), + memberType, + { inputSource: 'const' }, + [{ input: values, expected: values[t.params.member_index] }] + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/constructor/zero_value.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/constructor/zero_value.spec.js new file mode 100644 index 0000000000..5879f4f29d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/constructor/zero_value.spec.js @@ -0,0 +1,162 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for zero value constructors +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { Type } from '../../../../util/conversion.js'; +import { basicExpressionBuilder, run } from '../expression.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('scalar'). +specURL('https://www.w3.org/TR/WGSL/#zero-value-builtin-function'). +desc(`Test that a zero value scalar constructor produces the expected zero value`). +params((u) => u.combine('type', ['bool', 'i32', 'u32', 'f32', 'f16'])). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const type = Type[t.params.type]; + await run( + t, + basicExpressionBuilder((ops) => `${type}()`), + [], + type, + { inputSource: 'const' }, + [{ input: [], expected: type.create(0) }] + ); +}); + +g.test('vector'). +specURL('https://www.w3.org/TR/WGSL/#zero-value-builtin-function'). +desc(`Test that a zero value vector constructor produces the expected zero value`). +params((u) => +u. +combine('type', ['bool', 'i32', 'u32', 'f32', 'f16']). +combine('width', [2, 3, 4]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const type = Type.vec(t.params.width, Type[t.params.type]); + await run( + t, + basicExpressionBuilder((ops) => `${type}()`), + [], + type, + { inputSource: 'const' }, + [{ input: [], expected: type.create(0) }] + ); +}); + +g.test('matrix'). +specURL('https://www.w3.org/TR/WGSL/#zero-value-builtin-function'). +desc(`Test that a zero value matrix constructor produces the expected zero value`). +params((u) => +u. +combine('type', ['f32', 'f16']). +combine('columns', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const type = Type.mat(t.params.columns, t.params.rows, Type[t.params.type]); + await run( + t, + basicExpressionBuilder((ops) => `${type}()`), + [], + type, + { inputSource: 'const' }, + [{ input: [], expected: type.create(0) }] + ); +}); + +g.test('array'). +specURL('https://www.w3.org/TR/WGSL/#zero-value-builtin-function'). +desc(`Test that a zero value matrix constructor produces the expected zero value`). +params((u) => +u. +combine('type', ['bool', 'i32', 'u32', 'f32', 'f16', 'vec3f', 'vec4i']). +combine('length', [1, 5, 10]) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const type = Type.array(t.params.length, Type[t.params.type]); + await run( + t, + basicExpressionBuilder((ops) => `${type}()`), + [], + type, + { inputSource: 'const' }, + [{ input: [], expected: type.create(0) }] + ); +}); + +g.test('structure'). +specURL('https://www.w3.org/TR/WGSL/#zero-value-builtin-function'). +desc(`Test that an structure constructed from element values produces the expected value`). +params((u) => +u. +combine('member_types', [ +['bool'], +['u32'], +['vec3f'], +['i32', 'u32'], +['i32', 'f16', 'vec4i', 'mat3x2f'], +['bool', 'u32', 'f16', 'vec3f', 'vec2i'], +['i32', 'u32', 'f32', 'f16', 'vec3f', 'vec4i']] +). +combine('nested', [false, true]). +beginSubcases(). +expand('member_index', (t) => t.member_types.map((_, i) => i)) +). +beforeAllSubcases((t) => { + if (t.params.member_types.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn(async (t) => { + const memberType = Type[t.params.member_types[t.params.member_index]]; + const builder = basicExpressionBuilder((_) => + t.params.nested ? + `OuterStruct().inner.member_${t.params.member_index}` : + `MyStruct().member_${t.params.member_index}` + ); + await run( + t, + (parameterTypes, resultType, cases, inputSource) => { + return ` +${t.params.member_types.includes('f16') ? 'enable f16;' : ''} + +${builder(parameterTypes, resultType, cases, inputSource)} + +struct MyStruct { +${t.params.member_types.map((ty, i) => ` member_${i} : ${ty},`).join('\n')} +}; +struct OuterStruct { + pre : i32, + inner : MyStruct, + post : i32, +}; +`; + }, + [], + memberType, + { inputSource: 'const' }, + [{ input: [], expected: memberType.create(0) }] + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expectation.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expectation.js new file mode 100644 index 0000000000..d859117054 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expectation.js @@ -0,0 +1,38 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { compare } from '../../../util/compare.js';import { + ArrayValue, + MatrixValue, + + VectorValue, + isScalarValue } from +'../../../util/conversion.js'; +import { FPInterval } from '../../../util/floating_point.js'; + + + + + + + + +/** @returns if this Expectation actually a Comparator */ +export function isComparator(e) { + return !( + e instanceof FPInterval || + isScalarValue(e) || + e instanceof VectorValue || + e instanceof MatrixValue || + e instanceof ArrayValue || + e instanceof Array); + +} + +/** @returns the input if it is already a Comparator, otherwise wraps it in a 'value' comparator */ +export function toComparator(input) { + if (isComparator(input)) { + return input; + } + + return { compare: (got) => compare(got, input), kind: 'value' }; +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expression.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expression.js index d3d2d96c52..0503a1765d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expression.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expression.js @@ -2,241 +2,252 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { globalTestConfig } from '../../../../common/framework/test_config.js';import { assert, objectEquals, unreachable } from '../../../../common/util/util.js'; -import { compare } from '../../../util/compare.js'; import { kValue } from '../../../util/constants.js'; import { - ScalarType, - Scalar, - - TypeVec, - TypeU32, + MatrixType, - Vector, + ScalarType, + Type, VectorType, - u32, - i32, - Matrix, - MatrixType, - scalarTypeOf } from + VectorValue, + isAbstractType, + scalarTypeOf, + ArrayType, + elementTypeOf } from '../../../util/conversion.js'; -import { FPInterval } from '../../../util/floating_point.js'; -import { - cartesianProduct, - - quantizeToI32, - quantizeToU32 } from -'../../../util/math.js'; - +import { align } from '../../../util/math.js'; +import { toComparator } from './expectation.js'; +/** The input value source */ -/** @returns if this Expectation actually a Comparator */ -export function isComparator(e) { - return !( - e instanceof FPInterval || - e instanceof Scalar || - e instanceof Vector || - e instanceof Matrix || - e instanceof Array); - -} - -/** @returns the input if it is already a Comparator, otherwise wraps it in a 'value' comparator */ -export function toComparator(input) { - if (isComparator(input)) { - return input; - } - - return { compare: (got) => compare(got, input), kind: 'value' }; -} - -/** Case is a single expression test case. */ +// Read-write storage buffer +/** All possible input sources */ +export const allInputSources = ['const', 'uniform', 'storage_r', 'storage_rw']; +/** Just constant input source */ +export const onlyConstInputSource = ['const']; +/** All input sources except const */ +export const allButConstInputSource = ['uniform', 'storage_r', 'storage_rw']; +/** Configuration for running a expression test */ -/** CaseList is a list of Cases */ -/** The input value source */ -// Read-write storage buffer -/** All possible input sources */ -export const allInputSources = ['const', 'uniform', 'storage_r', 'storage_rw']; -/** Just constant input source */ -export const onlyConstInputSource = ['const']; -/** Configuration for running a expression test */ +/** + * @returns the size and alignment in bytes of the type 'ty', taking into + * consideration storage alignment constraints and abstract numerics, which are + * encoded as a struct of holding two u32s. + */ +function sizeAndAlignmentOf(ty, source) { + if (ty instanceof ScalarType) { + if (ty.kind === 'abstract-float' || ty.kind === 'abstract-int') { + // AbstractFloats and AbstractInts are passed out of the shader via structs of + // 2x u32s and unpacking containers as arrays + return { size: 8, alignment: 8 }; + } + return { size: ty.size, alignment: ty.alignment }; + } + if (ty instanceof VectorType) { + const out = sizeAndAlignmentOf(ty.elementType, source); + const n = ty.width === 3 ? 4 : ty.width; + out.size *= n; + out.alignment *= n; + return out; + } + if (ty instanceof MatrixType) { + const out = sizeAndAlignmentOf(ty.elementType, source); + const n = ty.rows === 3 ? 4 : ty.rows; + out.size *= n * ty.cols; + out.alignment *= n; + return out; + } + if (ty instanceof ArrayType) { + const out = sizeAndAlignmentOf(ty.elementType, source); + if (source === 'uniform') { + out.alignment = align(out.alignment, 16); + } + out.size *= ty.count; + return out; + } + unreachable(`unhandled type: ${ty}`); +} +/** + * @returns the stride in bytes of the type 'ty', taking into consideration abstract numerics, + * which are encoded as a struct of 2 x u32. + */ +function strideOf(ty, source) { + const sizeAndAlign = sizeAndAlignmentOf(ty, source); + return align(sizeAndAlign.size, sizeAndAlign.alignment); +} +/** + * Calls 'callback' with the layout information of each structure member with the types 'members'. + * @returns the byte size, stride and alignment of the structure. + */ +export function structLayout( +members, +source, +callback) -// Helper for returning the stride for a given Type -function valueStride(ty) { - // AbstractFloats are passed out of the shader via a struct of 2x u32s and - // unpacking containers as arrays - if (scalarTypeOf(ty).kind === 'abstract-float') { - if (ty instanceof ScalarType) { - return 16; - } - if (ty instanceof VectorType) { - if (ty.width === 2) { - return 16; - } - // vec3s have padding to make them the same size as vec4s - return 32; - } - if (ty instanceof MatrixType) { - switch (ty.cols) { - case 2: - switch (ty.rows) { - case 2: - return 32; - case 3: - return 64; - case 4: - return 64; - } - break; - case 3: - switch (ty.rows) { - case 2: - return 48; - case 3: - return 96; - case 4: - return 96; - } - break; - case 4: - switch (ty.rows) { - case 2: - return 64; - case 3: - return 128; - case 4: - return 128; - } - break; - } +{ + let offset = 0; + let alignment = 1; + for (let i = 0; i < members.length; i++) { + const member = members[i]; + const sizeAndAlign = sizeAndAlignmentOf(member, source); + offset = align(offset, sizeAndAlign.alignment); + if (callback) { + callback({ + index: i, + type: member, + size: sizeAndAlign.size, + alignment: sizeAndAlign.alignment, + offset + }); } - unreachable(`AbstractFloats have not yet been implemented for ${ty.toString()}`); + offset += sizeAndAlign.size; + alignment = Math.max(alignment, sizeAndAlign.alignment); } - if (ty instanceof MatrixType) { - switch (ty.cols) { - case 2: - switch (ty.rows) { - case 2: - return 16; - case 3: - return 32; - case 4: - return 32; - } - break; - case 3: - switch (ty.rows) { - case 2: - return 32; - case 3: - return 64; - case 4: - return 64; - } - break; - case 4: - switch (ty.rows) { - case 2: - return 32; - case 3: - return 64; - case 4: - return 64; - } - break; - } - unreachable( - `Attempted to get stride length for a matrix with dimensions (${ty.cols}x${ty.rows}), which isn't currently handled` - ); + if (source === 'uniform') { + alignment = align(alignment, 16); } - // Handles scalars and vectors - return 16; + const size = offset; + const stride = align(size, alignment); + return { size, stride, alignment }; } -// Helper for summing up all of the stride values for an array of Types -function valueStrides(tys) { - return tys.map(valueStride).reduce((sum, c) => sum + c); +/** @returns the stride in bytes between two consecutive structures with the given members */ +export function structStride(members, source) { + return structLayout(members, source).stride; +} + +/** @returns the WGSL to describe the structure members in 'members' */ +function wgslMembers(members, source, memberName) { + const lines = []; + const layout = structLayout(members, source, (m) => { + lines.push(` @size(${m.size}) ${memberName(lines.length)} : ${m.type},`); + }); + const padding = layout.stride - layout.size; + if (padding > 0) { + // Pad with a 'f16' if the padding requires an odd multiple of 2 bytes. + // This is required as 'i32' has an alignment and size of 4 bytes. + const ty = (padding & 2) !== 0 ? 'f16' : 'i32'; + lines.push(` @size(${padding}) padding : ${ty},`); + } + return lines.join('\n'); } // Helper for returning the WGSL storage type for the given Type. function storageType(ty) { if (ty instanceof ScalarType) { assert(ty.kind !== 'f64', `No storage type defined for 'f64' values`); + assert(ty.kind !== 'abstract-int', `Custom handling is implemented for 'abstract-int' values`); assert( ty.kind !== 'abstract-float', `Custom handling is implemented for 'abstract-float' values` ); if (ty.kind === 'bool') { - return TypeU32; + return Type.u32; } } if (ty instanceof VectorType) { - return TypeVec(ty.width, storageType(ty.elementType)); + return Type.vec(ty.width, storageType(ty.elementType)); + } + if (ty instanceof ArrayType) { + return Type.array(ty.count, storageType(ty.elementType)); } return ty; } +/** Structure used to hold [from|to]Storage conversion helpers */ + + + + + + + // Helper for converting a value of the type 'ty' from the storage type. -function fromStorage(ty, expr) { +function fromStorage(ty, expr, helpers) { if (ty instanceof ScalarType) { - assert(ty.kind !== 'abstract-float', `AbstractFloat values should not be in input storage`); + assert(ty.kind !== 'abstract-int', `'abstract-int' values should not be in input storage`); + assert(ty.kind !== 'abstract-float', `'abstract-float' values should not be in input storage`); assert(ty.kind !== 'f64', `'No storage type defined for 'f64' values`); if (ty.kind === 'bool') { return `${expr} != 0u`; } } if (ty instanceof VectorType) { + assert( + ty.elementType.kind !== 'abstract-int', + `'abstract-int' values cannot appear in input storage` + ); assert( ty.elementType.kind !== 'abstract-float', - `AbstractFloat values cannot appear in input storage` + `'abstract-float' values cannot appear in input storage` ); assert(ty.elementType.kind !== 'f64', `'No storage type defined for 'f64' values`); if (ty.elementType.kind === 'bool') { - return `${expr} != vec${ty.width}(0u)`; + return `(${expr} != vec${ty.width}(0u))`; } } + if (ty instanceof ArrayType && elementTypeOf(ty) === Type.bool) { + // array -> array + const conv = helpers.uniqueID(); + const inTy = Type.array(ty.count, Type.u32); + helpers.wgsl += ` +fn ${conv}(in : ${inTy}) -> ${ty} { + var out : ${ty}; + for (var i = 0; i < ${ty.count}; i++) { + out[i] = in[i] != 0; + } + return out; +} +`; + return `${conv}(${expr})`; + } return expr; } // Helper for converting a value of the type 'ty' to the storage type. -function toStorage(ty, expr) { +function toStorage(ty, expr, helpers) { if (ty instanceof ScalarType) { + assert( + ty.kind !== 'abstract-int', + `'abstract-int' values have custom code for writing to storage` + ); assert( ty.kind !== 'abstract-float', - `AbstractFloat values have custom code for writing to storage` + `'abstract-float' values have custom code for writing to storage` ); assert(ty.kind !== 'f64', `No storage type defined for 'f64' values`); if (ty.kind === 'bool') { @@ -244,15 +255,34 @@ function toStorage(ty, expr) { } } if (ty instanceof VectorType) { + assert( + ty.elementType.kind !== 'abstract-int', + `'abstract-int' values have custom code for writing to storage` + ); assert( ty.elementType.kind !== 'abstract-float', - `AbstractFloat values have custom code for writing to storage` + `'abstract-float' values have custom code for writing to storage` ); assert(ty.elementType.kind !== 'f64', `'No storage type defined for 'f64' values`); if (ty.elementType.kind === 'bool') { return `select(vec${ty.width}(0u), vec${ty.width}(1u), ${expr})`; } } + if (ty instanceof ArrayType && elementTypeOf(ty) === Type.bool) { + // array -> array + const conv = helpers.uniqueID(); + const outTy = Type.array(ty.count, Type.u32); + helpers.wgsl += ` +fn ${conv}(in : ${ty}) -> ${outTy} { + var out : ${outTy}; + for (var i = 0; i < ${ty.count}; i++) { + out[i] = select(0u, 1u, in[i]); + } + return out; +} +`; + return `${conv}(${expr})`; + } return expr; } @@ -325,12 +355,13 @@ batch_size) // 2k appears to be a sweet-spot when benchmarking. return Math.floor( Math.min(1024 * 2, t.device.limits.maxUniformBufferBindingSize) / - valueStrides(parameterTypes) + structStride(parameterTypes, cfg.inputSource) ); case 'storage_r': case 'storage_rw': return Math.floor( - t.device.limits.maxStorageBufferBindingSize / valueStrides(parameterTypes) + t.device.limits.maxStorageBufferBindingSize / + structStride(parameterTypes, cfg.inputSource) ); } }(); @@ -409,7 +440,8 @@ inputSource, pipelineCache) { // Construct a buffer to hold the results of the expression tests - const outputBufferSize = cases.length * valueStride(resultType); + const outputStride = structStride([resultType], 'storage_rw'); + const outputBufferSize = align(cases.length * outputStride, 4); const outputBuffer = t.device.createBuffer({ size: outputBufferSize, usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE @@ -444,7 +476,7 @@ pipelineCache) // Read the outputs from the output buffer const outputs = new Array(cases.length); for (let i = 0; i < cases.length; i++) { - outputs[i] = resultType.read(outputData, i * valueStride(resultType)); + outputs[i] = resultType.read(outputData, i * outputStride); } // The list of expectation failures @@ -507,10 +539,13 @@ function map(v, fn) { */ function wgslOutputs(resultType, count) { let output_struct = undefined; - if (scalarTypeOf(resultType).kind !== 'abstract-float') { + if ( + scalarTypeOf(resultType).kind !== 'abstract-float' && + scalarTypeOf(resultType).kind !== 'abstract-int') + { output_struct = ` struct Output { - @size(${valueStride(resultType)}) value : ${storageType(resultType)} + @size(${strideOf(resultType, 'storage_rw')}) value : ${storageType(resultType)} };`; } else { if (resultType instanceof ScalarType) { @@ -520,7 +555,7 @@ struct Output { }; struct Output { - @size(${valueStride(resultType)}) value: AF, + @size(${strideOf(resultType, 'storage_rw')}) value: AF, };`; } if (resultType instanceof VectorType) { @@ -531,7 +566,7 @@ struct Output { }; struct Output { - @size(${valueStride(resultType)}) value: array, + @size(${strideOf(resultType, 'storage_rw')}) value: array, };`; } @@ -544,7 +579,7 @@ struct Output { }; struct Output { - @size(${valueStride(resultType)}) value: array, ${cols}>, + @size(${strideOf(resultType, 'storage_rw')}) value: array, ${cols}>, };`; } @@ -615,16 +650,25 @@ resultType, cases, inputSource) { + 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` + `abstractFloatShaderBuilder should be used when result type is 'abstract-float'` ); + let nextUniqueIDSuffix = 0; + const convHelpers = { + wgsl: '', + uniqueID: () => `cts_symbol_${nextUniqueIDSuffix++}` + }; if (inputSource === 'const') { ////////////////////////////////////////////////////////////////////////// // Constant eval ////////////////////////////////////////////////////////////////////////// let body = ''; - if (parameterTypes.some((ty) => scalarTypeOf(ty).kind === 'abstract-float')) { + if (parameterTypes.some((ty) => isAbstractType(elementTypeOf(ty)))) { // Directly assign the expression to the output, to avoid an // intermediate store, which will concretize the value early body = cases. @@ -632,7 +676,8 @@ inputSource) (c, i) => ` outputs[${i}].value = ${toStorage( resultType, - expressionBuilder(map(c.input, (v) => v.wgsl())) + expressionBuilder(map(c.input, (v) => v.wgsl())), + convHelpers )};` ). join('\n '); @@ -640,47 +685,60 @@ inputSource) body = cases. map((_, i) => { const value = `values[${i}]`; - return ` outputs[${i}].value = ${toStorage(resultType, value)};`; + return ` outputs[${i}].value = ${toStorage(resultType, value, convHelpers)};`; }). join('\n '); } else { body = ` for (var i = 0u; i < ${cases.length}; i++) { - outputs[i].value = ${toStorage(resultType, `values[i]`)}; + outputs[i].value = ${toStorage(resultType, `values[i]`, convHelpers)}; }`; } + // If params are abstract, we will assign them directly to the storage array, so skip the values array. + let valuesArray = ''; + if (!parameterTypes.some(isAbstractType)) { + valuesArray = wgslValuesArray(parameterTypes, resultType, cases, expressionBuilder); + } + return ` ${wgslOutputs(resultType, cases.length)} -${wgslValuesArray(parameterTypes, resultType, cases, expressionBuilder)} +${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, i) => fromStorage(ty, `inputs[i].param${i}`); + const paramExpr = (ty, i) => fromStorage(ty, `inputs[i].param${i}`, convHelpers); // resolves to the expression that calls the builtin - const expr = toStorage(resultType, expressionBuilder(parameterTypes.map(paramExpr))); + const expr = toStorage( + resultType, + expressionBuilder(parameterTypes.map(paramExpr)), + convHelpers + ); return ` struct Input { -${parameterTypes. - map((ty, i) => ` @size(${valueStride(ty)}) param${i} : ${storageType(ty)},`). - join('\n')} -}; +${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++) { @@ -807,8 +865,7 @@ ${wgslHeader(parameterTypes, resultType)} ${wgslOutputs(resultType, cases.length)} struct Input { - @size(${valueStride(lhsType)}) lhs : ${storageType(lhsType)}, - @size(${valueStride(rhsType)}) rhs : ${storageType(rhsType)}, +${wgslMembers([lhsType, rhsType].map(storageType), inputSource, (i) => ['lhs', 'rhs'][i])} } ${wgslInputVar(inputSource, cases.length)} @@ -972,7 +1029,7 @@ export function abstractFloatShaderBuilder(expressionBuilder) { cases, inputSource) => { - assert(inputSource === 'const', 'AbstractFloat results are only defined for const-eval'); + assert(inputSource === 'const', `'abstract-float' results are only defined for const-eval`); assert( scalarTypeOf(resultType).kind === 'abstract-float', `Expected resultType of 'abstract-float', received '${scalarTypeOf(resultType).kind}' instead` @@ -997,6 +1054,90 @@ ${body} }; } +/** + * @returns a string that extracts the value of an AbstractInt into an output + * destination + * @param expr expression for an AbstractInt value, if working with vectors, + * this string needs to include indexing into the container. + * @param case_idx index in the case output array to assign the result + * @param accessor string representing how access to the AbstractInt that needs + * to be operated on. + * For scalars this should be left as ''. + * For vectors this will be an indexing operation, + * i.e. '[i]' + */ +function abstractIntSnippet(expr, case_idx, accessor = '') { + // AbstractInts are i64s under the hood. WebGPU does not support + // putting i64s in buffers, or any 64-bit simple types, so the result needs to + // be split up into u32 bitfields + // + // Since there is no 64-bit data type that can be used as an element for a + // vector or a matrix in WGSL, the testing framework needs to pass the u32s + // via a struct with two u32s, and deconstruct vectors into arrays. + // + // This is complicated by the fact that user defined functions cannot + // take/return AbstractInts, and AbstractInts cannot be stored in + // variables, so the code cannot just inject a simple utility function + // at the top of the shader, instead this snippet needs to be inlined + // everywhere the test needs to return an AbstractInt. + return ` { + outputs[${case_idx}].value${accessor}.high = bitcast(i32(${expr}${accessor} >> 32)) & 0xFFFFFFFF; + const low_sign = (${expr}${accessor} & (1 << 31)); + outputs[${case_idx}].value${accessor}.low = bitcast((${expr}${accessor} & 0x7FFFFFFF)) | low_sign; + }`; +} + +/** @returns a string for a specific case that has a AbstractInt result */ +function abstractIntCaseBody(expr, resultType, i) { + if (resultType instanceof ScalarType) { + return abstractIntSnippet(expr, i); + } + + if (resultType instanceof VectorType) { + return [...Array(resultType.width).keys()]. + map((idx) => abstractIntSnippet(expr, i, `[${idx}]`)). + join(' \n'); + } + + unreachable(`Results of type '${resultType}' not yet implemented`); +} + +/** + * @returns a ShaderBuilder that builds a test shader hands AbstractInt results. + * @param expressionBuilder an expression builder that will return AbstractInts + */ +export function abstractIntShaderBuilder(expressionBuilder) { + return ( + parameterTypes, + resultType, + cases, + inputSource) => + { + assert(inputSource === 'const', `'abstract-int' results are only defined for const-eval`); + assert( + scalarTypeOf(resultType).kind === 'abstract-int', + `Expected resultType of 'abstract-int', received '${scalarTypeOf(resultType).kind}' instead` + ); + + const body = cases. + map((c, i) => { + const expr = `${expressionBuilder(map(c.input, (v) => v.wgsl()))}`; + return abstractIntCaseBody(expr, resultType, i); + }). + join('\n '); + + return ` +${wgslHeader(parameterTypes, resultType)} + +${wgslOutputs(resultType, cases.length)} + +@compute @workgroup_size(1) +fn main() { +${body} +}`; + }; +} + /** * Constructs and returns a GPUComputePipeline and GPUBindGroup for running a * batch of test cases. If a pre-created pipeline can be found in @@ -1060,27 +1201,23 @@ pipelineCache) // Input values come from a uniform or storage buffer // size in bytes of the input buffer - const inputSize = cases.length * valueStrides(parameterTypes); + const caseStride = structStride(parameterTypes, inputSource); + const inputSize = align(cases.length * caseStride, 4); // Holds all the parameter values for all cases const inputData = new Uint8Array(inputSize); // Pack all the input parameter values into the inputData buffer - { - const caseStride = valueStrides(parameterTypes); - for (let caseIdx = 0; caseIdx < cases.length; caseIdx++) { - const caseBase = caseIdx * caseStride; - let offset = caseBase; - for (let paramIdx = 0; paramIdx < parameterTypes.length; paramIdx++) { - const params = cases[caseIdx].input; - if (params instanceof Array) { - params[paramIdx].copyTo(inputData, offset); - } else { - params.copyTo(inputData, offset); - } - offset += valueStride(parameterTypes[paramIdx]); + for (let caseIdx = 0; caseIdx < cases.length; caseIdx++) { + const offset = caseIdx * caseStride; + structLayout(parameterTypes, inputSource, (m) => { + const arg = cases[caseIdx].input; + if (arg instanceof Array) { + arg[m.index].copyTo(inputData, offset + m.offset); + } else { + arg.copyTo(inputData, offset + m.offset); } - } + }); } // build the compute pipeline, if the shader hasn't been compiled already. @@ -1123,7 +1260,7 @@ pipelineCache) * If `cases.length` is not a multiple of `vectorWidth`, then the last scalar * test case value is repeated to fill the vector value. */ -function packScalarsToVector( +export function packScalarsToVector( parameterTypes, resultType, cases, @@ -1145,8 +1282,8 @@ vectorWidth) } const packedCases = []; - const packedParameterTypes = parameterTypes.map((p) => TypeVec(vectorWidth, p)); - const packedResultType = new VectorType(vectorWidth, resultType); + const packedParameterTypes = parameterTypes.map((p) => Type.vec(vectorWidth, p)); + const packedResultType = Type.vec(vectorWidth, resultType); const clampCaseIdx = (idx) => Math.min(idx, cases.length - 1); @@ -1160,7 +1297,7 @@ vectorWidth) const input = cases[clampCaseIdx(caseIdx + i)].input; inputElements[i] = input instanceof Array ? input[paramIdx] : input; } - packedInputs[paramIdx] = new Vector(inputElements); + packedInputs[paramIdx] = new VectorValue(inputElements); } // Gather the comparators for the packed cases @@ -1198,239 +1335,4 @@ vectorWidth) parameterTypes: packedParameterTypes, resultType: packedResultType }; -} - -/** - * Indicates bounds that acceptance intervals need to be within to avoid inputs - * being filtered out. This is used for const-eval tests, since going OOB will - * cause a validation error not an execution error. - */ - - -// No expectations - -/** - * A function that performs a binary operation on x and y, and returns the expected - * result. - */ - - - - -/** - * @returns array of Case for the input params with op applied - * @param param0s array of inputs to try for the first param - * @param param1s array of inputs to try for the second param - * @param op callback called on each pair of inputs to produce each case - * @param quantize function to quantize all values - * @param scalarize function to convert numbers to Scalars - */ -function generateScalarBinaryToScalarCases( -param0s, -param1s, -op, -quantize, -scalarize) -{ - param0s = param0s.map(quantize); - param1s = param1s.map(quantize); - return cartesianProduct(param0s, param1s).reduce((cases, e) => { - const expected = op(e[0], e[1]); - if (expected !== undefined) { - cases.push({ input: [scalarize(e[0]), scalarize(e[1])], expected: scalarize(expected) }); - } - return cases; - }, new Array()); -} - -/** - * @returns an array of Cases for operations over a range of inputs - * @param param0s array of inputs to try for the first param - * @param param1s array of inputs to try for the second param - * @param op callback called on each pair of inputs to produce each case - */ -export function generateBinaryToI32Cases( -param0s, -param1s, -op) -{ - return generateScalarBinaryToScalarCases(param0s, param1s, op, quantizeToI32, i32); -} - -/** - * @returns an array of Cases for operations over a range of inputs - * @param param0s array of inputs to try for the first param - * @param param1s array of inputs to try for the second param - * @param op callback called on each pair of inputs to produce each case - */ -export function generateBinaryToU32Cases( -param0s, -param1s, -op) -{ - return generateScalarBinaryToScalarCases(param0s, param1s, op, quantizeToU32, u32); -} - -/** - * @returns a Case for the input params with op applied - * @param scalar scalar param - * @param vector vector param (2, 3, or 4 elements) - * @param op the op to apply to scalar and vector - * @param quantize function to quantize all values in vectors and scalars - * @param scalarize function to convert numbers to Scalars - */ -function makeScalarVectorBinaryToVectorCase( -scalar, -vector, -op, -quantize, -scalarize) -{ - scalar = quantize(scalar); - vector = vector.map(quantize); - const result = vector.map((v) => op(scalar, v)); - if (result.includes(undefined)) { - return undefined; - } - return { - input: [scalarize(scalar), new Vector(vector.map(scalarize))], - expected: new Vector(result.map(scalarize)) - }; -} - -/** - * @returns array of Case for the input params with op applied - * @param scalars array of scalar params - * @param vectors array of vector params (2, 3, or 4 elements) - * @param op the op to apply to each pair of scalar and vector - * @param quantize function to quantize all values in vectors and scalars - * @param scalarize function to convert numbers to Scalars - */ -function generateScalarVectorBinaryToVectorCases( -scalars, -vectors, -op, -quantize, -scalarize) -{ - const cases = new Array(); - scalars.forEach((s) => { - vectors.forEach((v) => { - const c = makeScalarVectorBinaryToVectorCase(s, v, op, quantize, scalarize); - if (c !== undefined) { - cases.push(c); - } - }); - }); - return cases; -} - -/** - * @returns a Case for the input params with op applied - * @param vector vector param (2, 3, or 4 elements) - * @param scalar scalar param - * @param op the op to apply to vector and scalar - * @param quantize function to quantize all values in vectors and scalars - * @param scalarize function to convert numbers to Scalars - */ -function makeVectorScalarBinaryToVectorCase( -vector, -scalar, -op, -quantize, -scalarize) -{ - vector = vector.map(quantize); - scalar = quantize(scalar); - const result = vector.map((v) => op(v, scalar)); - if (result.includes(undefined)) { - return undefined; - } - return { - input: [new Vector(vector.map(scalarize)), scalarize(scalar)], - expected: new Vector(result.map(scalarize)) - }; -} - -/** - * @returns array of Case for the input params with op applied - * @param vectors array of vector params (2, 3, or 4 elements) - * @param scalars array of scalar params - * @param op the op to apply to each pair of vector and scalar - * @param quantize function to quantize all values in vectors and scalars - * @param scalarize function to convert numbers to Scalars - */ -function generateVectorScalarBinaryToVectorCases( -vectors, -scalars, -op, -quantize, -scalarize) -{ - const cases = new Array(); - scalars.forEach((s) => { - vectors.forEach((v) => { - const c = makeVectorScalarBinaryToVectorCase(v, s, op, quantize, scalarize); - if (c !== undefined) { - cases.push(c); - } - }); - }); - return cases; -} - -/** - * @returns array of Case for the input params with op applied - * @param scalars array of scalar params - * @param vectors array of vector params (2, 3, or 4 elements) - * @param op he op to apply to each pair of scalar and vector - */ -export function generateU32VectorBinaryToVectorCases( -scalars, -vectors, -op) -{ - return generateScalarVectorBinaryToVectorCases(scalars, vectors, op, quantizeToU32, u32); -} - -/** - * @returns array of Case for the input params with op applied - * @param vectors array of vector params (2, 3, or 4 elements) - * @param scalars array of scalar params - * @param op he op to apply to each pair of vector and scalar - */ -export function generateVectorU32BinaryToVectorCases( -vectors, -scalars, -op) -{ - return generateVectorScalarBinaryToVectorCases(vectors, scalars, op, quantizeToU32, u32); -} - -/** - * @returns array of Case for the input params with op applied - * @param scalars array of scalar params - * @param vectors array of vector params (2, 3, or 4 elements) - * @param op he op to apply to each pair of scalar and vector - */ -export function generateI32VectorBinaryToVectorCases( -scalars, -vectors, -op) -{ - return generateScalarVectorBinaryToVectorCases(scalars, vectors, op, quantizeToI32, i32); -} - -/** - * @returns array of Case for the input params with op applied - * @param vectors array of vector params (2, 3, or 4 elements) - * @param scalars array of scalar params - * @param op he op to apply to each pair of vector and scalar - */ -export function generateVectorI32BinaryToVectorCases( -vectors, -scalars, -op) -{ - return generateVectorScalarBinaryToVectorCases(vectors, scalars, op, quantizeToI32, i32); } \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/interval_filter.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/interval_filter.js new file mode 100644 index 0000000000..d70e087a74 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/interval_filter.js @@ -0,0 +1,9 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ /** + * Indicates bounds that acceptance intervals need to be within to avoid inputs + * being filtered out. This is used for const-eval tests, since going OOB will + * cause a validation error not an execution error. + */ +// No expectations +export {}; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/precedence.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/precedence.spec.js new file mode 100644 index 0000000000..6bdea30e43 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/precedence.spec.js @@ -0,0 +1,113 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for operator precedence. +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { GPUTest } from '../../../gpu_test.js'; + +export const g = makeTestGroup(GPUTest); + +// The list of test cases and their expected results. + + + + +const kExpressions = { + add_mul: { expr: 'kThree + kSeven * kEleven', result: 80 }, + mul_add: { expr: 'kThree * kSeven + kEleven', result: 32 }, + sub_neg: { expr: 'kThree - - kSeven', result: 10 }, + neg_shl: { expr: '- kThree << u32(kSeven)', result: -384 }, + neg_shr: { expr: '- kThree >> u32(kSeven)', result: -1 }, + neg_add: { expr: '- kThree + kSeven', result: 4 }, + neg_mul: { expr: '- kThree * kSeven', result: -21 }, + neg_and: { expr: '- kThree & kSeven', result: 5 }, + neg_or: { expr: '- kThree | kSeven', result: -1 }, + neg_xor: { expr: '- kThree ^ kSeven', result: -6 }, + comp_add: { expr: '~ kThree + kSeven', result: 3 }, + mul_deref: { expr: 'kThree * * ptr_five', result: 15 }, + not_and: { expr: 'i32(! kFalse && kFalse)', result: 0 }, + not_or: { expr: 'i32(! kTrue || kTrue)', result: 1 }, + eq_and: { expr: 'i32(kFalse == kTrue && kFalse)', result: 0 }, + and_eq: { expr: 'i32(kFalse && kTrue == kFalse)', result: 0 }, + eq_or: { expr: 'i32(kFalse == kFalse || kTrue)', result: 1 }, + or_eq: { expr: 'i32(kTrue || kFalse == kFalse)', result: 1 }, + add_swizzle: { expr: '(vec + vec . y) . z', result: 8 } +}; + +g.test('precedence'). +desc( + ` + Test that operator precedence rules are correctly implemented. + ` +). +params((u) => +u. +combine('expr', keysOf(kExpressions)). +combine('decl', ['literal', 'const', 'override', 'var']). +combine('strip_spaces', [false, true]) +). +fn((t) => { + const expr = kExpressions[t.params.expr]; + + let decl = t.params.decl; + let expr_wgsl = expr.expr; + if (t.params.decl === 'literal') { + decl = 'const'; + expr_wgsl = expr_wgsl.replace(/kThree/g, '3'); + expr_wgsl = expr_wgsl.replace(/kSeven/g, '7'); + expr_wgsl = expr_wgsl.replace(/kEleven/g, '11'); + expr_wgsl = expr_wgsl.replace(/kFalse/g, 'false'); + expr_wgsl = expr_wgsl.replace(/kTrue/g, 'true'); + } + if (t.params.strip_spaces) { + expr_wgsl = expr_wgsl.replace(/ /g, ''); + } + const wgsl = ` + @group(0) @binding(0) var buffer : i32; + + ${decl} kFalse = false; + ${decl} kTrue = true; + + ${decl} kThree = 3; + ${decl} kSeven = 7; + ${decl} kEleven = 11; + + @compute @workgroup_size(1) + fn main() { + var five = 5; + var vec = vec4(1, kThree, 5, kSeven); + let ptr_five = &five; + + buffer = ${expr_wgsl}; + } + `; + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ code: wgsl }) + } + }); + + // Allocate a buffer and fill it with 0xdeadbeef. + const outputBuffer = t.makeBufferWithContents( + new Uint32Array([0xdeadbeef]), + GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC + ); + const bindGroup = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [{ binding: 0, resource: { buffer: outputBuffer } }] + }); + + // Run the shader. + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bindGroup); + pass.dispatchWorkgroups(1); + pass.end(); + t.queue.submit([encoder.finish()]); + + // Check that the result is as expected. + t.expectGPUBufferValuesEqual(outputBuffer, new Int32Array([expr.result])); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/address_of_and_indirection.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/address_of_and_indirection.spec.js new file mode 100644 index 0000000000..f68dc18822 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/address_of_and_indirection.spec.js @@ -0,0 +1,171 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for unary address-of and indirection (dereference) +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../common/util/data_tables.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { scalarType } from '../../../../util/conversion.js'; +import { sparseScalarF32Range } from '../../../../util/math.js'; +import { + allButConstInputSource, + basicExpressionWithPredeclarationBuilder, + run } from +'../expression.js'; + +export const g = makeTestGroup(GPUTest); + +// All the ways to deref an expression +const kDerefCases = { + deref_address_of_identifier: { + wgsl: '(*(&a))', + requires_pointer_composite_access: false + }, + deref_pointer: { + wgsl: '(*p)', + requires_pointer_composite_access: false + }, + address_of_identifier: { + wgsl: '(&a)', + requires_pointer_composite_access: true + }, + pointer: { + wgsl: 'p', + requires_pointer_composite_access: true + } +}; + +g.test('deref'). +specURL('https://www.w3.org/TR/WGSL/#indirection'). +desc( + ` +Expression: *e + +Pointer expression dereference. +` +). +params((u) => +u. +combine('inputSource', allButConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]). +combine('scalarType', ['bool', 'u32', 'i32', 'f32', 'f16']). +combine('derefType', keysOf(kDerefCases)). +filter((p) => !kDerefCases[p.derefType].requires_pointer_composite_access) +). +beforeAllSubcases((t) => { + if (t.params.scalarType === 'f16') { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); + } +}). +fn(async (t) => { + const ty = scalarType(t.params.scalarType); + const cases = sparseScalarF32Range().map((e) => { + return { input: ty.create(e), expected: ty.create(e) }; + }); + const elemType = ty.kind; + const type = t.params.vectorize ? `vec${t.params.vectorize}<${elemType}>` : elemType; + const shaderBuilder = basicExpressionWithPredeclarationBuilder( + (value) => `get_dereferenced_value(${value})`, + `fn get_dereferenced_value(value: ${type}) -> ${type} { + var a = value; + let p = &a; + return ${kDerefCases[t.params.derefType].wgsl}; + }` + ); + await run(t, shaderBuilder, [ty], ty, t.params, cases); +}); + +g.test('deref_index'). +specURL('https://www.w3.org/TR/WGSL/#logical-expr'). +desc( + ` +Expression: (*e)[index] + +Pointer expression dereference as lhs of index accessor expression +` +). +params((u) => +u. +combine('inputSource', allButConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]). +combine('scalarType', ['bool', 'u32', 'i32', 'f32', 'f16']). +combine('derefType', keysOf(kDerefCases)) +). +beforeAllSubcases((t) => { + if (t.params.scalarType === 'f16') { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); + } +}). +fn(async (t) => { + if ( + kDerefCases[t.params.derefType].requires_pointer_composite_access && + !t.hasLanguageFeature('pointer_composite_access')) + { + return; + } + + const ty = scalarType(t.params.scalarType); + const cases = sparseScalarF32Range().map((e) => { + return { input: ty.create(e), expected: ty.create(e) }; + }); + const elemType = ty.kind; + const type = t.params.vectorize ? `vec${t.params.vectorize}<${elemType}>` : elemType; + const shaderBuilder = basicExpressionWithPredeclarationBuilder( + (value) => `get_dereferenced_value(${value})`, + `fn get_dereferenced_value(value: ${type}) -> ${type} { + var a = array<${type}, 1>(value); + let p = &a; + return ${kDerefCases[t.params.derefType].wgsl}[0]; + }` + ); + await run(t, shaderBuilder, [ty], ty, t.params, cases); +}); + +g.test('deref_member'). +specURL('https://www.w3.org/TR/WGSL/#logical-expr'). +desc( + ` +Expression: (*e).member + +Pointer expression dereference as lhs of member accessor expression +` +). +params((u) => +u. +combine('inputSource', allButConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]). +combine('scalarType', ['bool', 'u32', 'i32', 'f32', 'f16']). +combine('derefType', keysOf(kDerefCases)) +). +beforeAllSubcases((t) => { + if (t.params.scalarType === 'f16') { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); + } +}). +fn(async (t) => { + if ( + kDerefCases[t.params.derefType].requires_pointer_composite_access && + !t.hasLanguageFeature('pointer_composite_access')) + { + return; + } + + const ty = scalarType(t.params.scalarType); + const cases = sparseScalarF32Range().map((e) => { + return { input: ty.create(e), expected: ty.create(e) }; + }); + const elemType = ty.kind; + const type = t.params.vectorize ? `vec${t.params.vectorize}<${elemType}>` : elemType; + const shaderBuilder = basicExpressionWithPredeclarationBuilder( + (value) => `get_dereferenced_value(${value})`, + `struct S { + m : ${type} + } + fn get_dereferenced_value(value: ${type}) -> ${type} { + var a = S(value); + let p = &a; + return ${kDerefCases[t.params.derefType].wgsl}.m; + }` + ); + await run(t, shaderBuilder, [ty], ty, t.params, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_arithmetic.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_arithmetic.cache.js new file mode 100644 index 0000000000..97917cb2a3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_arithmetic.cache.js @@ -0,0 +1,13 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { scalarF64Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +export const d = makeCaseCache('unary/af_arithmetic', { + negation: () => { + return FP.abstract.generateScalarToIntervalCases( + scalarF64Range({ neg_norm: 250, neg_sub: 20, pos_sub: 20, pos_norm: 250 }), + 'unfiltered', + FP.abstract.negationInterval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_arithmetic.spec.js index 25571a970b..55457e59d1 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_arithmetic.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_arithmetic.spec.js @@ -1,29 +1,17 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` -Execution Tests for AbstractFloat arithmetic unary expression operations +Execution Tests for Type.abstractFloat arithmetic unary expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeAbstractFloat } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { fullF64Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { onlyConstInputSource, run } from '../expression.js'; -import { abstractUnary } from './unary.js'; +import { d } from './af_arithmetic.cache.js'; +import { abstractFloatUnary } from './unary.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unary/af_arithmetic', { - negation: () => { - return FP.abstract.generateScalarToIntervalCases( - fullF64Range({ neg_norm: 250, neg_sub: 20, pos_sub: 20, pos_norm: 250 }), - 'unfiltered', - FP.abstract.negationInterval - ); - } -}); - g.test('negation'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -39,5 +27,13 @@ combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { const cases = await d.get('negation'); - await run(t, abstractUnary('-'), [TypeAbstractFloat], TypeAbstractFloat, t.params, cases, 1); + await run( + t, + abstractFloatUnary('-'), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases, + 1 + ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_assignment.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_assignment.cache.js new file mode 100644 index 0000000000..70d50ca609 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_assignment.cache.js @@ -0,0 +1,51 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kValue } from '../../../../util/constants.js';import { abstractFloat } from '../../../../util/conversion.js';import { FP } from '../../../../util/floating_point.js'; +import { + isSubnormalNumberF64, + limitedScalarF64Range, + scalarF64Range } from +'../../../../util/math.js'; +import { reinterpretU64AsF64 } from '../../../../util/reinterpret.js'; +import { makeCaseCache } from '../case_cache.js'; + +export const d = makeCaseCache('unary/af_assignment', { + abstract: () => { + const inputs = [ + // Values that are useful for debugging the underlying framework/shader code, since it cannot be directly unit tested. + 0, + 0.5, + 0.5, + 1, + -1, + reinterpretU64AsF64(0x7000_0000_0000_0001n), // smallest magnitude negative subnormal with non-zero mantissa + reinterpretU64AsF64(0x0000_0000_0000_0001n), // smallest magnitude positive subnormal with non-zero mantissa + reinterpretU64AsF64(0x600a_aaaa_5555_5555n), // negative subnormal with obvious pattern + reinterpretU64AsF64(0x000a_aaaa_5555_5555n), // positive subnormal with obvious pattern + reinterpretU64AsF64(0x0010_0000_0000_0001n), // smallest magnitude negative normal with non-zero mantissa + reinterpretU64AsF64(0x0010_0000_0000_0001n), // smallest magnitude positive normal with non-zero mantissa + reinterpretU64AsF64(0xf555_5555_aaaa_aaaan), // negative normal with obvious pattern + reinterpretU64AsF64(0x5555_5555_aaaa_aaaan), // positive normal with obvious pattern + reinterpretU64AsF64(0xffef_ffff_ffff_ffffn), // largest magnitude negative normal + reinterpretU64AsF64(0x7fef_ffff_ffff_ffffn), // largest magnitude positive normal + // WebGPU implementation stressing values + ...scalarF64Range()]; + + return inputs.map((f) => { + return { + input: abstractFloat(f), + expected: isSubnormalNumberF64(f) ? abstractFloat(0) : abstractFloat(f) + }; + }); + }, + f32: () => { + return limitedScalarF64Range(kValue.f32.negative.min, kValue.f32.positive.max).map((f) => { + return { input: abstractFloat(f), expected: FP.f32.correctlyRoundedInterval(f) }; + }); + }, + f16: () => { + return limitedScalarF64Range(kValue.f16.negative.min, kValue.f16.positive.max).map((f) => { + return { input: abstractFloat(f), expected: FP.f16.correctlyRoundedInterval(f) }; + }); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_assignment.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_assignment.spec.js index 777262a364..2288245f36 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_assignment.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/af_assignment.spec.js @@ -4,20 +4,17 @@ Execution Tests for assignment of AbstractFloats `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { kValue } from '../../../../util/constants.js'; -import { abstractFloat, TypeAbstractFloat, TypeF16, TypeF32 } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { filteredF64Range, fullF64Range, isSubnormalNumberF64 } from '../../../../util/math.js'; -import { reinterpretU64AsF64 } from '../../../../util/reinterpret.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { + abstractFloatShaderBuilder, basicExpressionBuilder, onlyConstInputSource, run } from - '../expression.js'; +import { d } from './af_assignment.cache.js'; + function concrete_assignment() { return basicExpressionBuilder((value) => `${value}`); } @@ -28,47 +25,6 @@ function abstract_assignment() { export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unary/af_assignment', { - abstract: () => { - const inputs = [ - // Values that are useful for debugging the underlying framework/shader code, since it cannot be directly unit tested. - 0, - 0.5, - 0.5, - 1, - -1, - reinterpretU64AsF64(0x7000_0000_0000_0001n), // smallest magnitude negative subnormal with non-zero mantissa - reinterpretU64AsF64(0x0000_0000_0000_0001n), // smallest magnitude positive subnormal with non-zero mantissa - reinterpretU64AsF64(0x600a_aaaa_5555_5555n), // negative subnormal with obvious pattern - reinterpretU64AsF64(0x000a_aaaa_5555_5555n), // positive subnormal with obvious pattern - reinterpretU64AsF64(0x0010_0000_0000_0001n), // smallest magnitude negative normal with non-zero mantissa - reinterpretU64AsF64(0x0010_0000_0000_0001n), // smallest magnitude positive normal with non-zero mantissa - reinterpretU64AsF64(0xf555_5555_aaaa_aaaan), // negative normal with obvious pattern - reinterpretU64AsF64(0x5555_5555_aaaa_aaaan), // positive normal with obvious pattern - reinterpretU64AsF64(0xffef_ffff_ffff_ffffn), // largest magnitude negative normal - reinterpretU64AsF64(0x7fef_ffff_ffff_ffffn), // largest magnitude positive normal - // WebGPU implementation stressing values - ...fullF64Range()]; - - return inputs.map((f) => { - return { - input: abstractFloat(f), - expected: isSubnormalNumberF64(f) ? abstractFloat(0) : abstractFloat(f) - }; - }); - }, - f32: () => { - return filteredF64Range(kValue.f32.negative.min, kValue.f32.positive.max).map((f) => { - return { input: abstractFloat(f), expected: FP.f32.correctlyRoundedInterval(f) }; - }); - }, - f16: () => { - return filteredF64Range(kValue.f16.negative.min, kValue.f16.positive.max).map((f) => { - return { input: abstractFloat(f), expected: FP.f16.correctlyRoundedInterval(f) }; - }); - } -}); - g.test('abstract'). specURL('https://www.w3.org/TR/WGSL/#floating-point-conversion'). desc( @@ -79,7 +35,15 @@ testing that extracting abstract floats works params((u) => u.combine('inputSource', onlyConstInputSource)). fn(async (t) => { const cases = await d.get('abstract'); - await run(t, abstract_assignment(), [TypeAbstractFloat], TypeAbstractFloat, t.params, cases, 1); + await run( + t, + abstract_assignment(), + [Type.abstractFloat], + Type.abstractFloat, + t.params, + cases, + 1 + ); }); g.test('f32'). @@ -92,7 +56,7 @@ concretizing to f32 params((u) => u.combine('inputSource', onlyConstInputSource)). fn(async (t) => { const cases = await d.get('f32'); - await run(t, concrete_assignment(), [TypeAbstractFloat], TypeF32, t.params, cases); + await run(t, concrete_assignment(), [Type.abstractFloat], Type.f32, t.params, cases); }); g.test('f16'). @@ -108,5 +72,5 @@ beforeAllSubcases((t) => { params((u) => u.combine('inputSource', onlyConstInputSource)). fn(async (t) => { const cases = await d.get('f16'); - await run(t, concrete_assignment(), [TypeAbstractFloat], TypeF16, t.params, cases); + await run(t, concrete_assignment(), [Type.abstractFloat], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_arithmetic.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_arithmetic.cache.js new file mode 100644 index 0000000000..3ed097dc50 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_arithmetic.cache.js @@ -0,0 +1,11 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { abstractInt } from '../../../../util/conversion.js';import { fullI64Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +export const d = makeCaseCache('unary/ai_arithmetic', { + negation: () => { + return fullI64Range().map((e) => { + return { input: abstractInt(e), expected: abstractInt(-e) }; + }); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_arithmetic.spec.js new file mode 100644 index 0000000000..6060edd7d5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_arithmetic.spec.js @@ -0,0 +1,30 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for the abstract integer arithmetic unary expression operations +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { Type } from '../../../../util/conversion.js'; +import { onlyConstInputSource, run } from '../expression.js'; + +import { d } from './ai_arithmetic.cache.js'; +import { abstractIntUnary } from './unary.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('negation'). +specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr'). +desc( + ` +Expression: -x +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = await d.get('negation'); + await run(t, abstractIntUnary('-'), [Type.abstractInt], Type.abstractInt, t.params, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_assignment.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_assignment.cache.js new file mode 100644 index 0000000000..dfe479bad7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_assignment.cache.js @@ -0,0 +1,21 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { abstractInt, i32, u32 } from '../../../../util/conversion.js';import { fullI32Range, fullI64Range, fullU32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +export const d = makeCaseCache('unary/ai_assignment', { + abstract: () => { + return fullI64Range().map((n) => { + return { input: abstractInt(n), expected: abstractInt(n) }; + }); + }, + i32: () => { + return fullI32Range().map((n) => { + return { input: abstractInt(BigInt(n)), expected: i32(n) }; + }); + }, + u32: () => { + return fullU32Range().map((n) => { + return { input: abstractInt(BigInt(n)), expected: u32(n) }; + }); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_assignment.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_assignment.spec.js new file mode 100644 index 0000000000..be05705c54 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_assignment.spec.js @@ -0,0 +1,65 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for assignment of AbstractInts +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { Type } from '../../../../util/conversion.js'; +import { + + abstractIntShaderBuilder, + basicExpressionBuilder, + onlyConstInputSource, + run } from +'../expression.js'; + +import { d } from './ai_assignment.cache.js'; + +function concrete_assignment() { + return basicExpressionBuilder((value) => `${value}`); +} + +function abstract_assignment() { + return abstractIntShaderBuilder((value) => `${value}`); +} + +export const g = makeTestGroup(GPUTest); + +g.test('abstract'). +specURL('https://www.w3.org/TR/WGSL/#abstract-types'). +desc( + ` +testing that extracting abstract ints works +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('abstract'); + await run(t, abstract_assignment(), [Type.abstractInt], Type.abstractInt, t.params, cases, 1); +}); + +g.test('i32'). +specURL('https://www.w3.org/TR/WGSL/#i32-builtin'). +desc( + ` +concretizing to i32 +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('i32'); + await run(t, concrete_assignment(), [Type.abstractInt], Type.i32, t.params, cases); +}); + +g.test('u32'). +specURL('https://www.w3.org/TR/WGSL/#u32-builtin'). +desc( + ` +concretizing to u32 +` +). +params((u) => u.combine('inputSource', onlyConstInputSource)). +fn(async (t) => { + const cases = await d.get('u32'); + await run(t, concrete_assignment(), [Type.abstractInt], Type.u32, t.params, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_complement.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_complement.spec.js new file mode 100644 index 0000000000..c8d4209608 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/ai_complement.spec.js @@ -0,0 +1,32 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution Tests for the Type.abstractInt bitwise complement operation +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../../gpu_test.js'; +import { abstractInt, Type } from '../../../../util/conversion.js'; +import { fullI64Range } from '../../../../util/math.js'; +import { onlyConstInputSource, run } from '../expression.js'; + +import { abstractIntUnary } from './unary.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('complement'). +specURL('https://www.w3.org/TR/WGSL/#bit-expr'). +desc( + ` +Expression: ~x +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = fullI64Range().map((e) => { + return { input: abstractInt(e), expected: abstractInt(~e) }; + }); + await run(t, abstractIntUnary('~'), [Type.abstractInt], Type.abstractInt, t.params, cases); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_conversion.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_conversion.cache.js new file mode 100644 index 0000000000..f0ca905774 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_conversion.cache.js @@ -0,0 +1,54 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { anyOf } from '../../../../util/compare.js';import { bool, f16, f32, i32, u32 } from '../../../../util/conversion.js';import { + fullI32Range, + fullU32Range, + isSubnormalNumberF16, + isSubnormalNumberF32, + scalarF16Range, + scalarF32Range } from +'../../../../util/math.js'; +import { makeCaseCache } from '../case_cache.js'; + +export const d = makeCaseCache('unary/bool_conversion', { + bool: () => { + return [ + { input: bool(true), expected: bool(true) }, + { input: bool(false), expected: bool(false) }]; + + }, + u32: () => { + return fullU32Range().map((u) => { + return { input: u32(u), expected: u === 0 ? bool(false) : bool(true) }; + }); + }, + i32: () => { + return fullI32Range().map((i) => { + return { input: i32(i), expected: i === 0 ? bool(false) : bool(true) }; + }); + }, + f32: () => { + return scalarF32Range().map((f) => { + const expected = []; + if (f !== 0) { + expected.push(bool(true)); + } + if (isSubnormalNumberF32(f)) { + expected.push(bool(false)); + } + return { input: f32(f), expected: anyOf(...expected) }; + }); + }, + f16: () => { + return scalarF16Range().map((f) => { + const expected = []; + if (f !== 0) { + expected.push(bool(true)); + } + if (isSubnormalNumberF16(f)) { + expected.push(bool(false)); + } + return { input: f16(f), expected: anyOf(...expected) }; + }); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_conversion.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_conversion.spec.js index d4bbbddce4..8da4619fe7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_conversion.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_conversion.spec.js @@ -4,78 +4,14 @@ Execution Tests for the boolean conversion operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { anyOf } from '../../../../util/compare.js'; -import { - bool, - f32, - f16, - i32, - - TypeBool, - TypeF32, - TypeF16, - TypeI32, - TypeU32, - u32 } from -'../../../../util/conversion.js'; -import { - fullF32Range, - fullF16Range, - fullI32Range, - fullU32Range, - isSubnormalNumberF32, - isSubnormalNumberF16 } from -'../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; +import { d } from './bool_conversion.cache.js'; import { unary } from './unary.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unary/bool_conversion', { - bool: () => { - return [ - { input: bool(true), expected: bool(true) }, - { input: bool(false), expected: bool(false) }]; - - }, - u32: () => { - return fullU32Range().map((u) => { - return { input: u32(u), expected: u === 0 ? bool(false) : bool(true) }; - }); - }, - i32: () => { - return fullI32Range().map((i) => { - return { input: i32(i), expected: i === 0 ? bool(false) : bool(true) }; - }); - }, - f32: () => { - return fullF32Range().map((f) => { - const expected = []; - if (f !== 0) { - expected.push(bool(true)); - } - if (isSubnormalNumberF32(f)) { - expected.push(bool(false)); - } - return { input: f32(f), expected: anyOf(...expected) }; - }); - }, - f16: () => { - return fullF16Range().map((f) => { - const expected = []; - if (f !== 0) { - expected.push(bool(true)); - } - if (isSubnormalNumberF16(f)) { - expected.push(bool(false)); - } - return { input: f16(f), expected: anyOf(...expected) }; - }); - } -}); - /** Generate expression builder based on how the test case is to be vectorized */ function vectorizeToExpression(vectorize) { return vectorize === undefined ? unary('bool') : unary(`vec${vectorize}`); @@ -95,7 +31,14 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('bool'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeBool], TypeBool, t.params, cases); + await run( + t, + vectorizeToExpression(t.params.vectorize), + [Type.bool], + Type.bool, + t.params, + cases + ); }); g.test('u32'). @@ -113,7 +56,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('u32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeU32], TypeBool, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.u32], Type.bool, t.params, cases); }); g.test('i32'). @@ -131,7 +74,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('i32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeI32], TypeBool, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.i32], Type.bool, t.params, cases); }); g.test('f32'). @@ -149,7 +92,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeF32], TypeBool, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.f32], Type.bool, t.params, cases); }); g.test('f16'). @@ -170,5 +113,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeF16], TypeBool, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.f16], Type.bool, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_logical.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_logical.spec.js index ac8da84846..e09cb35d3f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_logical.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_logical.spec.js @@ -4,7 +4,7 @@ Execution Tests for the boolean unary logical expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { bool, TypeBool } from '../../../../util/conversion.js'; +import { bool, Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; import { unary } from './unary.js'; @@ -29,5 +29,5 @@ fn(async (t) => { { input: bool(false), expected: bool(true) }]; - await run(t, unary('!'), [TypeBool], TypeBool, t.params, cases); + await run(t, unary('!'), [Type.bool], Type.bool, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_arithmetic.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_arithmetic.cache.js new file mode 100644 index 0000000000..5c68b275cb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_arithmetic.cache.js @@ -0,0 +1,13 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { scalarF16Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +export const d = makeCaseCache('unary/f16_arithmetic', { + negation: () => { + return FP.f16.generateScalarToIntervalCases( + scalarF16Range({ neg_norm: 250, neg_sub: 20, pos_sub: 20, pos_norm: 250 }), + 'unfiltered', + FP.f16.negationInterval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_arithmetic.spec.js index e82895ffbc..1dbeffd696 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_arithmetic.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_arithmetic.spec.js @@ -4,26 +4,14 @@ Execution Tests for the f16 arithmetic unary expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF16 } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { fullF16Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; +import { d } from './f16_arithmetic.cache.js'; import { unary } from './unary.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unary/f16_arithmetic', { - negation: () => { - return FP.f16.generateScalarToIntervalCases( - fullF16Range({ neg_norm: 250, neg_sub: 20, pos_sub: 20, pos_norm: 250 }), - 'unfiltered', - FP.f16.negationInterval - ); - } -}); - g.test('negation'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -40,5 +28,5 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('negation'); - await run(t, unary('-'), [TypeF16], TypeF16, t.params, cases); + await run(t, unary('-'), [Type.f16], Type.f16, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_conversion.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_conversion.cache.js new file mode 100644 index 0000000000..19af40984a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_conversion.cache.js @@ -0,0 +1,135 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { abstractInt, bool, f16, i32, u32 } from '../../../../util/conversion.js';import { FP, FPInterval } from '../../../../util/floating_point.js';import { fullI32Range, fullI64Range, fullU32Range } from '../../../../util/math.js'; +import { makeCaseCache } from '../case_cache.js'; + +const f16FiniteRangeInterval = new FPInterval( + 'f16', + FP.f16.constants().negative.min, + FP.f16.constants().positive.max +); + +// Cases: f32_matCxR_[non_]const +// Note that f32 values may be not exactly representable in f16 and/or out of range. +const f32_mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`f32_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateMatrixToMatrixCases( + FP.f32.sparseMatrixRange(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f16.correctlyRoundedMatrix + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: f16_matCxR_[non_]const +const f16_mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`f16_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + // Input matrix is of f16 types, use f16.generateMatrixToMatrixCases. + return FP.f16.generateMatrixToMatrixCases( + FP.f16.sparseMatrixRange(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f16.correctlyRoundedMatrix + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: abstract_float_matCxR +// Note that abstract float values may be not exactly representable in f16 +// and/or out of range. +const abstract_float_mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].map((rows) => ({ + [`abstract_float_mat${cols}x${rows}`]: () => { + return FP.abstract.generateMatrixToMatrixCases( + FP.abstract.sparseMatrixRange(cols, rows), + 'finite', + FP.f16.correctlyRoundedMatrix + ); + } +})) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('unary/f16_conversion', { + bool: () => { + return [ + { input: bool(true), expected: f16(1.0) }, + { input: bool(false), expected: f16(0.0) }]; + + }, + u32_non_const: () => { + return [...fullU32Range(), 65504].map((u) => { + return { input: u32(u), expected: FP.f16.correctlyRoundedInterval(u) }; + }); + }, + u32_const: () => { + return [...fullU32Range(), 65504]. + filter((v) => f16FiniteRangeInterval.contains(v)). + map((u) => { + return { input: u32(u), expected: FP.f16.correctlyRoundedInterval(u) }; + }); + }, + i32_non_const: () => { + return [...fullI32Range(), 65504, -65504].map((i) => { + return { input: i32(i), expected: FP.f16.correctlyRoundedInterval(i) }; + }); + }, + i32_const: () => { + return [...fullI32Range(), 65504, -65504]. + filter((v) => f16FiniteRangeInterval.contains(v)). + map((i) => { + return { input: i32(i), expected: FP.f16.correctlyRoundedInterval(i) }; + }); + }, + abstract_int: () => { + return [...fullI64Range(), 65504n, -65504n]. + filter((v) => f16FiniteRangeInterval.contains(Number(v))). + map((i) => { + return { input: abstractInt(i), expected: FP.f16.correctlyRoundedInterval(Number(i)) }; + }); + }, + // Note that f32 values may be not exactly representable in f16 and/or out of range. + f32_non_const: () => { + return FP.f32.generateScalarToIntervalCases( + [...FP.f32.scalarRange(), 65535.996, -65535.996], + 'unfiltered', + FP.f16.correctlyRoundedInterval + ); + }, + f32_const: () => { + return FP.f32.generateScalarToIntervalCases( + [...FP.f32.scalarRange(), 65535.996, -65535.996], + 'finite', + FP.f16.correctlyRoundedInterval + ); + }, + // Note that abstract float values may be not exactly representable in f16. + abstract_float: () => { + return FP.abstract.generateScalarToIntervalCases( + [...FP.abstract.scalarRange(), 65535.996, -65535.996], + 'finite', + FP.f16.correctlyRoundedInterval + ); + }, + // All f16 values are exactly representable in f16. + f16: () => { + return FP.f16.scalarRange().map((f) => { + return { input: f16(f), expected: FP.f16.correctlyRoundedInterval(f) }; + }); + }, + ...f32_mat_cases, + ...f16_mat_cases, + ...abstract_float_mat_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_conversion.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_conversion.spec.js index a37c816062..53e11c44ec 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_conversion.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f16_conversion.spec.js @@ -4,132 +4,14 @@ Execution Tests for the f32 conversion operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { - bool, - f16, - i32, - TypeBool, - TypeF32, - TypeF16, - TypeI32, - TypeMat, - TypeU32, - u32 } from -'../../../../util/conversion.js'; -import { FP, FPInterval } from '../../../../util/floating_point.js'; -import { - fullF32Range, - fullF16Range, - fullI32Range, - fullU32Range, - sparseMatrixF32Range, - sparseMatrixF16Range } from -'../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; -import { allInputSources, run } from '../expression.js'; +import { Type } from '../../../../util/conversion.js'; +import { allInputSources, run, onlyConstInputSource } from '../expression.js'; +import { d } from './f16_conversion.cache.js'; import { unary } from './unary.js'; export const g = makeTestGroup(GPUTest); -const f16FiniteRangeInterval = new FPInterval( - 'f32', - FP.f16.constants().negative.min, - FP.f16.constants().positive.max -); - -// Cases: f32_matCxR_[non_]const -// Note that f32 values may be not exactly representable in f16 and/or out of range. -const f32_mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`f32_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateMatrixToMatrixCases( - sparseMatrixF32Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f16.correctlyRoundedMatrix - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: f16_matCxR_[non_]const -const f16_mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`f16_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - // Input matrix is of f16 types, use f16.generateMatrixToMatrixCases. - return FP.f16.generateMatrixToMatrixCases( - sparseMatrixF16Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f16.correctlyRoundedMatrix - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('unary/f16_conversion', { - bool: () => { - return [ - { input: bool(true), expected: f16(1.0) }, - { input: bool(false), expected: f16(0.0) }]; - - }, - u32_non_const: () => { - return [...fullU32Range(), 65504].map((u) => { - return { input: u32(u), expected: FP.f16.correctlyRoundedInterval(u) }; - }); - }, - u32_const: () => { - return [...fullU32Range(), 65504]. - filter((v) => f16FiniteRangeInterval.contains(v)). - map((u) => { - return { input: u32(u), expected: FP.f16.correctlyRoundedInterval(u) }; - }); - }, - i32_non_const: () => { - return [...fullI32Range(), 65504, -65504].map((i) => { - return { input: i32(i), expected: FP.f16.correctlyRoundedInterval(i) }; - }); - }, - i32_const: () => { - return [...fullI32Range(), 65504, -65504]. - filter((v) => f16FiniteRangeInterval.contains(v)). - map((i) => { - return { input: i32(i), expected: FP.f16.correctlyRoundedInterval(i) }; - }); - }, - // Note that f32 values may be not exactly representable in f16 and/or out of range. - f32_non_const: () => { - return FP.f32.generateScalarToIntervalCases( - [...fullF32Range(), 65535.996, -65535.996], - 'unfiltered', - FP.f16.correctlyRoundedInterval - ); - }, - f32_const: () => { - return FP.f32.generateScalarToIntervalCases( - [...fullF32Range(), 65535.996, -65535.996], - 'finite', - FP.f16.correctlyRoundedInterval - ); - }, - // All f16 values are exactly representable in f16. - f16: () => { - return fullF16Range().map((f) => { - return { input: f16(f), expected: FP.f16.correctlyRoundedInterval(f) }; - }); - }, - ...f32_mat_cases, - ...f16_mat_cases -}); - /** Generate a ShaderBuilder based on how the test case is to be vectorized */ function vectorizeToExpression(vectorize) { return vectorize === undefined ? unary('f16') : unary(`vec${vectorize}`); @@ -157,7 +39,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('bool'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeBool], TypeF16, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.bool], Type.f16, t.params, cases); }); g.test('u32'). @@ -177,7 +59,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeU32], TypeF16, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.u32], Type.f16, t.params, cases); }); g.test('i32'). @@ -197,7 +79,36 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'i32_const' : 'i32_non_const'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeI32], TypeF16, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.i32], Type.f16, t.params, cases); +}); + +g.test('abstract_int'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc( + ` +f16(e), where e is an AbstractInt + +Converted to f16, +/-Inf if out of range +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +beforeAllSubcases((t) => { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); +}). +fn(async (t) => { + const cases = await d.get('abstract_int'); + await run( + t, + vectorizeToExpression(t.params.vectorize), + [Type.abstractInt], + Type.f16, + t.params, + cases + ); }); g.test('f32'). @@ -217,7 +128,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeF32], TypeF16, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.f32], Type.f16, t.params, cases); }); g.test('f32_mat'). @@ -243,8 +154,8 @@ fn(async (t) => { await run( t, matrixExperession(cols, rows), - [TypeMat(cols, rows, TypeF32)], - TypeMat(cols, rows, TypeF16), + [Type.mat(cols, rows, Type.f32)], + Type.mat(cols, rows, Type.f16), t.params, cases ); @@ -267,7 +178,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeF16], TypeF16, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.f16], Type.f16, t.params, cases); }); g.test('f16_mat'). @@ -293,8 +204,63 @@ fn(async (t) => { await run( t, matrixExperession(cols, rows), - [TypeMat(cols, rows, TypeF16)], - TypeMat(cols, rows, TypeF16), + [Type.mat(cols, rows, Type.f16)], + Type.mat(cols, rows, Type.f16), + t.params, + cases + ); +}); + +g.test('abstract_float'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc( + ` +f16(e), where e is an AbstractFloat + +Correctly rounded to f16 +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +beforeAllSubcases((t) => { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); +}). +fn(async (t) => { + const cases = await d.get('abstract_float'); + await run( + t, + vectorizeToExpression(t.params.vectorize), + [Type.abstractFloat], + Type.f16, + t.params, + cases + ); +}); + +g.test('abstract_float_mat'). +specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions'). +desc(`AbstractFloat matrix to f16 matrix tests`). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('cols', [2, 3, 4]). +combine('rows', [2, 3, 4]) +). +beforeAllSubcases((t) => { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); +}). +fn(async (t) => { + const cols = t.params.cols; + const rows = t.params.rows; + const cases = await d.get(`abstract_float_mat${cols}x${rows}`); + await run( + t, + matrixExperession(cols, rows), + [Type.mat(cols, rows, Type.abstractFloat)], + Type.mat(cols, rows, Type.f16), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.cache.js new file mode 100644 index 0000000000..cdd991a4f9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.cache.js @@ -0,0 +1,13 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { FP } from '../../../../util/floating_point.js';import { scalarF32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +export const d = makeCaseCache('unary/f32_arithmetic', { + negation: () => { + return FP.f32.generateScalarToIntervalCases( + scalarF32Range({ neg_norm: 250, neg_sub: 20, pos_sub: 20, pos_norm: 250 }), + 'unfiltered', + FP.f32.negationInterval + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.spec.js index a91bab73d2..785f8f9aa1 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.spec.js @@ -4,26 +4,14 @@ Execution Tests for the f32 arithmetic unary expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { TypeF32 } from '../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { fullF32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; +import { d } from './f32_arithmetic.cache.js'; import { unary } from './unary.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unary/f32_arithmetic', { - negation: () => { - return FP.f32.generateScalarToIntervalCases( - fullF32Range({ neg_norm: 250, neg_sub: 20, pos_sub: 20, pos_norm: 250 }), - 'unfiltered', - FP.f32.negationInterval - ); - } -}); - g.test('negation'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -37,5 +25,5 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('negation'); - await run(t, unary('-'), [TypeF32], TypeF32, t.params, cases); + await run(t, unary('-'), [Type.f32], Type.f32, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_conversion.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_conversion.cache.js new file mode 100644 index 0000000000..eb8fbe2c79 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_conversion.cache.js @@ -0,0 +1,79 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { bool, f16, f32, i32, u32 } from '../../../../util/conversion.js';import { FP } from '../../../../util/floating_point.js';import { + fullI32Range, + fullU32Range, + scalarF16Range, + scalarF32Range, + sparseMatrixF16Range, + sparseMatrixF32Range } from +'../../../../util/math.js'; +import { makeCaseCache } from '../case_cache.js'; + +// Cases: f32_matCxR_[non_]const +const f32_mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`f32_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + return FP.f32.generateMatrixToMatrixCases( + sparseMatrixF32Range(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f32.correctlyRoundedMatrix + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +// Cases: f16_matCxR_[non_]const +// Note that all f16 values are exactly representable in f32. +const f16_mat_cases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +[true, false].map((nonConst) => ({ + [`f16_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + // Input matrix is of f16 types, use f16.generateMatrixToMatrixCases. + return FP.f16.generateMatrixToMatrixCases( + sparseMatrixF16Range(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP.f32.correctlyRoundedMatrix + ); + } +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +export const d = makeCaseCache('unary/f32_conversion', { + bool: () => { + return [ + { input: bool(true), expected: f32(1.0) }, + { input: bool(false), expected: f32(0.0) }]; + + }, + u32: () => { + return fullU32Range().map((u) => { + return { input: u32(u), expected: FP.f32.correctlyRoundedInterval(u) }; + }); + }, + i32: () => { + return fullI32Range().map((i) => { + return { input: i32(i), expected: FP.f32.correctlyRoundedInterval(i) }; + }); + }, + f32: () => { + return scalarF32Range().map((f) => { + return { input: f32(f), expected: FP.f32.correctlyRoundedInterval(f) }; + }); + }, + // All f16 values are exactly representable in f32. + f16: () => { + return scalarF16Range().map((f) => { + return { input: f16(f), expected: FP.f32.correctlyRoundedInterval(f) }; + }); + }, + ...f32_mat_cases, + ...f16_mat_cases +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_conversion.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_conversion.spec.js index d9aa209365..08e42b8598 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_conversion.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_conversion.spec.js @@ -4,103 +4,14 @@ Execution Tests for the f32 conversion operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { - bool, - f32, - f16, - i32, - TypeBool, - TypeF32, - TypeF16, - TypeI32, - TypeMat, - TypeU32, - u32 } from -'../../../../util/conversion.js'; -import { FP } from '../../../../util/floating_point.js'; -import { - fullF32Range, - fullF16Range, - fullI32Range, - fullU32Range, - sparseMatrixF32Range, - sparseMatrixF16Range } from -'../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; +import { d } from './f32_conversion.cache.js'; import { unary } from './unary.js'; export const g = makeTestGroup(GPUTest); -// Cases: f32_matCxR_[non_]const -const f32_mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`f32_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateMatrixToMatrixCases( - sparseMatrixF32Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f32.correctlyRoundedMatrix - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: f16_matCxR_[non_]const -// Note that all f16 values are exactly representable in f32. -const f16_mat_cases = [2, 3, 4]. -flatMap((cols) => -[2, 3, 4].flatMap((rows) => -[true, false].map((nonConst) => ({ - [`f16_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - // Input matrix is of f16 types, use f16.generateMatrixToMatrixCases. - return FP.f16.generateMatrixToMatrixCases( - sparseMatrixF16Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f32.correctlyRoundedMatrix - ); - } -})) -) -). -reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('unary/f32_conversion', { - bool: () => { - return [ - { input: bool(true), expected: f32(1.0) }, - { input: bool(false), expected: f32(0.0) }]; - - }, - u32: () => { - return fullU32Range().map((u) => { - return { input: u32(u), expected: FP.f32.correctlyRoundedInterval(u) }; - }); - }, - i32: () => { - return fullI32Range().map((i) => { - return { input: i32(i), expected: FP.f32.correctlyRoundedInterval(i) }; - }); - }, - f32: () => { - return fullF32Range().map((f) => { - return { input: f32(f), expected: FP.f32.correctlyRoundedInterval(f) }; - }); - }, - // All f16 values are exactly representable in f32. - f16: () => { - return fullF16Range().map((f) => { - return { input: f16(f), expected: FP.f32.correctlyRoundedInterval(f) }; - }); - }, - ...f32_mat_cases, - ...f16_mat_cases -}); - /** Generate a ShaderBuilder based on how the test case is to be vectorized */ function vectorizeToExpression(vectorize) { return vectorize === undefined ? unary('f32') : unary(`vec${vectorize}`); @@ -125,7 +36,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('bool'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeBool], TypeF32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.bool], Type.f32, t.params, cases); }); g.test('u32'). @@ -142,7 +53,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('u32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeU32], TypeF32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.u32], Type.f32, t.params, cases); }); g.test('i32'). @@ -159,7 +70,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('i32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeI32], TypeF32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.i32], Type.f32, t.params, cases); }); g.test('f32'). @@ -176,7 +87,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeF32], TypeF32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.f32], Type.f32, t.params, cases); }); g.test('f32_mat'). @@ -199,8 +110,8 @@ fn(async (t) => { await run( t, matrixExperession(cols, rows), - [TypeMat(cols, rows, TypeF32)], - TypeMat(cols, rows, TypeF32), + [Type.mat(cols, rows, Type.f32)], + Type.mat(cols, rows, Type.f32), t.params, cases ); @@ -223,7 +134,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeF16], TypeF32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.f16], Type.f32, t.params, cases); }); g.test('f16_mat'). @@ -249,8 +160,8 @@ fn(async (t) => { await run( t, matrixExperession(cols, rows), - [TypeMat(cols, rows, TypeF16)], - TypeMat(cols, rows, TypeF32), + [Type.mat(cols, rows, Type.f16)], + Type.mat(cols, rows, Type.f32), t.params, cases ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.cache.js new file mode 100644 index 0000000000..84708efa74 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.cache.js @@ -0,0 +1,11 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { i32 } from '../../../../util/conversion.js';import { fullI32Range } from '../../../../util/math.js';import { makeCaseCache } from '../case_cache.js'; + +export const d = makeCaseCache('unary/i32_arithmetic', { + negation: () => { + return fullI32Range().map((e) => { + return { input: i32(e), expected: i32(-e) }; + }); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.spec.js index 9a46879c6c..c30b3d5aa3 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.spec.js @@ -4,23 +4,14 @@ Execution Tests for the i32 arithmetic unary expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { i32, TypeI32 } from '../../../../util/conversion.js'; -import { fullI32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; +import { Type } from '../../../../util/conversion.js'; import { allInputSources, run } from '../expression.js'; +import { d } from './i32_arithmetic.cache.js'; import { unary } from './unary.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unary/i32_arithmetic', { - negation: () => { - return fullI32Range().map((e) => { - return { input: i32(e), expected: i32(-e) }; - }); - } -}); - g.test('negation'). specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation'). desc( @@ -33,5 +24,5 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('negation'); - await run(t, unary('-'), [TypeI32], TypeI32, t.params, cases); + await run(t, unary('-'), [Type.i32], Type.i32, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_complement.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_complement.spec.js index e5870b2256..0648c9ee3c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_complement.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_complement.spec.js @@ -4,23 +4,14 @@ Execution Tests for the i32 bitwise complement operation `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { i32, TypeI32 } from '../../../../util/conversion.js'; +import { i32, Type } from '../../../../util/conversion.js'; import { fullI32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; import { allInputSources, run } from '../expression.js'; import { unary } from './unary.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unary/i32_complement', { - complement: () => { - return fullI32Range().map((e) => { - return { input: i32(e), expected: i32(~e) }; - }); - } -}); - g.test('i32_complement'). specURL('https://www.w3.org/TR/WGSL/#bit-expr'). desc( @@ -32,6 +23,8 @@ params((u) => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { - const cases = await d.get('complement'); - await run(t, unary('~'), [TypeI32], TypeI32, t.params, cases); + const cases = fullI32Range().map((e) => { + return { input: i32(e), expected: i32(~e) }; + }); + await run(t, unary('~'), [Type.i32], Type.i32, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_conversion.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_conversion.cache.js new file mode 100644 index 0000000000..ab5cac3b28 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_conversion.cache.js @@ -0,0 +1,116 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kValue } from '../../../../util/constants.js';import { abstractFloat, +abstractInt, +bool, +f16, +f32, +i32, +u32 } from +'../../../../util/conversion.js'; +import { + fullI32Range, + fullU32Range, + quantizeToF16, + quantizeToF32, + scalarF16Range, + scalarF32Range, + scalarF64Range } from +'../../../../util/math.js'; +import { reinterpretU32AsI32 } from '../../../../util/reinterpret.js'; +import { makeCaseCache } from '../case_cache.js'; + +export const d = makeCaseCache('unary/i32_conversion', { + bool: () => { + return [ + { input: bool(true), expected: i32(1) }, + { input: bool(false), expected: i32(0) }]; + + }, + abstractInt: () => { + return fullI32Range().map((i) => { + return { input: abstractInt(BigInt(i)), expected: i32(i) }; + }); + }, + u32: () => { + return fullU32Range().map((u) => { + return { input: u32(u), expected: i32(reinterpretU32AsI32(u)) }; + }); + }, + i32: () => { + return fullI32Range().map((i) => { + return { input: i32(i), expected: i32(i) }; + }); + }, + abstractFloat: () => { + return scalarF64Range().map((f) => { + // Handles zeros and subnormals + if (Math.abs(f) < 1.0) { + return { input: abstractFloat(f), expected: i32(0) }; + } + + if (f <= kValue.i32.negative.min) { + return { input: abstractFloat(f), expected: i32(kValue.i32.negative.min) }; + } + + if (f >= kValue.i32.positive.max) { + return { input: abstractFloat(f), expected: i32(kValue.i32.positive.max) }; + } + + // All i32s are representable as f64, and both AbstractFloat and number + // are f64 internally, so there is no need for special casing like f32 and + // f16 below. + return { input: abstractFloat(f), expected: i32(Math.trunc(f)) }; + }); + }, + f32: () => { + return scalarF32Range().map((f) => { + // Handles zeros and subnormals + if (Math.abs(f) < 1.0) { + return { input: f32(f), expected: i32(0) }; + } + + if (f <= kValue.i32.negative.min) { + return { input: f32(f), expected: i32(kValue.i32.negative.min) }; + } + + if (f >= kValue.i32.positive.max) { + return { input: f32(f), expected: i32(kValue.i32.positive.max) }; + } + + // All f32 no larger than 2^24 has a precise interger part and a fractional part, just need + // to trunc towards 0 for the result integer. + if (Math.abs(f) <= 2 ** 24) { + return { input: f32(f), expected: i32(Math.trunc(f)) }; + } + + // All f32s between 2 ** 24 and kValue.i32.negative.min/.positive.max are + // integers, so in theory one could use them directly, expect that number + // is actually f64 internally, so they need to be quantized to f32 first. + // Cannot just use trunc here, since that might produce a i32 value that + // is precise in f64, but not in f32. + return { input: f32(f), expected: i32(quantizeToF32(f)) }; + }); + }, + f16: () => { + // Note that finite f16 values are always in range of i32. + return scalarF16Range().map((f) => { + // Handles zeros and subnormals + if (Math.abs(f) < 1.0) { + return { input: f16(f), expected: i32(0) }; + } + + // All f16 no larger than <= 2^12 has a precise interger part and a fractional part, just need + // to trunc towards 0 for the result integer. + if (Math.abs(f) <= 2 ** 12) { + return { input: f16(f), expected: i32(Math.trunc(f)) }; + } + + // All f16s larger than 2 ** 12 are integers, so in theory one could use them directly, expect + // that number is actually f64 internally, so they need to be quantized to f16 first. + // Cannot just use trunc here, since that might produce a i32 value that is precise in f64, + // but not in f16. + return { input: f16(f), expected: i32(quantizeToF16(f)) }; + }); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_conversion.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_conversion.spec.js index a4b8247f56..57768e7abc 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_conversion.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_conversion.spec.js @@ -4,104 +4,14 @@ Execution Tests for the i32 conversion operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { kValue } from '../../../../util/constants.js'; -import { - bool, - f32, - f16, - i32, - TypeBool, - TypeF32, - TypeF16, - TypeI32, - TypeU32, - u32 } from -'../../../../util/conversion.js'; -import { - fullF32Range, - fullF16Range, - fullI32Range, - fullU32Range, - quantizeToF32, - quantizeToF16 } from -'../../../../util/math.js'; -import { reinterpretU32AsI32 } from '../../../../util/reinterpret.js'; -import { makeCaseCache } from '../case_cache.js'; -import { allInputSources, run } from '../expression.js'; +import { Type } from '../../../../util/conversion.js'; +import { allInputSources, run, onlyConstInputSource } from '../expression.js'; +import { d } from './i32_conversion.cache.js'; import { unary } from './unary.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unary/i32_conversion', { - bool: () => { - return [ - { input: bool(true), expected: i32(1) }, - { input: bool(false), expected: i32(0) }]; - - }, - u32: () => { - return fullU32Range().map((u) => { - return { input: u32(u), expected: i32(reinterpretU32AsI32(u)) }; - }); - }, - i32: () => { - return fullI32Range().map((i) => { - return { input: i32(i), expected: i32(i) }; - }); - }, - f32: () => { - return fullF32Range().map((f) => { - // Handles zeros and subnormals - if (Math.abs(f) < 1.0) { - return { input: f32(f), expected: i32(0) }; - } - - if (f <= kValue.i32.negative.min) { - return { input: f32(f), expected: i32(kValue.i32.negative.min) }; - } - - if (f >= kValue.i32.positive.max) { - return { input: f32(f), expected: i32(kValue.i32.positive.max) }; - } - - // All f32 no larger than 2^24 has a precise interger part and a fractional part, just need - // to trunc towards 0 for the result integer. - if (Math.abs(f) <= 2 ** 24) { - return { input: f32(f), expected: i32(Math.trunc(f)) }; - } - - // All f32s between 2 ** 24 and kValue.i32.negative.min/.positive.max are - // integers, so in theory one could use them directly, expect that number - // is actually f64 internally, so they need to be quantized to f32 first. - // Cannot just use trunc here, since that might produce a i32 value that - // is precise in f64, but not in f32. - return { input: f32(f), expected: i32(quantizeToF32(f)) }; - }); - }, - f16: () => { - // Note that finite f16 values are always in range of i32. - return fullF16Range().map((f) => { - // Handles zeros and subnormals - if (Math.abs(f) < 1.0) { - return { input: f16(f), expected: i32(0) }; - } - - // All f16 no larger than <= 2^12 has a precise interger part and a fractional part, just need - // to trunc towards 0 for the result integer. - if (Math.abs(f) <= 2 ** 12) { - return { input: f16(f), expected: i32(Math.trunc(f)) }; - } - - // All f16s larger than 2 ** 12 are integers, so in theory one could use them directly, expect - // that number is actually f64 internally, so they need to be quantized to f16 first. - // Cannot just use trunc here, since that might produce a i32 value that is precise in f64, - // but not in f16. - return { input: f16(f), expected: i32(quantizeToF16(f)) }; - }); - } -}); - /** Generate a ShaderBuilder based on how the test case is to be vectorized */ function vectorizeToExpression(vectorize) { return vectorize === undefined ? unary('i32') : unary(`vec${vectorize}`); @@ -121,7 +31,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('bool'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeBool], TypeI32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.bool], Type.i32, t.params, cases); }); g.test('u32'). @@ -138,7 +48,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('u32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeU32], TypeI32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.u32], Type.i32, t.params, cases); }); g.test('i32'). @@ -155,7 +65,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('i32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeI32], TypeI32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.i32], Type.i32, t.params, cases); }); g.test('f32'). @@ -172,7 +82,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeF32], TypeI32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.f32], Type.i32, t.params, cases); }); g.test('f16'). @@ -192,5 +102,57 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeF16], TypeI32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.f16], Type.i32, t.params, cases); +}); + +g.test('abstract_int'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc( + ` +i32(e), where e is an AbstractInt + +Identity operation if e is in bounds for i32, otherwise shader creation error +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = await d.get('abstractInt'); + await run( + t, + vectorizeToExpression(t.params.vectorize), + [Type.abstractInt], + Type.i32, + t.params, + cases + ); +}); + +g.test('abstract_float'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc( + ` +i32(e), where e is an AbstractFloat + +e is converted to i32, rounding towards zero +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = await d.get('abstractFloat'); + await run( + t, + vectorizeToExpression(t.params.vectorize), + [Type.abstractFloat], + Type.i32, + t.params, + cases + ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_complement.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_complement.spec.js index 36a664652c..a15742738c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_complement.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_complement.spec.js @@ -4,23 +4,14 @@ Execution Tests for the u32 bitwise complement operation `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { u32, TypeU32 } from '../../../../util/conversion.js'; +import { Type, u32 } from '../../../../util/conversion.js'; import { fullU32Range } from '../../../../util/math.js'; -import { makeCaseCache } from '../case_cache.js'; import { allInputSources, run } from '../expression.js'; import { unary } from './unary.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unary/u32_complement', { - complement: () => { - return fullU32Range().map((e) => { - return { input: u32(e), expected: u32(~e) }; - }); - } -}); - g.test('u32_complement'). specURL('https://www.w3.org/TR/WGSL/#bit-expr'). desc( @@ -32,6 +23,8 @@ params((u) => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) ). fn(async (t) => { - const cases = await d.get('complement'); - await run(t, unary('~'), [TypeU32], TypeU32, t.params, cases); + const cases = fullU32Range().map((e) => { + return { input: u32(e), expected: u32(~e) }; + }); + await run(t, unary('~'), [Type.u32], Type.u32, t.params, cases); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_conversion.cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_conversion.cache.js new file mode 100644 index 0000000000..d43133a5f6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_conversion.cache.js @@ -0,0 +1,107 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { kValue } from '../../../../util/constants.js';import { abstractFloat, +abstractInt, +bool, +f16, +f32, +i32, +u32 } from +'../../../../util/conversion.js'; +import { + fullI32Range, + fullU32Range, + quantizeToF16, + quantizeToF32, + scalarF16Range, + scalarF32Range, + scalarF64Range } from +'../../../../util/math.js'; +import { reinterpretI32AsU32 } from '../../../../util/reinterpret.js'; +import { makeCaseCache } from '../case_cache.js'; + +export const d = makeCaseCache('unary/u32_conversion', { + bool: () => { + return [ + { input: bool(true), expected: u32(1) }, + { input: bool(false), expected: u32(0) }]; + + }, + abstractInt: () => { + return fullU32Range().map((u) => { + return { input: abstractInt(BigInt(u)), expected: u32(u) }; + }); + }, + u32: () => { + return fullU32Range().map((u) => { + return { input: u32(u), expected: u32(u) }; + }); + }, + i32: () => { + return fullI32Range().map((i) => { + return { input: i32(i), expected: u32(reinterpretI32AsU32(i)) }; + }); + }, + abstractFloat: () => { + return [...scalarF64Range(), -1].map((f) => { + // Handles zeros, subnormals, and negatives + if (f < 1.0) { + return { input: abstractFloat(f), expected: u32(0) }; + } + + if (f >= kValue.u32.max) { + return { input: abstractFloat(f), expected: u32(kValue.u32.max) }; + } + + // All u32s are representable as f64s and number is a f64 internally, so + // no need for special handling like is done for f32 and f16 below. + return { input: abstractFloat(f), expected: u32(Math.floor(f)) }; + }); + }, + f32: () => { + return scalarF32Range().map((f) => { + // Handles zeros, subnormals, and negatives + if (f < 1.0) { + return { input: f32(f), expected: u32(0) }; + } + + if (f >= kValue.u32.max) { + return { input: f32(f), expected: u32(kValue.u32.max) }; + } + + // All f32 no larger than 2^24 has a precise integer part and a fractional + // part, just need to trunc towards 0 for the result integer. + if (f <= 2 ** 24) { + return { input: f32(f), expected: u32(Math.floor(f)) }; + } + + // All f32s between 2 ** 24 and kValue.u32.max are integers, so in theory + // one could use them directly, expect that number is actually f64 + // internally, so they need to be quantized to f32 first. + // Cannot just use floor here, since that might produce a u32 value that + // is precise in f64, but not in f32. + return { input: f32(f), expected: u32(quantizeToF32(f)) }; + }); + }, + f16: () => { + // Note that all positive finite f16 values are in range of u32. + return scalarF16Range().map((f) => { + // Handles zeros, subnormals, and negatives + if (f < 1.0) { + return { input: f16(f), expected: u32(0) }; + } + + // All f16 no larger than <= 2^12 has a precise integer part and a + // fractional part, just need to trunc towards 0 for the result integer. + if (f <= 2 ** 12) { + return { input: f16(f), expected: u32(Math.trunc(f)) }; + } + + // All f16s larger than 2 ** 12 are integers, so in theory one could use + // them directly, expect that number is actually f64 internally, so they + // need to be quantized to f16 first.Cannot just use trunc here, since + // that might produce a u32 value that is precise in f64, but not in f16. + return { input: f16(f), expected: u32(quantizeToF16(f)) }; + }); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_conversion.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_conversion.spec.js index adec5bcc65..528e01f4cc 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_conversion.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/u32_conversion.spec.js @@ -4,100 +4,14 @@ Execution Tests for the u32 conversion operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -import { kValue } from '../../../../util/constants.js'; -import { - bool, - f32, - f16, - i32, - TypeBool, - TypeF32, - TypeF16, - TypeI32, - TypeU32, - u32 } from -'../../../../util/conversion.js'; -import { - fullF32Range, - fullF16Range, - fullI32Range, - fullU32Range, - quantizeToF32, - quantizeToF16 } from -'../../../../util/math.js'; -import { reinterpretI32AsU32 } from '../../../../util/reinterpret.js'; -import { makeCaseCache } from '../case_cache.js'; -import { allInputSources, run } from '../expression.js'; +import { Type } from '../../../../util/conversion.js'; +import { allInputSources, run, onlyConstInputSource } from '../expression.js'; +import { d } from './u32_conversion.cache.js'; import { unary } from './unary.js'; export const g = makeTestGroup(GPUTest); -export const d = makeCaseCache('unary/u32_conversion', { - bool: () => { - return [ - { input: bool(true), expected: u32(1) }, - { input: bool(false), expected: u32(0) }]; - - }, - u32: () => { - return fullU32Range().map((u) => { - return { input: u32(u), expected: u32(u) }; - }); - }, - i32: () => { - return fullI32Range().map((i) => { - return { input: i32(i), expected: u32(reinterpretI32AsU32(i)) }; - }); - }, - f32: () => { - return fullF32Range().map((f) => { - // Handles zeros, subnormals, and negatives - if (f < 1.0) { - return { input: f32(f), expected: u32(0) }; - } - - if (f >= kValue.u32.max) { - return { input: f32(f), expected: u32(kValue.u32.max) }; - } - - // All f32 no larger than 2^24 has a precise interger part and a fractional part, just need - // to trunc towards 0 for the result integer. - if (f <= 2 ** 24) { - return { input: f32(f), expected: u32(Math.floor(f)) }; - } - - // All f32s between 2 ** 24 and kValue.u32.max are integers, so in theory - // one could use them directly, expect that number is actually f64 - // internally, so they need to be quantized to f32 first. - // Cannot just use floor here, since that might produce a u32 value that - // is precise in f64, but not in f32. - return { input: f32(f), expected: u32(quantizeToF32(f)) }; - }); - }, - f16: () => { - // Note that all positive finite f16 values are in range of u32. - return fullF16Range().map((f) => { - // Handles zeros, subnormals, and negatives - if (f < 1.0) { - return { input: f16(f), expected: u32(0) }; - } - - // All f16 no larger than <= 2^12 has a precise interger part and a fractional part, just need - // to trunc towards 0 for the result integer. - if (f <= 2 ** 12) { - return { input: f16(f), expected: u32(Math.trunc(f)) }; - } - - // All f16s larger than 2 ** 12 are integers, so in theory one could use them directly, expect - // that number is actually f64 internally, so they need to be quantized to f16 first. - // Cannot just use trunc here, since that might produce a u32 value that is precise in f64, - // but not in f16. - return { input: f16(f), expected: u32(quantizeToF16(f)) }; - }); - } -}); - /** Generate a ShaderBuilder based on how the test case is to be vectorized */ function vectorizeToExpression(vectorize) { return vectorize === undefined ? unary('u32') : unary(`vec${vectorize}`); @@ -117,7 +31,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('bool'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeBool], TypeU32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.bool], Type.u32, t.params, cases); }); g.test('u32'). @@ -134,7 +48,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('u32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeU32], TypeU32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.u32], Type.u32, t.params, cases); }); g.test('i32'). @@ -151,7 +65,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('i32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeI32], TypeU32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.i32], Type.u32, t.params, cases); }); g.test('f32'). @@ -168,7 +82,7 @@ u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, ). fn(async (t) => { const cases = await d.get('f32'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeF32], TypeU32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.f32], Type.u32, t.params, cases); }); g.test('f16'). @@ -188,7 +102,7 @@ beforeAllSubcases((t) => { }). fn(async (t) => { const cases = await d.get('f16'); - await run(t, vectorizeToExpression(t.params.vectorize), [TypeF16], TypeU32, t.params, cases); + await run(t, vectorizeToExpression(t.params.vectorize), [Type.f16], Type.u32, t.params, cases); }); g.test('abstract_int'). @@ -201,6 +115,44 @@ Identity operation if the e can be represented in u32, otherwise it produces a s ` ). params((u) => -u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]) +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) +). +fn(async (t) => { + const cases = await d.get('abstractInt'); + await run( + t, + vectorizeToExpression(t.params.vectorize), + [Type.abstractInt], + Type.u32, + t.params, + cases + ); +}); + +g.test('abstract_float'). +specURL('https://www.w3.org/TR/WGSL/#value-constructor-builtin-function'). +desc( + ` +u32(e), where e is an AbstractFloat + +e is converted to u32, rounding towards zero +` +). +params((u) => +u. +combine('inputSource', onlyConstInputSource). +combine('vectorize', [undefined, 2, 3, 4]) ). -unimplemented(); \ No newline at end of file +fn(async (t) => { + const cases = await d.get('abstractFloat'); + await run( + t, + vectorizeToExpression(t.params.vectorize), + [Type.abstractFloat], + Type.u32, + t.params, + cases + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/unary.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/unary.js index 914d9fed4c..1b46f37795 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/unary.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/unary.js @@ -1,6 +1,7 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { abstractFloatShaderBuilder, basicExpressionBuilder } from +**/import { abstractFloatShaderBuilder, abstractIntShaderBuilder, + basicExpressionBuilder } from '../expression.js'; @@ -10,6 +11,11 @@ export function unary(op) { } /* @returns a ShaderBuilder that evaluates a prefix unary operation that returns AbstractFloats */ -export function abstractUnary(op) { +export function abstractFloatUnary(op) { return abstractFloatShaderBuilder((value) => `${op}(${value})`); +} + +/* @returns a ShaderBuilder that evaluates a prefix unary operation that returns AbstractInts */ +export function abstractIntUnary(op) { + return abstractIntShaderBuilder((value) => `${op}(${value})`); } \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/call.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/call.spec.js index 43897ca432..00d2451eca 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/call.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/call.spec.js @@ -80,4 +80,117 @@ fn c() { ${f.expect_order(3, 7)} }` })); +}); + +g.test('arg_eval'). +desc('Test that arguments are evaluated left to right'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest(t, (f) => ({ + entrypoint: ` + ${f.expect_order(0)} + a(b(), c(), d()); + ${f.expect_order(5)} +`, + extra: ` +fn a(p1 : u32, p2 : u32, p3 : u32) { + ${f.expect_order(4)} +} +fn b() -> u32 { + ${f.expect_order(1)} + return 0; +} +fn c() -> u32 { + ${f.expect_order(2)} + return 0; +} +fn d() -> u32 { + ${f.expect_order(3)} + return 0; +}` + })); +}); + +g.test('arg_eval_logical_and'). +desc('Test that arguments are evaluated left to right'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest(t, (f) => ({ + entrypoint: ` + ${f.expect_order(0)} + a(b(${f.value(1)}) && c()); + a(b(${f.value(0)}) && c()); + ${f.expect_order(6)} +`, + extra: ` +fn a(p : bool) { + ${f.expect_order(3, 5)} +} +fn b(x : i32) -> bool { + ${f.expect_order(1, 4)} + return x == 1; +} +fn c() -> bool { + ${f.expect_order(2)} + return true; +}` + })); +}); + +g.test('arg_eval_logical_or'). +desc('Test that arguments are evaluated left to right'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest(t, (f) => ({ + entrypoint: ` + ${f.expect_order(0)} + a(b(${f.value(1)}) || c()); + a(b(${f.value(0)}) || c()); + ${f.expect_order(6)} +`, + extra: ` +fn a(p : bool) { + ${f.expect_order(3, 5)} +} +fn b(x : i32) -> bool { + ${f.expect_order(1, 4)} + return x == 0; +} +fn c() -> bool { + ${f.expect_order(2)} + return true; +}` + })); +}); + +g.test('arg_eval_pointers'). +desc('Test that arguments are evaluated left to right'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest(t, (f) => ({ + entrypoint: ` + var x : i32 = ${f.value(0)}; + ${f.expect_order(0)} + _ = c(&x); + a(b(&x), c(&x)); + ${f.expect_order(5)} +`, + extra: ` +fn a(p1 : i32, p2 : i32) { + ${f.expect_order(4)} +} +fn b(p : ptr) -> i32 { + (*p)++; + ${f.expect_order(2)} + return 0; +} +fn c(p : ptr) -> i32 { + if (*p == 1) { + ${f.expect_order(3)} + } else { + ${f.expect_order(1)} + } + return 0; +}` + })); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/for.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/for.spec.js index 182f1e999a..4f7714cf42 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/for.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/for.spec.js @@ -268,4 +268,54 @@ fn((t) => { ${f.expect_order(9)} ` ); +}); + +g.test('for_logical_and_condition'). +desc('Test flow control for a for-loop with a logical and condition'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest(t, (f) => ({ + entrypoint: ` + ${f.expect_order(0)} + for (var i = ${f.value(0)}; a(i) && b(i); i++) { + ${f.expect_order(3, 6)} + } + ${f.expect_order(8)} + `, + extra: ` +fn a(i : i32) -> bool { + ${f.expect_order(1, 4, 7)} + return i < ${f.value(2)}; +} +fn b(i : i32) -> bool { + ${f.expect_order(2, 5)} + return i < ${f.value(5)}; +} + ` + })); +}); + +g.test('for_logical_or_condition'). +desc('Test flow control for a for-loop with a logical or condition'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest(t, (f) => ({ + entrypoint: ` + ${f.expect_order(0)} + for (var i = ${f.value(0)}; a(i) || b(i); i++) { + ${f.expect_order(2, 4, 7, 10)} + } + ${f.expect_order(13)} + `, + extra: ` +fn a(i : i32) -> bool { + ${f.expect_order(1, 3, 5, 8, 11)} + return i < ${f.value(2)}; +} +fn b(i : i32) -> bool { + ${f.expect_order(6, 9, 12)} + return i < ${f.value(4)}; +} + ` + })); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/loop.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/loop.spec.js index adb5e0916d..829c5b4997 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/loop.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/loop.spec.js @@ -122,4 +122,64 @@ fn((t) => { ${f.expect_order(23)} ` ); +}); + +g.test('loop_break_if_logical_and_condition'). +desc('Test flow control for a loop with a logical and break if'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest(t, (f) => ({ + entrypoint: ` + ${f.expect_order(0)} + var i = ${f.value(0)}; + loop { + ${f.expect_order(1, 4, 7)} + continuing { + i++; + break if !(a(i) && b(i)); + } + } + ${f.expect_order(9)} + `, + extra: ` +fn a(i : i32) -> bool { + ${f.expect_order(2, 5, 8)} + return i < ${f.value(3)}; +} +fn b(i : i32) -> bool { + ${f.expect_order(3, 6)} + return i < ${f.value(5)}; +} + ` + })); +}); + +g.test('loop_break_if_logical_or_condition'). +desc('Test flow control for a loop with a logical or break if'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest(t, (f) => ({ + entrypoint: ` + ${f.expect_order(0)} + var i = ${f.value(0)}; + loop { + ${f.expect_order(1, 3, 6, 9)} + continuing { + i++; + break if !(a(i) || b(i)); + } + } + ${f.expect_order(12)} + `, + extra: ` +fn a(i : i32) -> bool { + ${f.expect_order(2, 4, 7, 10)} + return i < ${f.value(2)}; +} +fn b(i : i32) -> bool { + ${f.expect_order(5, 8, 11)} + return i < ${f.value(4)}; +} + ` + })); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/switch.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/switch.spec.js index 09664a067e..597ef20c78 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/switch.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/switch.spec.js @@ -151,6 +151,39 @@ default: { } } ${f.expect_order(2)} +` + ); +}); + +g.test('switch_inside_loop_with_continue'). +desc('Test that flow control executes correct for a switch calling continue inside a loop'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest( + t, + (f) => ` +${f.expect_order(0)} +var i = ${f.value(0)}; +loop { + switch (i) { + case 1: { + ${f.expect_order(4)} + continue; + } + default: { + ${f.expect_order(1)} + break; + } + } + ${f.expect_order(2)} + + continuing { + ${f.expect_order(3, 5)} + i++; + break if i >= 2; + } +} +${f.expect_order(6)} ` ); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/while.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/while.spec.js index f4bbc942ef..b77e09bf48 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/while.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/flow_control/while.spec.js @@ -137,4 +137,58 @@ fn((t) => { ${f.expect_order(19)} ` ); +}); + +g.test('while_logical_and_condition'). +desc('Test flow control for a while-loop with a logical and condition'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest(t, (f) => ({ + entrypoint: ` + ${f.expect_order(0)} + var i = ${f.value(0)}; + while (a(i) && b(i)) { + ${f.expect_order(3, 6)} + i++; + } + ${f.expect_order(8)} + `, + extra: ` +fn a(i : i32) -> bool { + ${f.expect_order(1, 4, 7)} + return i < ${f.value(2)}; +} +fn b(i : i32) -> bool { + ${f.expect_order(2, 5)} + return i < ${f.value(5)}; +} + ` + })); +}); + +g.test('while_logical_or_condition'). +desc('Test flow control for a while-loop with a logical or condition'). +params((u) => u.combine('preventValueOptimizations', [true, false])). +fn((t) => { + runFlowControlTest(t, (f) => ({ + entrypoint: ` + ${f.expect_order(0)} + var i = ${f.value(0)}; + while (a(i) || b(i)) { + ${f.expect_order(2, 4, 7, 10)} + i++; + } + ${f.expect_order(13)} + `, + extra: ` +fn a(i : i32) -> bool { + ${f.expect_order(1, 3, 5, 8, 11)} + return i < ${f.value(2)}; +} +fn b(i : i32) -> bool { + ${f.expect_order(6, 9, 12)} + return i < ${f.value(4)}; +} + ` + })); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_layout.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_layout.spec.js new file mode 100644 index 0000000000..53a797b7c8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_layout.spec.js @@ -0,0 +1,1059 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Test memory layout requirements`;import { makeTestGroup } from '../../../common/framework/test_group.js'; +import { keysOf } from '../../../common/util/data_tables.js'; +import { iterRange } from '../../../common/util/util.js'; +import { GPUTest } from '../../gpu_test.js'; + +export const g = makeTestGroup(GPUTest); + + + + + + + + + + + + +const kLayoutCases = { + vec2u_align8: { + type: `S_vec2u_align`, + decl: `struct S_vec2u_align { + x : u32, + y : vec2u, + }`, + read_assign: `out = in.y[1]`, + write_assign: `out.y[1] = in`, + offset: 12 + }, + vec3u_align16: { + type: `S_vec3u_align`, + decl: `struct S_vec3u_align { + x : u32, + y : vec3u, + }`, + read_assign: `out = in.y[2]`, + write_assign: `out.y[2] = in`, + offset: 24 + }, + vec4u_align16: { + type: `S_vec4u_align`, + decl: `struct S_vec4u_align { + x : u32, + y : vec4u, + }`, + read_assign: `out = in.y[0]`, + write_assign: `out.y[0] = in`, + offset: 16 + }, + struct_align32: { + type: `S_align32`, + decl: `struct S_align32 { + x : u32, + @align(32) y : u32, + }`, + read_assign: `out = in.y;`, + write_assign: `out.y = in`, + offset: 32 + }, + vec2h_align4: { + type: `S_vec2h_align`, + decl: `struct S_vec2h_align { + x : f16, + y : vec2h, + }`, + read_assign: `out = u32(in.y[0])`, + write_assign: `out.y[0] = f16(in)`, + offset: 4, + f16: true + }, + vec3h_align8: { + type: `S_vec3h_align`, + decl: `struct S_vec3h_align { + x : f16, + y : vec3h, + }`, + read_assign: `out = u32(in.y[2])`, + write_assign: `out.y[2] = f16(in)`, + offset: 12, + f16: true + }, + vec4h_align8: { + type: `S_vec4h_align`, + decl: `struct S_vec4h_align { + x : f16, + y : vec4h, + }`, + read_assign: `out = u32(in.y[2])`, + write_assign: `out.y[2] = f16(in)`, + offset: 12, + f16: true + }, + vec2f_align8: { + type: `S_vec2f_align`, + decl: `struct S_vec2f_align { + x : u32, + y : vec2f, + }`, + read_assign: `out = u32(in.y[1])`, + write_assign: `out.y[1] = f32(in)`, + offset: 12, + f32: true + }, + vec3f_align16: { + type: `S_vec3f_align`, + decl: `struct S_vec3f_align { + x : u32, + y : vec3f, + }`, + read_assign: `out = u32(in.y[2])`, + write_assign: `out.y[2] = f32(in)`, + offset: 24, + f32: true + }, + vec4f_align16: { + type: `S_vec4f_align`, + decl: `struct S_vec4f_align { + x : u32, + y : vec4f, + }`, + read_assign: `out = u32(in.y[0])`, + write_assign: `out.y[0] = f32(in)`, + offset: 16, + f32: true + }, + vec3i_size12: { + type: `S_vec3i_size`, + decl: `struct S_vec3i_size { + x : vec3i, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 12 + }, + vec3h_size6: { + type: `S_vec3h_size`, + decl: `struct S_vec3h_size { + x : vec3h, + y : f16, + z : f16, + }`, + read_assign: `out = u32(in.z)`, + write_assign: `out.z = f16(in)`, + offset: 8, + f16: true + }, + size80: { + type: `S_size80`, + decl: `struct S_size80 { + @size(80) x : u32, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 80 + }, + atomic_align4: { + type: `S_atomic_align`, + decl: `struct S_atomic_align { + x : u32, + y : atomic, + }`, + read_assign: `out = atomicLoad(&in.y)`, + write_assign: `atomicStore(&out.y, in)`, + offset: 4 + }, + atomic_size4: { + type: `S_atomic_size`, + decl: `struct S_atomic_size { + x : atomic, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 4 + }, + mat2x2f_align8: { + type: `S_mat2x2f_align`, + decl: `struct S_mat2x2f_align { + x : u32, + y : mat2x2f, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f32(in)`, + offset: 8, + f32: true + }, + mat3x2f_align8: { + type: `S_mat3x2f_align`, + decl: `struct S_mat3x2f_align { + x : u32, + y : mat3x2f, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f32(in)`, + offset: 8, + f32: true + }, + mat4x2f_align8: { + type: `S_mat4x2f_align`, + decl: `struct S_mat4x2f_align { + x : u32, + y : mat4x2f, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f32(in)`, + offset: 8, + f32: true + }, + mat2x3f_align16: { + type: `S_mat2x3f_align`, + decl: `struct S_mat2x3f_align { + x : u32, + y : mat2x3f, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f32(in)`, + offset: 16, + f32: true + }, + mat3x3f_align16: { + type: `S_mat3x3f_align`, + decl: `struct S_mat3x3f_align { + x : u32, + y : mat3x3f, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f32(in)`, + offset: 16, + f32: true + }, + mat4x3f_align16: { + type: `S_mat4x3f_align`, + decl: `struct S_mat4x3f_align { + x : u32, + y : mat4x3f, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f32(in)`, + offset: 16, + f32: true + }, + mat2x4f_align16: { + type: `S_mat2x4f_align`, + decl: `struct S_mat2x4f_align { + x : u32, + y : mat2x4f, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f32(in)`, + offset: 16, + f32: true + }, + mat3x4f_align16: { + type: `S_mat3x4f_align`, + decl: `struct S_mat3x4f_align { + x : u32, + y : mat3x4f, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f32(in)`, + offset: 16, + f32: true + }, + mat4x4f_align16: { + type: `S_mat4x4f_align`, + decl: `struct S_mat4x4f_align { + x : u32, + y : mat4x4f, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f32(in)`, + offset: 16, + f32: true + }, + mat2x2h_align4: { + type: `S_mat2x2h_align`, + decl: `struct S_mat2x2h_align { + x : u32, + y : mat2x2h, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f16(in)`, + offset: 4, + f16: true + }, + mat3x2h_align4: { + type: `S_mat3x2h_align`, + decl: `struct S_mat3x2h_align { + x : u32, + y : mat3x2h, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f16(in)`, + offset: 4, + f16: true + }, + mat4x2h_align4: { + type: `S_mat4x2h_align`, + decl: `struct S_mat4x2h_align { + x : u32, + y : mat4x2h, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f16(in)`, + offset: 4, + f16: true + }, + mat2x3h_align8: { + type: `S_mat2x3h_align`, + decl: `struct S_mat2x3h_align { + x : u32, + y : mat2x3h, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f16(in)`, + offset: 8, + f16: true + }, + mat3x3h_align8: { + type: `S_mat3x3h_align`, + decl: `struct S_mat3x3h_align { + x : u32, + y : mat2x3h, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f16(in)`, + offset: 8, + f16: true + }, + mat4x3h_align8: { + type: `S_mat4x3h_align`, + decl: `struct S_mat4x3h_align { + x : u32, + y : mat4x3h, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f16(in)`, + offset: 8, + f16: true + }, + mat2x4h_align8: { + type: `S_mat2x4h_align`, + decl: `struct S_mat2x4h_align { + x : u32, + y : mat2x4h, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f16(in)`, + offset: 8, + f16: true + }, + mat3x4h_align8: { + type: `S_mat3x4h_align`, + decl: `struct S_mat3x4h_align { + x : u32, + y : mat3x4h, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f16(in)`, + offset: 8, + f16: true + }, + mat4x4h_align8: { + type: `S_mat4x4h_align`, + decl: `struct S_mat4x4h_align { + x : u32, + y : mat4x4h, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f16(in)`, + offset: 8, + f16: true + }, + mat2x2f_size: { + type: `S_mat2x2f_size`, + decl: `struct S_mat2x2f_size { + x : mat2x2f, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 16 + }, + mat3x2f_size: { + type: `S_mat3x2f_size`, + decl: `struct S_mat3x2f_size { + x : mat3x2f, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 24 + }, + mat4x2f_size: { + type: `S_mat4x2f_size`, + decl: `struct S_mat4x2f_size { + x : mat4x2f, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 32 + }, + mat2x3f_size: { + type: `S_mat2x3f_size`, + decl: `struct S_mat2x3f_size { + x : mat2x3f, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 32 + }, + mat3x3f_size: { + type: `S_mat3x3f_size`, + decl: `struct S_mat3x3f_size { + x : mat3x3f, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 48 + }, + mat4x3f_size: { + type: `S_mat4x3f_size`, + decl: `struct S_mat4x3f_size { + x : mat4x3f, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 64 + }, + mat2x4f_size: { + type: `S_mat2x4f_size`, + decl: `struct S_mat2x4f_size { + x : mat2x4f, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 32 + }, + mat3x4f_size: { + type: `S_mat3x4f_size`, + decl: `struct S_mat3x4f_size { + x : mat3x4f, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 48 + }, + mat4x4f_size: { + type: `S_mat4x4f_size`, + decl: `struct S_mat4x4f_size { + x : mat4x4f, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 64 + }, + mat2x2h_size: { + type: `S_mat2x2h_size`, + decl: `struct S_mat2x2h_size { + x : mat2x2h, + y : f16, + }`, + read_assign: `out = u32(in.y)`, + write_assign: `out.y = f16(in)`, + offset: 8, + f16: true + }, + mat3x2h_size: { + type: `S_mat3x2h_size`, + decl: `struct S_mat3x2h_size { + x : mat3x2h, + y : f16, + }`, + read_assign: `out = u32(in.y)`, + write_assign: `out.y = f16(in)`, + offset: 12, + f16: true + }, + mat4x2h_size: { + type: `S_mat4x2h_size`, + decl: `struct S_mat4x2h_size { + x : mat4x2h, + y : f16, + }`, + read_assign: `out = u32(in.y)`, + write_assign: `out.y = f16(in)`, + offset: 16, + f16: true + }, + mat2x3h_size: { + type: `S_mat2x3h_size`, + decl: `struct S_mat2x3h_size { + x : mat2x3h, + y : f16, + }`, + read_assign: `out = u32(in.y)`, + write_assign: `out.y = f16(in)`, + offset: 16, + f16: true + }, + mat3x3h_size: { + type: `S_mat3x3h_size`, + decl: `struct S_mat3x3h_size { + x : mat3x3h, + y : f16, + }`, + read_assign: `out = u32(in.y)`, + write_assign: `out.y = f16(in)`, + offset: 24, + f16: true + }, + mat4x3h_size: { + type: `S_mat4x3h_size`, + decl: `struct S_mat4x3h_size { + x : mat4x3h, + y : f16, + }`, + read_assign: `out = u32(in.y)`, + write_assign: `out.y = f16(in)`, + offset: 32, + f16: true + }, + mat2x4h_size: { + type: `S_mat2x4h_size`, + decl: `struct S_mat2x4h_size { + x : mat2x4h, + y : f16, + }`, + read_assign: `out = u32(in.y)`, + write_assign: `out.y = f16(in)`, + offset: 16, + f16: true + }, + mat3x4h_size: { + type: `S_mat3x4h_size`, + decl: `struct S_mat3x4h_size { + x : mat3x4h, + y : f16, + }`, + read_assign: `out = u32(in.y)`, + write_assign: `out.y = f16(in)`, + offset: 24, + f16: true + }, + mat4x4h_size: { + type: `S_mat4x4h_size`, + decl: `struct S_mat4x4h_size { + x : mat4x4h, + y : f16, + }`, + read_assign: `out = u32(in.y)`, + write_assign: `out.y = f16(in)`, + offset: 32, + f16: true + }, + struct_align_vec2i: { + type: `S_struct_align_vec2i`, + decl: `struct Inner { + x : u32, + y : vec2i, + } + struct S_struct_align_vec2i { + x : u32, + y : Inner, + }`, + read_assign: `out = in.y.x`, + write_assign: `out.y.x = in`, + offset: 8, + skip_uniform: true + }, + struct_align_vec3i: { + type: `S_struct_align_vec3i`, + decl: `struct Inner { + x : u32, + y : vec3i, + } + struct S_struct_align_vec3i { + x : u32, + y : Inner, + }`, + read_assign: `out = in.y.x`, + write_assign: `out.y.x = in`, + offset: 16 + }, + struct_align_vec4i: { + type: `S_struct_align_vec4i`, + decl: `struct Inner { + x : u32, + y : vec4i, + } + struct S_struct_align_vec4i { + x : u32, + y : Inner, + }`, + read_assign: `out = in.y.x`, + write_assign: `out.y.x = in`, + offset: 16 + }, + struct_align_vec2h: { + type: `S_struct_align_vec2h`, + decl: `struct Inner { + x : f16, + y : vec2h, + } + struct S_struct_align_vec2h { + x : f16, + y : Inner, + }`, + read_assign: `out = u32(in.y.x)`, + write_assign: `out.y.x = f16(in)`, + offset: 4, + f16: true, + skip_uniform: true + }, + struct_align_vec3h: { + type: `S_struct_align_vec3h`, + decl: `struct Inner { + x : f16, + y : vec3h, + } + struct S_struct_align_vec3h { + x : f16, + y : Inner, + }`, + read_assign: `out = u32(in.y.x)`, + write_assign: `out.y.x = f16(in)`, + offset: 8, + f16: true, + skip_uniform: true + }, + struct_align_vec4h: { + type: `S_struct_align_vec4h`, + decl: `struct Inner { + x : f16, + y : vec4h, + } + struct S_struct_align_vec4h { + x : f16, + y : Inner, + }`, + read_assign: `out = u32(in.y.x)`, + write_assign: `out.y.x = f16(in)`, + offset: 8, + f16: true, + skip_uniform: true + }, + struct_size_roundup: { + type: `S_struct_size_roundup`, + decl: `struct Inner { + x : vec3u, + } + struct S_struct_size_roundup { + x : Inner, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 16 + }, + struct_inner_size: { + type: `S_struct_inner_size`, + decl: `struct Inner { + @size(112) x : u32, + } + struct S_struct_inner_size { + x : Inner, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 112 + }, + struct_inner_align: { + type: `S_struct_inner_align`, + decl: `struct Inner { + @align(64) x : u32, + } + struct S_struct_inner_align { + x : u32, + y : Inner, + }`, + read_assign: `out = in.y.x`, + write_assign: `out.y.x = in`, + offset: 64 + }, + struct_inner_size_and_align: { + type: `S_struct_inner_size_and_align`, + decl: `struct Inner { + @align(32) @size(33) x : u32, + } + struct S_struct_inner_size_and_align { + x : Inner, + y : Inner, + }`, + read_assign: `out = in.y.x`, + write_assign: `out.y.x = in`, + offset: 64 + }, + struct_override_size: { + type: `S_struct_override_size`, + decl: `struct Inner { + @size(32) x : u32, + } + struct S_struct_override_size { + @size(64) x : Inner, + y : u32, + }`, + read_assign: `out = in.y`, + write_assign: `out.y = in`, + offset: 64 + }, + struct_double_align: { + type: `S_struct_double_align`, + decl: `struct Inner { + x : u32, + @align(32) y : u32, + } + struct S_struct_double_align { + x : u32, + @align(64) y : Inner, + }`, + read_assign: `out = in.y.y`, + write_assign: `out.y.y = in`, + offset: 96 + }, + array_vec3u_align: { + type: `S_array_vec3u_align`, + decl: `struct S_array_vec3u_align { + x : u32, + y : array, + }`, + read_assign: `out = in.y[0][0]`, + write_assign: `out.y[0][0] = in`, + offset: 16 + }, + array_vec3h_align: { + type: `S_array_vec3h_align`, + decl: `struct S_array_vec3h_align { + x : f16, + y : array, + }`, + read_assign: `out = u32(in.y[0][0])`, + write_assign: `out.y[0][0] = f16(in)`, + offset: 8, + f16: true, + skip_uniform: true + }, + array_vec3u_stride: { + type: `S_array_vec3u_stride`, + decl: `struct S_array_vec3u_stride { + x : array, + }`, + read_assign: `out = in.x[1][0]`, + write_assign: `out.x[1][0] = in`, + offset: 16 + }, + array_vec3h_stride: { + type: `S_array_vec3h_stride`, + decl: `struct S_array_vec3h_stride { + x : array, + }`, + read_assign: `out = u32(in.x[1][0])`, + write_assign: `out.x[1][0] = f16(in)`, + offset: 8, + f16: true, + skip_uniform: true + }, + array_stride_size: { + type: `array`, + decl: `struct S_stride { + @size(16) x : u32, + }`, + read_assign: `out = in[2].x`, + write_assign: `out[2].x = in`, + offset: 32 + } +}; + +g.test('read_layout'). +desc('Test reading memory layouts'). +params((u) => +u. +combine('case', keysOf(kLayoutCases)). +combine('aspace', ['storage', 'uniform', 'workgroup', 'function', 'private']). +beginSubcases() +). +beforeAllSubcases((t) => { + const testcase = kLayoutCases[t.params.case]; + if (testcase.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } + // Don't test atomics in workgroup due to initialization boilerplate. + t.skipIf( + testcase.type.includes('atomic') && t.params.aspace !== 'storage', + `Skipping atomic test for non-storage address space` + ); + + t.skipIf( + testcase.skip_uniform === true && t.params.aspace === 'uniform', + `Uniform requires 16 byte alignment` + ); +}). +fn((t) => { + const testcase = kLayoutCases[t.params.case]; + let code = ` +${testcase.f16 ? 'enable f16;' : ''} +${testcase.decl} + +@group(0) @binding(1) +var out : u32; +`; + + if (t.params.aspace === 'uniform') { + code += `@group(0) @binding(0) + var<${t.params.aspace}> in : ${testcase.type};`; + } else if (t.params.aspace === 'storage') { + // Use read_write for input data to support atomics. + code += `@group(0) @binding(0) + var<${t.params.aspace}, read_write> in : ${testcase.type};`; + } else { + code += `@group(0) @binding(0) + var pre_in : ${testcase.type};`; + if (t.params.aspace === 'workgroup') { + code += ` + var in : ${testcase.type};`; + } else if (t.params.aspace === 'private') { + code += ` + var in : ${testcase.type};`; + } + } + + code += ` +@compute @workgroup_size(1,1,1) +fn main() { +`; + + if ( + t.params.aspace === 'workgroup' || + t.params.aspace === 'function' || + t.params.aspace === 'private') + { + if (t.params.aspace === 'function') { + code += `var in : ${testcase.type};\n`; + } + code += `in = pre_in;`; + if (t.params.aspace === 'workgroup') { + code += `workgroupBarrier();\n`; + } + } + + code += `\n${testcase.read_assign};\n}`; + + let usage = GPUBufferUsage.COPY_SRC; + if (t.params.aspace === 'uniform') { + usage |= GPUBufferUsage.UNIFORM; + } else { + usage |= GPUBufferUsage.STORAGE; + } + + // Magic number is 42 in various representations. + const inMagicNumber = testcase.f16 ? 0x5140 : testcase.f32 ? 0x42280000 : 42; + const in_buffer = t.makeBufferWithContents( + new Uint32Array([ + ...iterRange(128, (x) => { + if (x * 4 === testcase.offset) { + return inMagicNumber; + } else { + return 0; + } + })] + ), + usage + ); + t.trackForCleanup(in_buffer); + + const out_buffer = t.makeBufferWithContents( + new Uint32Array([...iterRange(1, (x) => 0)]), + GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + ); + t.trackForCleanup(out_buffer); + + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ + code + }), + entryPoint: 'main' + } + }); + + const bg = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: { + buffer: in_buffer + } + }, + { + binding: 1, + resource: { + buffer: out_buffer + } + }] + + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bg); + pass.dispatchWorkgroups(1, 1, 1); + pass.end(); + t.queue.submit([encoder.finish()]); + + t.expectGPUBufferValuesEqual(out_buffer, new Uint32Array([42])); +}); + +g.test('write_layout'). +desc('Test writing memory layouts'). +params((u) => +u. +combine('case', keysOf(kLayoutCases)). +combine('aspace', ['storage', 'workgroup', 'function', 'private']). +beginSubcases() +). +beforeAllSubcases((t) => { + const testcase = kLayoutCases[t.params.case]; + if (testcase.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } + // Don't test atomics in workgroup due to initialization boilerplate. + t.skipIf( + testcase.type.includes('atomic') && t.params.aspace !== 'storage', + `Skipping atomic test for non-storage address space` + ); +}). +fn((t) => { + const testcase = kLayoutCases[t.params.case]; + let code = ` +${testcase.f16 ? 'enable f16;' : ''} +${testcase.decl} + +@group(0) @binding(0) +var in : u32; +`; + + if (t.params.aspace === 'storage') { + code += `@group(0) @binding(1) + var out : ${testcase.type};\n`; + } else { + code += `@group(0) @binding(1) + var post_out : ${testcase.type};\n`; + + if (t.params.aspace === 'workgroup') { + code += `var out : ${testcase.type};\n`; + } else if (t.params.aspace === 'private') { + code += `var out : ${testcase.type};\n`; + } + } + + code += ` +@compute @workgroup_size(1,1,1) +fn main() { +`; + + if (t.params.aspace === 'function') { + code += `var out : ${testcase.type};\n`; + } + + code += `${testcase.write_assign};\n`; + if ( + t.params.aspace === 'workgroup' || + t.params.aspace === 'function' || + t.params.aspace === 'private') + { + if (t.params.aspace === 'workgroup') { + code += `workgroupBarrier();\n`; + } + code += `post_out = out;`; + } + + code += `\n}`; + + const in_buffer = t.makeBufferWithContents( + new Uint32Array([42]), + GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE + ); + t.trackForCleanup(in_buffer); + + const out_buffer = t.makeBufferWithContents( + new Uint32Array([...iterRange(128, (x) => 0)]), + GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + ); + t.trackForCleanup(out_buffer); + + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ + code + }), + entryPoint: 'main' + } + }); + + const bg = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: { + buffer: in_buffer + } + }, + { + binding: 1, + resource: { + buffer: out_buffer + } + }] + + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bg); + pass.dispatchWorkgroups(1, 1, 1); + pass.end(); + t.queue.submit([encoder.finish()]); + + // Magic number is 42 in various representations. + const outMagicNumber = testcase.f16 ? 0x5140 : testcase.f32 ? 0x42280000 : 42; + const expect = new Uint32Array([ + ...iterRange(128, (x) => { + if (x * 4 === testcase.offset) { + return outMagicNumber; + } else { + return 0; + } + })] + ); + + t.expectGPUBufferValuesEqual(out_buffer, expect); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/barrier.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/barrier.spec.js index f5e41440bb..9ccd04c61d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/barrier.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/barrier.spec.js @@ -43,22 +43,33 @@ const memoryModelTestParams = { numBehaviors: 2 }; -// The two kinds of non-atomic accesses tested. +// The three kinds of non-atomic accesses tested. // rw: read -> barrier -> write // wr: write -> barrier -> read // ww: write -> barrier -> write // Test the non-atomic memory types. -const kMemTypes = [MemoryType.NonAtomicStorageClass, MemoryType.NonAtomicWorkgroupClass]; +const kMemTypes = [ +MemoryType.NonAtomicStorageClass, +MemoryType.NonAtomicWorkgroupClass, +MemoryType.NonAtomicTextureClass]; + const storageMemoryBarrierStoreLoadTestCode = ` test_locations.value[x_0] = 1; - workgroupBarrier(); + storageBarrier(); let r0 = u32(test_locations.value[x_1]); atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0); `; +const textureMemoryBarrierStoreLoadTestCode = ` + textureStore(texture_locations, indexToCoord(x_0), vec4u(1)); + textureBarrier(); + let r0 = textureLoad(texture_locations, indexToCoord(x_1)).x; + atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0); +`; + const workgroupMemoryBarrierStoreLoadTestCode = ` wg_test_locations[x_0] = 1; workgroupBarrier(); @@ -66,13 +77,27 @@ const workgroupMemoryBarrierStoreLoadTestCode = ` atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0); `; +const workgroupUniformLoadMemoryBarrierStoreLoadTestCode = ` + wg_test_locations[x_0] = 1; + _ = workgroupUniformLoad(&placeholder_wg_var); + let r0 = u32(wg_test_locations[x_1]); + atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0); +`; + const storageMemoryBarrierLoadStoreTestCode = ` let r0 = u32(test_locations.value[x_0]); - workgroupBarrier(); + storageBarrier(); test_locations.value[x_1] = 1; atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0); `; +const textureMemoryBarrierLoadStoreTestCode = ` + let r0 = textureLoad(texture_locations, indexToCoord(x_0)).x; + textureBarrier(); + textureStore(texture_locations, indexToCoord(x_1), vec4u(1)); + atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0); +`; + const workgroupMemoryBarrierLoadStoreTestCode = ` let r0 = u32(wg_test_locations[x_0]); workgroupBarrier(); @@ -80,12 +105,27 @@ const workgroupMemoryBarrierLoadStoreTestCode = ` atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0); `; +const workgroupUniformLoadMemoryBarrierLoadStoreTestCode = ` + let r0 = u32(wg_test_locations[x_0]); + _ = workgroupUniformLoad(&placeholder_wg_var); + wg_test_locations[x_1] = 1; + atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0); +`; + const storageMemoryBarrierStoreStoreTestCode = ` test_locations.value[x_0] = 1; storageBarrier(); test_locations.value[x_1] = 2; `; +const textureMemoryBarrierStoreStoreTestCode = ` + textureStore(texture_locations, indexToCoord(x_0), vec4u(1)); + textureBarrier(); + textureStore(texture_locations, indexToCoord(x_1), vec4u(2)); + textureBarrier(); + test_locations.value[x_1] = textureLoad(texture_locations, indexToCoord(x_1)).x; +`; + const workgroupMemoryBarrierStoreStoreTestCode = ` wg_test_locations[x_0] = 1; workgroupBarrier(); @@ -94,20 +134,56 @@ const workgroupMemoryBarrierStoreStoreTestCode = ` test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1] = wg_test_locations[x_1]; `; -function getTestCode(p) { +const workgroupUniformLoadMemoryBarrierStoreStoreTestCode = ` + wg_test_locations[x_0] = 1; + _ = workgroupUniformLoad(&placeholder_wg_var); + wg_test_locations[x_1] = 2; + _ = workgroupUniformLoad(&placeholder_wg_var); + test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1] = wg_test_locations[x_1]; +`; + +function getTestCode(p) + + + +{ switch (p.accessPair) { - case 'rw': - return p.memType === MemoryType.NonAtomicStorageClass ? - storageMemoryBarrierLoadStoreTestCode : - workgroupMemoryBarrierLoadStoreTestCode; - case 'wr': - return p.memType === MemoryType.NonAtomicStorageClass ? - storageMemoryBarrierStoreLoadTestCode : - workgroupMemoryBarrierStoreLoadTestCode; - case 'ww': - return p.memType === MemoryType.NonAtomicStorageClass ? - storageMemoryBarrierStoreStoreTestCode : - workgroupMemoryBarrierStoreStoreTestCode; + case 'rw':{ + switch (p.memType) { + case MemoryType.NonAtomicStorageClass: + return storageMemoryBarrierLoadStoreTestCode; + case MemoryType.NonAtomicTextureClass: + return textureMemoryBarrierLoadStoreTestCode; + default: + return p.normalBarrier ? + workgroupMemoryBarrierLoadStoreTestCode : + workgroupUniformLoadMemoryBarrierLoadStoreTestCode; + } + } + case 'wr':{ + switch (p.memType) { + case MemoryType.NonAtomicStorageClass: + return storageMemoryBarrierStoreLoadTestCode; + case MemoryType.NonAtomicTextureClass: + return textureMemoryBarrierStoreLoadTestCode; + default: + return p.normalBarrier ? + workgroupMemoryBarrierStoreLoadTestCode : + workgroupUniformLoadMemoryBarrierStoreLoadTestCode; + } + } + case 'ww':{ + switch (p.memType) { + case MemoryType.NonAtomicStorageClass: + return storageMemoryBarrierStoreStoreTestCode; + case MemoryType.NonAtomicTextureClass: + return textureMemoryBarrierStoreStoreTestCode; + default: + return p.normalBarrier ? + workgroupMemoryBarrierStoreStoreTestCode : + workgroupUniformLoadMemoryBarrierStoreStoreTestCode; + } + } } } @@ -122,14 +198,29 @@ params((u) => u. combine('accessValueType', kAccessValueTypes). combine('memType', kMemTypes). -combine('accessPair', ['wr']) +combine('accessPair', ['wr']). +combine('normalBarrier', [true, false]) ). beforeAllSubcases((t) => { if (t.params.accessValueType === 'f16') { t.selectDeviceOrSkipTestCase('shader-f16'); } + t.skipIf( + !t.params.normalBarrier && t.params.memType !== MemoryType.NonAtomicWorkgroupClass, + 'workgroupUniformLoad does not have storage memory semantics' + ); + t.skipIf( + t.params.memType === MemoryType.NonAtomicTextureClass && t.params.accessValueType === 'f16', + 'textures do not support f16 access' + ); }). fn(async (t) => { + t.skipIf( + t.params.memType === MemoryType.NonAtomicTextureClass && + !t.hasLanguageFeature('readonly_and_readwrite_storage_textures'), + 'requires RW storage textures feature' + ); + const resultCode = ` if (r0 == 1u) { atomicAdd(&test_results.seq, 1u); @@ -137,11 +228,14 @@ fn(async (t) => { atomicAdd(&test_results.weak, 1u); } `; - const testShader = buildTestShader( + let testShader = buildTestShader( getTestCode(t.params), t.params.memType, TestType.IntraWorkgroup ); + if (!t.params.normalBarrier) { + testShader += '\nvar placeholder_wg_var : u32;\n'; + } const resultShader = buildResultShader( resultCode, TestType.IntraWorkgroup, @@ -152,7 +246,8 @@ fn(async (t) => { memoryModelTestParams, testShader, resultShader, - t.params.accessValueType + t.params.accessValueType, + t.params.memType === MemoryType.NonAtomicTextureClass ); await memModelTester.run(15, 1); }); @@ -168,14 +263,29 @@ params((u) => u. combine('accessValueType', kAccessValueTypes). combine('memType', kMemTypes). -combine('accessPair', ['rw']) +combine('accessPair', ['rw']). +combine('normalBarrier', [true, false]) ). beforeAllSubcases((t) => { if (t.params.accessValueType === 'f16') { t.selectDeviceOrSkipTestCase('shader-f16'); } + t.skipIf( + !t.params.normalBarrier && t.params.memType !== MemoryType.NonAtomicWorkgroupClass, + 'workgroupUniformLoad does not have storage memory semantics' + ); + t.skipIf( + t.params.memType === MemoryType.NonAtomicTextureClass && t.params.accessValueType === 'f16', + 'textures do not support f16 access' + ); }). fn(async (t) => { + t.skipIf( + t.params.memType === MemoryType.NonAtomicTextureClass && + !t.hasLanguageFeature('readonly_and_readwrite_storage_textures'), + 'requires RW storage textures feature' + ); + const resultCode = ` if (r0 == 0u) { atomicAdd(&test_results.seq, 1u); @@ -183,11 +293,14 @@ fn(async (t) => { atomicAdd(&test_results.weak, 1u); } `; - const testShader = buildTestShader( + let testShader = buildTestShader( getTestCode(t.params), t.params.memType, TestType.IntraWorkgroup ); + if (!t.params.normalBarrier) { + testShader += '\nvar placeholder_wg_var : u32;\n'; + } const resultShader = buildResultShader( resultCode, TestType.IntraWorkgroup, @@ -198,7 +311,8 @@ fn(async (t) => { memoryModelTestParams, testShader, resultShader, - t.params.accessValueType + t.params.accessValueType, + t.params.memType === MemoryType.NonAtomicTextureClass ); await memModelTester.run(12, 1); }); @@ -214,14 +328,29 @@ params((u) => u. combine('accessValueType', kAccessValueTypes). combine('memType', kMemTypes). -combine('accessPair', ['ww']) +combine('accessPair', ['ww']). +combine('normalBarrier', [true, false]) ). beforeAllSubcases((t) => { if (t.params.accessValueType === 'f16') { t.selectDeviceOrSkipTestCase('shader-f16'); } + t.skipIf( + !t.params.normalBarrier && t.params.memType !== MemoryType.NonAtomicWorkgroupClass, + 'workgroupUniformLoad does not have storage memory semantics' + ); + t.skipIf( + t.params.memType === MemoryType.NonAtomicTextureClass && t.params.accessValueType === 'f16', + 'textures do not support f16 access' + ); }). fn(async (t) => { + t.skipIf( + t.params.memType === MemoryType.NonAtomicTextureClass && + !t.hasLanguageFeature('readonly_and_readwrite_storage_textures'), + 'requires RW storage textures feature' + ); + const resultCode = ` if (mem_x_0 == 2u) { atomicAdd(&test_results.seq, 1u); @@ -229,11 +358,14 @@ fn(async (t) => { atomicAdd(&test_results.weak, 1u); } `; - const testShader = buildTestShader( + let testShader = buildTestShader( getTestCode(t.params), t.params.memType, TestType.IntraWorkgroup ); + if (!t.params.normalBarrier) { + testShader += '\nvar placeholder_wg_var : u32;\n'; + } const resultShader = buildResultShader( resultCode, TestType.IntraWorkgroup, @@ -244,7 +376,8 @@ fn(async (t) => { memoryModelTestParams, testShader, resultShader, - t.params.accessValueType + t.params.accessValueType, + t.params.memType === MemoryType.NonAtomicTextureClass ); await memModelTester.run(10, 1); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/memory_model_setup.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/memory_model_setup.js index 8d107ae597..b10243e610 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/memory_model_setup.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/memory_model_setup.js @@ -1,6 +1,8 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { checkElementsPassPredicate } from '../../../util/check_contents.js'; +**/import { checkElementsPassPredicate } from '../../../util/check_contents.js';import { align } from '../../../util/math.js'; +import { PRNG } from '../../../util/prng.js'; + /* All buffer sizes are counted in units of 4-byte words. */ /** @@ -15,6 +17,9 @@ export const kAccessValueTypes = ['f16', 'u32']; +/** The width used for textures (default compat limit in WebGPU). */ +const kWidth = 4096; + /* Parameter values are set heuristically, typically by a time-intensive search. */ @@ -82,6 +87,27 @@ const numReadOutputs = 2; +/** Represents a device texture and a utility buffer for resetting memory and copying parameters. */ + + + + + + + + + + + + + + + + + + + + /** Specifies the buffers used during a memory model test. */ @@ -99,6 +125,10 @@ const numReadOutputs = 2; + + + + @@ -128,11 +158,11 @@ const bytesPerWord = 4; * - enable directives, if necessary * - the type alias for AccessValueType */ -function shaderPreamble(accessValueType) { +function shaderPreamble(accessValueType, constants) { if (accessValueType === 'f16') { - return 'enable f16;\nalias AccessValueTy = f16;\n'; + return `enable f16;\nalias AccessValueTy = f16;\n${constants}\n`; } - return `alias AccessValueTy = ${accessValueType};\n`; + return `alias AccessValueTy = ${accessValueType};\n${constants}\n`; } /** @@ -180,30 +210,46 @@ export class MemoryModelTester { + + + + /** Sets up a memory model test by initializing buffers and pipeline layouts. */ constructor( t, params, testShader, resultShader, - accessValueType = 'u32') + accessValueType = 'u32', + useTexture = false) { + this.prng = new PRNG(1); this.test = t; this.params = params; - - testShader = shaderPreamble(accessValueType) + testShader; - resultShader = shaderPreamble(accessValueType) + resultShader; + this.useTexture = useTexture; + + const workgroupXSize = Math.min(params.workgroupSize, t.device.limits.maxComputeWorkgroupSizeX); + const constants = ` + const kNumBarriers = 1u; // MAINTENANCE_TODO: make barrier not an array + const kMaxWorkgroups = ${params.maxWorkgroups}u; + const kScratchMemorySize = ${params.scratchMemorySize}u; + const kWorkgroupXSize = ${workgroupXSize}u; + `; + testShader = shaderPreamble(accessValueType, constants) + testShader; + resultShader = shaderPreamble(accessValueType, constants) + resultShader; // set up buffers - const testingThreads = this.params.workgroupSize * this.params.testingWorkgroups; + const testingThreads = workgroupXSize * this.params.testingWorkgroups; const testLocationsSize = testingThreads * numMemLocations * this.params.memStride * bytesPerWord; const testLocationsBuffer = { deviceBuf: this.test.device.createBuffer({ + label: 'testLocationsBuffer', size: testLocationsSize, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE }), srcBuf: this.test.device.createBuffer({ + label: 'testLocationsSrcBuf', size: testLocationsSize, usage: GPUBufferUsage.COPY_SRC }), @@ -213,10 +259,12 @@ export class MemoryModelTester { const readResultsSize = testingThreads * numReadOutputs * bytesPerWord; const readResultsBuffer = { deviceBuf: this.test.device.createBuffer({ + label: 'readResultsBuffer', size: readResultsSize, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE }), srcBuf: this.test.device.createBuffer({ + label: 'readResultsSrcBuf', size: readResultsSize, usage: GPUBufferUsage.COPY_SRC }), @@ -226,10 +274,12 @@ export class MemoryModelTester { const testResultsSize = this.params.numBehaviors * bytesPerWord; const testResultsBuffer = { deviceBuf: this.test.device.createBuffer({ + label: 'testResultsBuffer', size: testResultsSize, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC }), srcBuf: this.test.device.createBuffer({ + label: 'testResultsSrcBuffer', size: testResultsSize, usage: GPUBufferUsage.COPY_SRC }), @@ -249,52 +299,87 @@ export class MemoryModelTester { size: shuffledWorkgroupsSize }; - const barrierSize = bytesPerWord; + if (this.useTexture) { + const numTexels = testLocationsSize / bytesPerWord; + const width = kWidth; + const height = numTexels / width; + const textureSize = { width, height }; + const textureLocations = { + deviceTex: this.test.device.createTexture({ + format: 'r32uint', + dimension: '2d', + size: textureSize, + usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.STORAGE_BINDING + }), + srcBuf: testLocationsBuffer.srcBuf, + size: testLocationsSize + }; + this.textures = { + testLocations: textureLocations + }; + } + + // Combine 3 arrays into 1 buffer as we need to keep the number of storage buffers to 4 for compat. + const falseSharingAvoidanceQuantum = 4096; + const barrierSize = align(bytesPerWord, falseSharingAvoidanceQuantum); + const scratchpadSize = align( + this.params.scratchMemorySize * bytesPerWord, + falseSharingAvoidanceQuantum + ); + const scratchMemoryLocationsSize = align( + this.params.maxWorkgroups * bytesPerWord, + falseSharingAvoidanceQuantum + ); + const comboSize = barrierSize + scratchpadSize + scratchMemoryLocationsSize; + + const comboBuffer = this.test.device.createBuffer({ + label: 'comboBuffer', + size: comboSize, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE + }); + const barrierBuffer = { - deviceBuf: this.test.device.createBuffer({ - size: barrierSize, - usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE - }), + deviceBuf: comboBuffer, srcBuf: this.test.device.createBuffer({ + label: 'barrierSrcBuf', size: barrierSize, usage: GPUBufferUsage.COPY_SRC }), - size: barrierSize + size: barrierSize, + offset: 0 }; - const scratchpadSize = this.params.scratchMemorySize * bytesPerWord; const scratchpadBuffer = { - deviceBuf: this.test.device.createBuffer({ - size: scratchpadSize, - usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE - }), + deviceBuf: comboBuffer, srcBuf: this.test.device.createBuffer({ + label: 'scratchpadSrcBuf', size: scratchpadSize, usage: GPUBufferUsage.COPY_SRC }), - size: scratchpadSize + size: scratchpadSize, + offset: barrierSize }; - const scratchMemoryLocationsSize = this.params.maxWorkgroups * bytesPerWord; const scratchMemoryLocationsBuffer = { - deviceBuf: this.test.device.createBuffer({ - size: scratchMemoryLocationsSize, - usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE - }), + deviceBuf: comboBuffer, srcBuf: this.test.device.createBuffer({ + label: 'scratchMemoryLocationsSrcBuf', size: scratchMemoryLocationsSize, usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE }), - size: scratchMemoryLocationsSize + size: scratchMemoryLocationsSize, + offset: barrierSize + scratchpadSize }; const stressParamsSize = numStressParams * bytesPerWord; const stressParamsBuffer = { deviceBuf: this.test.device.createBuffer({ + label: 'stressParamsBuffer', size: stressParamsSize, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM }), srcBuf: this.test.device.createBuffer({ + label: 'stressParamsSrcBuf', size: stressParamsSize, usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE }), @@ -314,19 +399,50 @@ export class MemoryModelTester { // set up pipeline layouts const testLayout = this.test.device.createBindGroupLayout({ + label: 'testLayout', entries: [ { binding: 0, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } }, { binding: 1, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } }, { binding: 2, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'read-only-storage' } }, { binding: 3, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } }, - { binding: 4, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } }, - { binding: 5, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } }, - { binding: 6, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'uniform' } }] + { binding: 4, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'uniform' } }] }); + + let layouts = [testLayout]; + if (this.useTexture) { + const textureLayout = this.test.device.createBindGroupLayout({ + label: 'textureLayout', + entries: [ + { + binding: 0, + visibility: GPUShaderStage.COMPUTE, + storageTexture: { + access: 'read-write', + format: 'r32uint', + viewDimension: '2d' + } + }] + + }); + layouts = [testLayout, textureLayout]; + + const texLocations = this.textures.testLocations.deviceTex; + this.textureBindGroup = this.test.device.createBindGroup({ + label: 'textureBindGroup', + entries: [ + { + binding: 0, + resource: texLocations.createView() + }], + + layout: textureLayout + }); + } this.testPipeline = this.test.device.createComputePipeline({ + label: 'testPipeline', layout: this.test.device.createPipelineLayout({ - bindGroupLayouts: [testLayout] + bindGroupLayouts: layouts }), compute: { module: this.test.device.createShaderModule({ @@ -336,19 +452,19 @@ export class MemoryModelTester { } }); this.testBindGroup = this.test.device.createBindGroup({ + label: 'testBindGroup', entries: [ { binding: 0, resource: { buffer: this.buffers.testLocations.deviceBuf } }, { binding: 1, resource: { buffer: this.buffers.readResults.deviceBuf } }, { binding: 2, resource: { buffer: this.buffers.shuffledWorkgroups.deviceBuf } }, - { binding: 3, resource: { buffer: this.buffers.barrier.deviceBuf } }, - { binding: 4, resource: { buffer: this.buffers.scratchpad.deviceBuf } }, - { binding: 5, resource: { buffer: this.buffers.scratchMemoryLocations.deviceBuf } }, - { binding: 6, resource: { buffer: this.buffers.stressParams.deviceBuf } }], + { binding: 3, resource: { buffer: comboBuffer } }, + { binding: 4, resource: { buffer: this.buffers.stressParams.deviceBuf } }], layout: testLayout }); const resultLayout = this.test.device.createBindGroupLayout({ + label: 'resultLayout', entries: [ { binding: 0, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } }, { binding: 1, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } }, @@ -357,6 +473,7 @@ export class MemoryModelTester { }); this.resultPipeline = this.test.device.createComputePipeline({ + label: 'resultPipeline', layout: this.test.device.createPipelineLayout({ bindGroupLayouts: [resultLayout] }), @@ -368,6 +485,7 @@ export class MemoryModelTester { } }); this.resultBindGroup = this.test.device.createBindGroup({ + label: 'resultBindGroup', entries: [ { binding: 0, resource: { buffer: this.buffers.testLocations.deviceBuf } }, { binding: 1, resource: { buffer: this.buffers.readResults.deviceBuf } }, @@ -402,10 +520,16 @@ export class MemoryModelTester { this.copyBufferToBuffer(encoder, this.buffers.scratchpad); this.copyBufferToBuffer(encoder, this.buffers.scratchMemoryLocations); this.copyBufferToBuffer(encoder, this.buffers.stressParams); + if (this.useTexture) { + this.copyBufferToTexture(encoder, this.textures.testLocations); + } const testPass = encoder.beginComputePass(); testPass.setPipeline(this.testPipeline); testPass.setBindGroup(0, this.testBindGroup); + if (this.useTexture) { + testPass.setBindGroup(1, this.textureBindGroup); + } testPass.dispatchWorkgroups(numWorkgroups); testPass.end(); @@ -464,16 +588,42 @@ export class MemoryModelTester { } /** Utility method that simplifies copying source buffers to device buffers. */ - copyBufferToBuffer(encoder, buffer) { - encoder.copyBufferToBuffer(buffer.srcBuf, 0, buffer.deviceBuf, 0, buffer.size); + copyBufferToBuffer( + encoder, + buffer) + { + encoder.copyBufferToBuffer( + buffer.srcBuf, + 0, + buffer.deviceBuf, + buffer.offset || 0, + buffer.size + ); + } + + /** Utility method that simplifies copying source buffers to device textures. */ + copyBufferToTexture(encoder, texture) { + const bytesPerWord = 4; // always uses r32uint format. + const numTexels = texture.size / bytesPerWord; + const size = { width: kWidth, height: numTexels / kWidth }; + encoder.copyBufferToTexture( + { + buffer: texture.srcBuf, + offset: 0, + bytesPerRow: kWidth * bytesPerWord, + rowsPerImage: size.height + }, + { texture: texture.deviceTex }, + size + ); } - /** Returns a random integer between 0 and the max. */ + /** Returns a random integer in the range [0, max). */ getRandomInt(max) { - return Math.floor(Math.random() * max); + return this.prng.randomU32() % max; } - /** Returns a random number in between the min and max values. */ + /** Returns a random number in the range [min, max). */ getRandomInRange(min, max) { if (min === max) { return min; @@ -626,7 +776,19 @@ const shaderMemStructures = ` }; struct IndexMemory { - value: array + value: array, + }; + + struct AtomicMemoryBarrier { + value: array, kNumBarriers> + }; + + struct IndexMemoryScratchpad { + value: array, + }; + + struct IndexMemoryScratchLocations { + value: array, }; struct ReadResult { @@ -635,7 +797,14 @@ const shaderMemStructures = ` }; struct ReadResults { - value: array + value: array, + }; + + // These arrays are combine into 1 buffer because compat mode only supports 4 storage buffers by default. + struct CombinedData { + barrier: AtomicMemoryBarrier, + scratchpad: IndexMemoryScratchpad, + scratch_locations: IndexMemoryScratchLocations, }; struct StressParamsMemory { @@ -687,10 +856,8 @@ const twoBehaviorTestResultStructure = ` const commonTestShaderBindings = ` @group(0) @binding(1) var results : ReadResults; @group(0) @binding(2) var shuffled_workgroups : IndexMemory; - @group(0) @binding(3) var barrier : AtomicMemory; - @group(0) @binding(4) var scratchpad : IndexMemory; - @group(0) @binding(5) var scratch_locations : IndexMemory; - @group(0) @binding(6) var stress_params : StressParamsMemory; + @group(0) @binding(3) var combo : CombinedData; + @group(0) @binding(4) var stress_params : StressParamsMemory; `; /** The combined bindings for a test on atomic memory. */ @@ -709,6 +876,11 @@ const nonAtomicTestShaderBindings = [ commonTestShaderBindings]. join('\n'); +/** The extra binding for texture non-atomic texture tests. */ +const textureBindings = ` +@group(1) @binding(0) var texture_locations : texture_storage_2d; +`; + /** Bindings used in the result aggregation phase of the test. */ const resultShaderBindings = ` @group(0) @binding(0) var test_locations : Memory; @@ -750,6 +922,16 @@ const memoryLocationFunctions = ` } `; +/** + * Function to convert an index into an equivalent 2D coordinate for the texture. + */ +const textureFunctions = ` + const kWidth = ${kWidth}; + fn indexToCoord(idx : u32) -> vec2u { + return vec2u(idx % kWidth, idx / kWidth); + } +`; + /** Functions that help add stress to the test. */ const testShaderFunctions = ` //Force the invocations in the workgroup to wait for each other, but without the general memory ordering @@ -758,12 +940,12 @@ const testShaderFunctions = ` // the barrier but does not overly reduce testing throughput. fn spin(limit: u32) { var i : u32 = 0u; - var bar_val : u32 = atomicAdd(&barrier.value[0], 1u); + var bar_val : u32 = atomicAdd(&combo.barrier.value[0], 1u); loop { if (i == 1024u || bar_val >= limit) { break; } - bar_val = atomicAdd(&barrier.value[0], 0u); + bar_val = atomicAdd(&combo.barrier.value[0], 0u); i = i + 1u; } } @@ -773,44 +955,44 @@ const testShaderFunctions = ` // the compiler optimizing out unused loads, where 100,000 is larger than the maximum number of stress iterations used // in any test. fn do_stress(iterations: u32, pattern: u32, workgroup_id: u32) { - let addr = scratch_locations.value[workgroup_id]; + let addr = combo.scratch_locations.value[workgroup_id]; switch(pattern) { case 0u: { for(var i: u32 = 0u; i < iterations; i = i + 1u) { - scratchpad.value[addr] = i; - scratchpad.value[addr] = i + 1u; + combo.scratchpad.value[addr] = i; + combo.scratchpad.value[addr] = i + 1u; } } case 1u: { for(var i: u32 = 0u; i < iterations; i = i + 1u) { - scratchpad.value[addr] = i; - let tmp1: u32 = scratchpad.value[addr]; + combo.scratchpad.value[addr] = i; + let tmp1: u32 = combo.scratchpad.value[addr]; if (tmp1 > 100000u) { - scratchpad.value[addr] = i; + combo.scratchpad.value[addr] = i; break; } } } case 2u: { for(var i: u32 = 0u; i < iterations; i = i + 1u) { - let tmp1: u32 = scratchpad.value[addr]; + let tmp1: u32 = combo.scratchpad.value[addr]; if (tmp1 > 100000u) { - scratchpad.value[addr] = i; + combo.scratchpad.value[addr] = i; break; } - scratchpad.value[addr] = i; + combo.scratchpad.value[addr] = i; } } case 3u: { for(var i: u32 = 0u; i < iterations; i = i + 1u) { - let tmp1: u32 = scratchpad.value[addr]; + let tmp1: u32 = combo.scratchpad.value[addr]; if (tmp1 > 100000u) { - scratchpad.value[addr] = i; + combo.scratchpad.value[addr] = i; break; } - let tmp2: u32 = scratchpad.value[addr]; + let tmp2: u32 = combo.scratchpad.value[addr]; if (tmp2 > 100000u) { - scratchpad.value[addr] = i; + combo.scratchpad.value[addr] = i; break; } } @@ -827,7 +1009,7 @@ const testShaderFunctions = ` */ const shaderEntryPoint = ` // Change to pipeline overridable constant when possible. - const workgroupXSize = 256u; + const workgroupXSize = kWorkgroupXSize; @compute @workgroup_size(workgroupXSize) fn main( @builtin(local_invocation_id) local_invocation_id : vec3, @builtin(workgroup_id) workgroup_id : vec3) { @@ -980,6 +1162,18 @@ shaderEntryPoint, testShaderCommonHeader]. join('\n'); +/** The common shader code for the test shaders that perform non-atomic texture memory litmus tests. */ +const textureMemoryNonAtomicTestShaderCode = [ +shaderMemStructures, +nonAtomicTestShaderBindings, +textureBindings, +memoryLocationFunctions, +textureFunctions, +testShaderFunctions, +shaderEntryPoint, +testShaderCommonHeader]. +join('\n'); + /** The common shader code for test shaders that perform atomic workgroup class memory litmus tests. */ const workgroupMemoryAtomicTestShaderCode = [ shaderMemStructures, @@ -1014,7 +1208,9 @@ join('\n'); * Defines the types of possible memory a test is operating on. Used as part of the process of building shader code from * its composite parts. */ -export let MemoryType = /*#__PURE__*/function (MemoryType) {MemoryType["AtomicStorageClass"] = "atomic_storage";MemoryType["NonAtomicStorageClass"] = "non_atomic_storage";MemoryType["AtomicWorkgroupClass"] = "atomic_workgroup";MemoryType["NonAtomicWorkgroupClass"] = "non_atomic_workgroup";return MemoryType;}({}); +export let MemoryType = /*#__PURE__*/function (MemoryType) {MemoryType["AtomicStorageClass"] = "atomic_storage";MemoryType["NonAtomicStorageClass"] = "non_atomic_storage";MemoryType["AtomicWorkgroupClass"] = "atomic_workgroup";MemoryType["NonAtomicWorkgroupClass"] = "non_atomic_workgroup";MemoryType["NonAtomicTextureClass"] = "non_atomic_texture";return MemoryType;}({}); + + @@ -1052,21 +1248,26 @@ memoryType, testType) { let memoryTypeCode; - let isStorageAS = false; + let isGlobalSpace = false; switch (memoryType) { case MemoryType.AtomicStorageClass: memoryTypeCode = storageMemoryAtomicTestShaderCode; - isStorageAS = true; + isGlobalSpace = true; break; case MemoryType.NonAtomicStorageClass: memoryTypeCode = storageMemoryNonAtomicTestShaderCode; - isStorageAS = true; + isGlobalSpace = true; break; case MemoryType.AtomicWorkgroupClass: memoryTypeCode = workgroupMemoryAtomicTestShaderCode; break; case MemoryType.NonAtomicWorkgroupClass: memoryTypeCode = workgroupMemoryNonAtomicTestShaderCode; + break; + case MemoryType.NonAtomicTextureClass: + memoryTypeCode = textureMemoryNonAtomicTestShaderCode; + isGlobalSpace = true; + break; } let testTypeCode; switch (testType) { @@ -1074,7 +1275,7 @@ testType) testTypeCode = interWorkgroupTestShaderCode; break; case TestType.IntraWorkgroup: - if (isStorageAS) { + if (isGlobalSpace) { testTypeCode = storageIntraWorkgroupTestShaderCode; } else { testTypeCode = intraWorkgroupTestShaderCode; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/texture_intra_invocation_coherence.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/texture_intra_invocation_coherence.spec.js new file mode 100644 index 0000000000..a528737e78 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/texture_intra_invocation_coherence.spec.js @@ -0,0 +1,333 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Test that read/write storage textures are coherent within an invocation. + +Each invocation is assigned several random writing indices and a single +read index from among those. Writes are randomly predicated (except the +one corresponding to the read). Checks that an invocation can read data +it has written to the texture previously. +Does not test coherence between invocations + +Some platform (e.g. Metal) require a fence call to make writes visible +to reads performed by the same invocation. These tests attempt to ensure +WebGPU implementations emit correct fence calls.`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { unreachable, iterRange } from '../../../../common/util/util.js'; +import { GPUTest } from '../../../gpu_test.js'; +import { PRNG } from '../../../util/prng.js'; + +const kRWStorageFormats = ['r32uint', 'r32sint', 'r32float']; +const kDimensions = ['1d', '2d', '2d-array', '3d']; + +export const g = makeTestGroup(GPUTest); + +function indexToCoord(dim) { + switch (dim) { + case '1d':{ + return ` +fn indexToCoord(idx : u32) -> u32 { + return idx; +}`; + } + case '2d': + case '2d-array':{ + return ` +fn indexToCoord(idx : u32) -> vec2u { + return vec2u(idx % (wgx * num_wgs_x), idx / (wgx * num_wgs_x)); +}`; + } + case '3d':{ + return ` +fn indexToCoord(idx : u32) -> vec3u { + return vec3u(idx % (wgx * num_wgs_x), idx / (wgx * num_wgs_x), 0); +}`; + } + default:{ + unreachable(`unhandled dimension: ${dim}`); + } + } + return ``; +} + +function textureType(format, dim) { + let t = `texture_storage_`; + switch (dim) { + case '1d':{ + t += '1d'; + break; + } + case '2d':{ + t += '2d'; + break; + } + case '2d-array':{ + t += '2d_array'; + break; + } + case '3d':{ + t += '3d'; + break; + } + default:{ + unreachable(`unhandled dim: ${dim}`); + } + } + t += `<${format}, read_write>`; + return t; +} + +function textureStore(dim, index) { + let code = `textureStore(t, indexToCoord(${index}), `; + if (dim === '2d-array') { + code += `0, `; + } + code += `texel)`; + return code; +} + +function textureLoad(dim, format) { + let code = `textureLoad(t, indexToCoord(read_index[global_index])`; + if (dim === '2d-array') { + code += `, 0`; + } + code += `).x`; + if (format !== 'r32uint') { + code = `u32(${code})`; + } + return code; +} + +function texel(format) { + switch (format) { + case 'r32uint':{ + return 'vec4u(global_index,0,0,0)'; + } + case 'r32sint':{ + return 'vec4i(i32(global_index),0,0,0)'; + } + case 'r32float':{ + return 'vec4f(f32(global_index),0,0,0)'; + } + default:{ + unreachable('unhandled format: ${format}'); + } + } + return ''; +} + +function getTextureSize(numTexels, dim) { + const size = { width: 1, height: 1, depthOrArrayLayers: 1 }; + switch (dim) { + case '1d':{ + size.width = numTexels; + break; + } + case '2d': + case '2d-array': + case '3d':{ + size.width = numTexels / 2; + size.height = numTexels / 2; + // depthOrArrayLayers defaults to 1 + break; + } + default:{ + unreachable(`unhandled dim: ${dim}`); + } + } + return size; +} + +g.test('texture_intra_invocation_coherence'). +desc(`Tests writes from an invocation are visible to reads from the same invocation`). +params((u) => u.combine('format', kRWStorageFormats).combine('dim', kDimensions)). +beforeAllSubcases((t) => { + t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format); +}). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); + + const wgx = 16; + const wgy = t.device.limits.maxComputeInvocationsPerWorkgroup / wgx; + const num_wgs_x = 2; + const num_wgs_y = 2; + const invocations = wgx * wgy * num_wgs_x * num_wgs_y; + const num_writes_per_invocation = 4; + + const code = ` +requires readonly_and_readwrite_storage_textures; + +@group(0) @binding(0) +var t : ${textureType(t.params.format, t.params.dim)}; + +@group(1) @binding(0) +var write_indices : array; + +@group(1) @binding(1) +var read_index : array; + +@group(1) @binding(2) +var write_mask : array; + +@group(1) @binding(3) +var output : array; + +const wgx = ${wgx}u; +const wgy = ${wgy}u; +const num_wgs_x = ${num_wgs_x}u; +const num_wgs_y = ${num_wgs_y}u; + +${indexToCoord(t.params.dim)} + +@compute @workgroup_size(wgx, wgy, 1) +fn main(@builtin(global_invocation_id) gid : vec3u) { + let global_index = gid.x + gid.y * num_wgs_x * wgx; + + let write_index = write_indices[global_index]; + let mask = write_mask[global_index]; + let texel = ${texel(t.params.format)}; + + if mask.x != 0 { + ${textureStore(t.params.dim, 'write_index.x')}; + } + if mask.y != 0 { + ${textureStore(t.params.dim, 'write_index.y')}; + } + if mask.z != 0 { + ${textureStore(t.params.dim, 'write_index.z')}; + } + if mask.w != 0 { + ${textureStore(t.params.dim, 'write_index.w')}; + } + output[global_index] = ${textureLoad(t.params.dim, t.params.format)}; +}`; + + // To get a variety of testing, seed the random number generator based on which case this is. + // This means subcases will not execute the same code. + const seed = + kRWStorageFormats.indexOf(t.params.format) * kRWStorageFormats.length + + kDimensions.indexOf(t.params.dim); + const prng = new PRNG(seed); + + const num_write_indices = invocations * num_writes_per_invocation; + const write_indices = new Uint32Array([...iterRange(num_write_indices, (x) => x)]); + const write_masks = new Uint32Array([...iterRange(num_write_indices, (x) => 0)]); + // Shuffle the indices. + for (let i = 0; i < num_write_indices; i++) { + const remaining = num_write_indices - i; + const swapIdx = prng.randomU32() % remaining + i; + const tmp = write_indices[swapIdx]; + write_indices[swapIdx] = write_indices[i]; + write_indices[i] = tmp; + + // Assign random write masks + const mask = prng.randomU32() % 2; + write_masks[i] = mask; + } + const num_read_indices = invocations; + const read_indices = new Uint32Array(num_read_indices); + for (let i = 0; i < num_read_indices; i++) { + // Pick a random index from index from this invocation's writes to read from. + // Ensure that write is not masked out. + const readIdx = prng.randomU32() % num_writes_per_invocation; + read_indices[i] = write_indices[num_writes_per_invocation * i + readIdx]; + write_masks[num_writes_per_invocation * i + readIdx] = 1; + } + + // Buffers + const write_index_buffer = t.makeBufferWithContents( + write_indices, + GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE + ); + t.trackForCleanup(write_index_buffer); + const read_index_buffer = t.makeBufferWithContents( + read_indices, + GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE + ); + t.trackForCleanup(read_index_buffer); + const write_mask_buffer = t.makeBufferWithContents( + write_masks, + GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE + ); + t.trackForCleanup(write_mask_buffer); + const output_buffer = t.makeBufferWithContents( + new Uint32Array([...iterRange(invocations, (x) => 0)]), + GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE + ); + t.trackForCleanup(output_buffer); + + // Texture + const texture_size = getTextureSize(invocations * num_writes_per_invocation, t.params.dim); + const texture = t.device.createTexture({ + format: t.params.format, + dimension: t.params.dim === '2d-array' ? '2d' : t.params.dim, + size: texture_size, + usage: GPUTextureUsage.STORAGE_BINDING + }); + t.trackForCleanup(texture); + + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ + code + }), + entryPoint: 'main' + } + }); + + const bg0 = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: texture.createView({ + format: t.params.format, + dimension: t.params.dim, + mipLevelCount: 1, + arrayLayerCount: 1 + }) + }] + + }); + const bg1 = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(1), + entries: [ + { + binding: 0, + resource: { + buffer: write_index_buffer + } + }, + { + binding: 1, + resource: { + buffer: read_index_buffer + } + }, + { + binding: 2, + resource: { + buffer: write_mask_buffer + } + }, + { + binding: 3, + resource: { + buffer: output_buffer + } + }] + + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bg0); + pass.setBindGroup(1, bg1); + pass.dispatchWorkgroups(num_wgs_x, num_wgs_y, 1); + pass.end(); + t.queue.submit([encoder.finish()]); + + const expectedOutput = new Uint32Array([...iterRange(num_read_indices, (x) => x)]); + t.expectGPUBufferValuesEqual(output_buffer, expectedOutput); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access.spec.js index 8e6cd5c80b..561bde4fce 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access.spec.js @@ -7,6 +7,7 @@ Tests to check datatype clamping in shaders is correctly implemented for all ind TODO: add tests to check that textureLoad operations stay in-bounds. `;import { makeTestGroup } from '../../../common/framework/test_group.js'; import { assert } from '../../../common/util/util.js'; +import { Float16Array } from '../../../external/petamoriken/float16/float16.js'; import { GPUTest } from '../../gpu_test.js'; import { align } from '../../util/math.js'; import { generateTypes, supportedScalarTypes, supportsAtomics } from '../types.js'; @@ -25,6 +26,7 @@ const kMinI32 = -0x8000_0000; */ async function runShaderTest( t, +enables, stage, testSource, layout, @@ -41,7 +43,7 @@ dynamicOffsets) usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE }); - const source = ` + const source = `${enables} struct Constants { zero: u32 }; @@ -99,7 +101,9 @@ array, type, { zeroByteStart, zeroByteCount }) { - const constructor = { u32: Uint32Array, i32: Int32Array, f32: Float32Array }[type]; + const constructor = { u32: Uint32Array, i32: Int32Array, f16: Float16Array, f32: Float32Array }[ + type]; + assert(zeroByteCount % constructor.BYTES_PER_ELEMENT === 0); new constructor(array).fill(42); new constructor(array, zeroByteStart, zeroByteCount / constructor.BYTES_PER_ELEMENT).fill(0); @@ -122,6 +126,7 @@ desc( TODO: Test types like vec2>, if that's allowed. TODO: Test exprIndexAddon as constexpr. TODO: Test exprIndexAddon as pipeline-overridable constant expression. + TODO: Adjust test logic to support array of f16 in the uniform address space ` ). params((u) => @@ -168,10 +173,15 @@ combineWithParams([ { shadowingMode: 'function-scope' }] ). expand('isAtomic', (p) => supportsAtomics(p) ? [false, true] : [false]). -beginSubcases(). expand('baseType', supportedScalarTypes). +beginSubcases(). expandWithParams(generateTypes) ). +beforeAllSubcases((t) => { + if (t.params.baseType === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). fn(async (t) => { const { addressSpace, @@ -189,6 +199,13 @@ fn(async (t) => { assert(_kTypeInfo !== undefined, 'not an indexable type'); assert('arrayLength' in _kTypeInfo); + if (baseType === 'f16' && addressSpace === 'uniform' && containerType === 'array') { + // Array elements must be aligned to 16 bytes, but the logic in generateTypes + // creates an array of vec4 of the baseType. But for f16 that's only 8 bytes. + // We would need to write more complex logic for that. + t.skip('Test logic does not handle array of f16 in the uniform address space'); + } + let usesCanary = false; let globalSource = ''; let testFunctionSource = ''; @@ -429,6 +446,8 @@ fn runTest() -> u32 { }); + const enables = t.params.baseType === 'f16' ? 'enable f16;' : ''; + // Run it. if (bufferBindingSize !== undefined && baseType !== 'bool') { const expectedData = new ArrayBuffer(testBufferSize); @@ -450,6 +469,7 @@ fn runTest() -> u32 { // Run the shader, accessing the buffer. await runShaderTest( t, + enables, GPUShaderStage.COMPUTE, testSource, layout, @@ -475,6 +495,6 @@ fn runTest() -> u32 { bufferBindingEnd ); } else { - await runShaderTest(t, GPUShaderStage.COMPUTE, testSource, layout, []); + await runShaderTest(t, enables, GPUShaderStage.COMPUTE, testSource, layout, []); } }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access_vertex.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access_vertex.spec.js index d632179008..f964d330c3 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access_vertex.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access_vertex.spec.js @@ -545,6 +545,7 @@ params( combine('additionalBuffers', [0, 4]). combine('partialLastNumber', [false, true]). combine('offsetVertexBuffer', [false, true]). + beginSubcases(). combine('errorScale', [0, 1, 4, 10 ** 2, 10 ** 4, 10 ** 6]). unless((p) => p.drawCallTestParameter === 'instanceCount' && p.errorScale > 10 ** 4) // To avoid timeout ). diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/compute_builtins.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/compute_builtins.spec.js index 68eebacc05..90de84fb44 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/compute_builtins.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/compute_builtins.spec.js @@ -1,7 +1,6 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = `Test compute shader builtin variables`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; -import { iterRange } from '../../../../common/util/util.js'; import { GPUTest } from '../../../gpu_test.js'; export const g = makeTestGroup(GPUTest); @@ -98,17 +97,14 @@ fn((t) => { // WGSL shader that stores every builtin value to a buffer, for every invocation in the grid. const wgsl = ` - struct S { - data : array + struct Outputs { + local_id: vec3u, + local_index: u32, + global_id: vec3u, + group_id: vec3u, + num_groups: vec3u, }; - struct V { - data : array> - }; - @group(0) @binding(0) var local_id_out : V; - @group(0) @binding(1) var local_index_out : S; - @group(0) @binding(2) var global_id_out : V; - @group(0) @binding(3) var group_id_out : V; - @group(0) @binding(4) var num_groups_out : V; + @group(0) @binding(0) var outputs : array; ${structures} @@ -122,11 +118,13 @@ fn((t) => { ) { let group_index = ((${group_id}.z * ${num_groups}.y) + ${group_id}.y) * ${num_groups}.x + ${group_id}.x; let global_index = group_index * ${invocationsPerGroup}u + ${local_index}; - local_id_out.data[global_index] = ${local_id}; - local_index_out.data[global_index] = ${local_index}; - global_id_out.data[global_index] = ${global_id}; - group_id_out.data[global_index] = ${group_id}; - num_groups_out.data[global_index] = ${num_groups}; + var o: Outputs; + o.local_id = ${local_id}; + o.local_index = ${local_index}; + o.global_id = ${global_id}; + o.group_id = ${group_id}; + o.num_groups = ${num_groups}; + outputs[global_index] = o; } `; @@ -140,35 +138,24 @@ fn((t) => { } }); - // Helper to create a `size`-byte buffer with binding number `binding`. - function createBuffer(size, binding) { - const buffer = t.device.createBuffer({ - size, - usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC - }); - t.trackForCleanup(buffer); - - bindGroupEntries.push({ - binding, - resource: { - buffer - } - }); - - return buffer; - } + // Offsets are in u32 size units + const kLocalIdOffset = 0; + const kLocalIndexOffset = 3; + const kGlobalIdOffset = 4; + const kGroupIdOffset = 8; + const kNumGroupsOffset = 12; + const kOutputElementSize = 16; // Create the output buffers. - const bindGroupEntries = []; - const localIdBuffer = createBuffer(totalInvocations * 16, 0); - const localIndexBuffer = createBuffer(totalInvocations * 4, 1); - const globalIdBuffer = createBuffer(totalInvocations * 16, 2); - const groupIdBuffer = createBuffer(totalInvocations * 16, 3); - const numGroupsBuffer = createBuffer(totalInvocations * 16, 4); + const outputBuffer = t.device.createBuffer({ + size: totalInvocations * kOutputElementSize * 4, + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC + }); + t.trackForCleanup(outputBuffer); const bindGroup = t.device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), - entries: bindGroupEntries + entries: [{ binding: 0, resource: { buffer: outputBuffer } }] }); // Run the shader. @@ -204,11 +191,7 @@ fn((t) => { // Helper to check that the vec3 value at each index of the provided `output` buffer // matches the expected value for that invocation, as generated by the `getBuiltinValue` // function. The `name` parameter is the builtin name, used for error messages. - const checkEachIndex = ( - output, - name, - getBuiltinValue) => - { + const checkEachIndex = (output) => { // Loop over workgroups. for (let gz = 0; gz < t.params.numGroups.z; gz++) { for (let gy = 0; gy < t.params.numGroups.y; gy++) { @@ -220,30 +203,44 @@ fn((t) => { const groupIndex = (gz * t.params.numGroups.y + gy) * t.params.numGroups.x + gx; const localIndex = (lz * t.params.groupSize.y + ly) * t.params.groupSize.x + lx; const globalIndex = groupIndex * invocationsPerGroup + localIndex; - const expected = getBuiltinValue( - { x: gx, y: gy, z: gz }, - { x: lx, y: ly, z: lz } + const globalOffset = globalIndex * kOutputElementSize; + + const expectEqual = (name, expected, actual) => { + if (actual !== expected) { + return new Error( + `${name} failed at group(${gx},${gy},${gz}) local(${lx},${ly},${lz}))\n` + + ` expected: ${expected}\n` + + ` got: ${actual}` + ); + } + return undefined; + }; + + const checkVec3Value = (name, fieldOffset, expected) => { + const offset = globalOffset + fieldOffset; + return ( + expectEqual(`${name}.x`, expected.x, output[offset + 0]) || + expectEqual(`${name}.y`, expected.y, output[offset + 1]) || + expectEqual(`${name}.z`, expected.z, output[offset + 2])); + + }; + + const error = + checkVec3Value('local_id', kLocalIdOffset, { x: lx, y: ly, z: lz }) || + checkVec3Value('global_id', kGlobalIdOffset, { + x: gx * t.params.groupSize.x + lx, + y: gy * t.params.groupSize.y + ly, + z: gz * t.params.groupSize.z + lz + }) || + checkVec3Value('group_id', kGroupIdOffset, { x: gx, y: gy, z: gz }) || + checkVec3Value('num_groups', kNumGroupsOffset, t.params.numGroups) || + expectEqual( + 'local_index', + localIndex, + output[globalOffset + kLocalIndexOffset] ); - if (output[globalIndex * 4 + 0] !== expected.x) { - return new Error( - `${name}.x failed at group(${gx},${gy},${gz}) local(${lx},${ly},${lz}))\n` + - ` expected: ${expected.x}\n` + - ` got: ${output[globalIndex * 4 + 0]}` - ); - } - if (output[globalIndex * 4 + 1] !== expected.y) { - return new Error( - `${name}.y failed at group(${gx},${gy},${gz}) local(${lx},${ly},${lz}))\n` + - ` expected: ${expected.y}\n` + - ` got: ${output[globalIndex * 4 + 1]}` - ); - } - if (output[globalIndex * 4 + 2] !== expected.z) { - return new Error( - `${name}.z failed at group(${gx},${gy},${gz}) local(${lx},${ly},${lz}))\n` + - ` expected: ${expected.z}\n` + - ` got: ${output[globalIndex * 4 + 2]}` - ); + if (error) { + return error; } } } @@ -254,44 +251,8 @@ fn((t) => { return undefined; }; - // Check @builtin(local_invocation_index) values. - t.expectGPUBufferValuesEqual( - localIndexBuffer, - new Uint32Array([...iterRange(totalInvocations, (x) => x % invocationsPerGroup)]) - ); - - // Check @builtin(local_invocation_id) values. - t.expectGPUBufferValuesPassCheck( - localIdBuffer, - (outputData) => checkEachIndex(outputData, 'local_invocation_id', (_, localId) => localId), - { type: Uint32Array, typedLength: totalInvocations * 4 } - ); - - // Check @builtin(global_invocation_id) values. - const getGlobalId = (groupId, localId) => { - return { - x: groupId.x * t.params.groupSize.x + localId.x, - y: groupId.y * t.params.groupSize.y + localId.y, - z: groupId.z * t.params.groupSize.z + localId.z - }; - }; - t.expectGPUBufferValuesPassCheck( - globalIdBuffer, - (outputData) => checkEachIndex(outputData, 'global_invocation_id', getGlobalId), - { type: Uint32Array, typedLength: totalInvocations * 4 } - ); - - // Check @builtin(workgroup_id) values. - t.expectGPUBufferValuesPassCheck( - groupIdBuffer, - (outputData) => checkEachIndex(outputData, 'workgroup_id', (groupId, _) => groupId), - { type: Uint32Array, typedLength: totalInvocations * 4 } - ); - - // Check @builtin(num_workgroups) values. - t.expectGPUBufferValuesPassCheck( - numGroupsBuffer, - (outputData) => checkEachIndex(outputData, 'num_workgroups', () => t.params.numGroups), - { type: Uint32Array, typedLength: totalInvocations * 4 } - ); + t.expectGPUBufferValuesPassCheck(outputBuffer, (outputData) => checkEachIndex(outputData), { + type: Uint32Array, + typedLength: outputBuffer.size / 4 + }); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/fragment_builtins.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/fragment_builtins.spec.js new file mode 100644 index 0000000000..c02a1c8cda --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/fragment_builtins.spec.js @@ -0,0 +1,1410 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Test fragment shader builtin variables and inter-stage variables + +* test builtin(position) +* test @interpolate +* test builtin(sample_index) +* test builtin(front_facing) +* test builtin(sample_mask) + +Note: @interpolate settings and sample_index affect whether or not the fragment shader +is evaluated per-fragment or per-sample. With @interpolate(, sample) or usage of +@builtin(sample_index) the fragment shader should be executed per-sample. + +* sample_mask output is tested in + src/webgpu/api/operation/render_pipeline/sample_mask.spec.ts + +* frag_depth output is tested in + src/webgpu/api/operation/rendering/depth_clip_clamp.spec.ts +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { ErrorWithExtra, assert, range, unreachable } from '../../../../common/util/util.js'; + +import { GPUTest } from '../../../gpu_test.js'; +import { getMultisampleFragmentOffsets } from '../../../multisample_info.js'; +import { dotProduct, subtractVectors } from '../../../util/math.js'; +import { TexelView } from '../../../util/texture/texel_view.js'; +import { findFailedPixels } from '../../../util/texture/texture_ok.js'; + +export const g = makeTestGroup(GPUTest); + +const s_deviceToPipelineMap = new WeakMap( + + + + + +); + +/** + * Returns an object of pipelines associated + * by weakmap to a device so we can cache pipelines. + */ +function getPipelinesForDevice(device) { + let pipelines = s_deviceToPipelineMap.get(device); + if (!pipelines) { + pipelines = {}; + s_deviceToPipelineMap.set(device, pipelines); + } + return pipelines; +} + +/** + * Gets a compute pipeline that will copy the given texture if passed + * a dispatch size of texture.width, texture.height + * @param device a device + * @param texture texture the pipeline is needed for. + * @returns A GPUComputePipeline + */ +function getCopyMultisamplePipelineForDevice(device, textures) { + assert(textures.length === 4); + assert(textures[0].sampleCount === textures[1].sampleCount); + assert(textures[0].sampleCount === textures[2].sampleCount); + assert(textures[0].sampleCount === textures[3].sampleCount); + + const pipelineType = textures[0].sampleCount > 1 ? 'texture_multisampled_2d' : 'texture_2d'; + const pipelines = getPipelinesForDevice(device); + let pipeline = pipelines[pipelineType]; + if (!pipeline) { + const isMultisampled = pipelineType === 'texture_multisampled_2d'; + const numSamples = isMultisampled ? 'textureNumSamples(texture0)' : '1u'; + const sampleIndex = isMultisampled ? 'sampleIndex' : '0'; + const module = device.createShaderModule({ + code: ` + @group(0) @binding(0) var texture0: ${pipelineType}; + @group(0) @binding(1) var texture1: ${pipelineType}; + @group(0) @binding(2) var texture2: ${pipelineType}; + @group(0) @binding(3) var texture3: ${pipelineType}; + @group(0) @binding(4) var buffer: array; + + @compute @workgroup_size(1) fn cs(@builtin(global_invocation_id) id: vec3u) { + let numSamples = ${numSamples}; + let dimensions = textureDimensions(texture0); + let sampleIndex = id.x % numSamples; + let tx = id.x / numSamples; + let offset = ((id.y * dimensions.x + tx) * numSamples + sampleIndex) * 4; + let r = vec4u(textureLoad(texture0, vec2u(tx, id.y), ${sampleIndex}) * 255.0); + let g = vec4u(textureLoad(texture1, vec2u(tx, id.y), ${sampleIndex}) * 255.0); + let b = vec4u(textureLoad(texture2, vec2u(tx, id.y), ${sampleIndex}) * 255.0); + let a = vec4u(textureLoad(texture3, vec2u(tx, id.y), ${sampleIndex}) * 255.0); + + // expand rgba8unorm values back to their byte form, add them together + // and cast them to an f32 so we can recover the f32 values we encoded + // in the rgba8unorm texture. + buffer[offset + 0] = bitcast(dot(r, vec4u(0x1000000, 0x10000, 0x100, 0x1))); + buffer[offset + 1] = bitcast(dot(g, vec4u(0x1000000, 0x10000, 0x100, 0x1))); + buffer[offset + 2] = bitcast(dot(b, vec4u(0x1000000, 0x10000, 0x100, 0x1))); + buffer[offset + 3] = bitcast(dot(a, vec4u(0x1000000, 0x10000, 0x100, 0x1))); + } + ` + }); + + pipeline = device.createComputePipeline({ + label: 'copy multisampled texture pipeline', + layout: 'auto', + compute: { + module, + entryPoint: 'cs' + } + }); + + pipelines[pipelineType] = pipeline; + } + return pipeline; +} + +function isTextureSameDimensions(a, b) { + return ( + a.sampleCount === b.sampleCount && + a.width === b.width && + a.height === b.height && + a.depthOrArrayLayers === b.depthOrArrayLayers); + +} + +/** + * Copies a texture (even if multisampled) to a buffer + * @param t a gpu test + * @param texture texture to copy + * @returns buffer with copy of texture, mip level 0, array layer 0. + */ +function copyRGBA8EncodedFloatTexturesToBufferIncludingMultisampledTextures( +t, +textures) +{ + assert(textures.length === 4); + assert(isTextureSameDimensions(textures[0], textures[1])); + assert(isTextureSameDimensions(textures[0], textures[2])); + assert(isTextureSameDimensions(textures[0], textures[3])); + const { width, height, sampleCount } = textures[0]; + + const copyBuffer = t.device.createBuffer({ + size: width * height * sampleCount * 4 * 4, + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC + }); + t.trackForCleanup(copyBuffer); + + const buffer = t.device.createBuffer({ + size: copyBuffer.size, + usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST + }); + t.trackForCleanup(buffer); + + const pipeline = getCopyMultisamplePipelineForDevice(t.device, textures); + const encoder = t.device.createCommandEncoder(); + + const textureEntries = textures.map( + (texture, i) => ({ binding: i, resource: texture.createView() }) + ); + + const bindGroup = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [...textureEntries, { binding: 4, resource: { buffer: copyBuffer } }] + }); + + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bindGroup); + pass.dispatchWorkgroups(width * sampleCount, height); + pass.end(); + + encoder.copyBufferToBuffer(copyBuffer, 0, buffer, 0, buffer.size); + + t.device.queue.submit([encoder.finish()]); + + return buffer; +} + +/* column constants */ +const kX = 0; +const kY = 1; +const kZ = 2; +const kW = 3; + +/** + * Gets a column of values from an array of arrays. + */ +function getColumn(values, colNum) { + return values.map((v) => v[colNum]); +} + +/** + * Computes the linear interpolation of 3 values from 3 vertices of a triangle + * based on barycentric coordinates + */ +function linearInterpolation(baryCoords, interCoords) { + return dotProduct(baryCoords, interCoords); +} + +/** + * Computes the perspective interpolation of 3 values from 3 vertices of a + * triangle based on barycentric coordinates and their corresponding clip space + * W coordinates. + */ +function perspectiveInterpolation( +barycentricCoords, +clipSpaceTriangleCoords, +interCoords) +{ + const [a, b, c] = barycentricCoords; + const [fa, fb, fc] = interCoords; + const wa = clipSpaceTriangleCoords[0][kW]; + const wb = clipSpaceTriangleCoords[1][kW]; + const wc = clipSpaceTriangleCoords[2][kW]; + + return (a * fa / wa + b * fb / wb + c * fc / wc) / (a / wa + b / wb + c / wc); +} + +/** + * Converts clip space coords to NDC coords + */ +function clipSpaceToNDC(point) { + return point.map((v) => v / point[kW]); +} + +/** + * Converts NDC coords to window coords. + */ +function ndcToWindow(ndcPoint, viewport) { + const [xd, yd, zd] = ndcPoint; + const px = viewport[2]; + const py = viewport[3]; + const ox = viewport[0] + px / 2; + const oy = viewport[1] + py / 2; + const zNear = viewport[4]; + const zFar = viewport[5]; + + return [ + px / 2 * xd + ox, + -py / 2 * yd + oy, + zd * (zFar - zNear) + zNear]; + +} + +/** + * Computes barycentric coordinates of triangle for point p. + * @param trianglePoints points for triangle + * @param p point in triangle (or relative to it) + * @returns barycentric coords of p + */ +function calcBarycentricCoordinates(trianglePoints, p) { + const [a, b, c] = trianglePoints; + + const v0 = subtractVectors(b, a); + const v1 = subtractVectors(c, a); + const v2 = subtractVectors(p, a); + + const dot00 = dotProduct(v0, v0); + const dot01 = dotProduct(v0, v1); + const dot11 = dotProduct(v1, v1); + const dot20 = dotProduct(v2, v0); + const dot21 = dotProduct(v2, v1); + + const denom = 1 / (dot00 * dot11 - dot01 * dot01); + const v = (dot11 * dot20 - dot01 * dot21) * denom; + const w = (dot00 * dot21 - dot01 * dot20) * denom; + const u = 1 - v - w; + + return [u, v, w]; +} + +/** + * Returns true if point is inside triangle + */ +function isInsideTriangle(barycentricCoords) { + for (const v of barycentricCoords) { + if (v < 0 || v > 1) { + return false; + } + } + return true; +} + +/** + * Returns true if windowPoints define a clockwise triangle + */ +function isTriangleClockwise(windowPoints) { + let sum = 0; + for (let i = 0; i < 3; ++i) { + const p0 = windowPoints[i]; + const p1 = windowPoints[(i + 1) % 3]; + sum += p0[kX] * p1[kY] - p1[kX] * p0[kY]; + } + return sum >= 0; +} + + + + + + + + + + + + + + +/** + * For each sample in texture, computes the values that would be provided + * to the shader as `@builtin(position)` if the texture was a render target + * and every point in the texture was inside the triangle. + * @param texture The texture + * @param clipSpacePoints triangle points in clip space + * @returns the expected values for each sample + */ +function generateFragmentInputs({ + width, + height, + nearFar, + sampleCount, + frontFace, + clipSpacePoints, + interpolateFn + + + + + + + + +}) { + const expected = new Float32Array(width * height * sampleCount * 4); + + const viewport = [0, 0, width, height, ...nearFar]; + + // For each triangle + for (let vertexIndex = 0; vertexIndex < clipSpacePoints.length; vertexIndex += 3) { + const ndcPoints = clipSpacePoints.slice(vertexIndex, vertexIndex + 3).map(clipSpaceToNDC); + const windowPoints = ndcPoints.map((p) => ndcToWindow(p, viewport)); + const windowPoints2D = windowPoints.map((p) => p.slice(0, 2)); + + const cw = isTriangleClockwise(windowPoints2D); + const frontFacing = frontFace === 'cw' ? cw : !cw; + const fragmentOffsets = getMultisampleFragmentOffsets(sampleCount); + + for (let y = 0; y < height; ++y) { + for (let x = 0; x < width; ++x) { + let sampleMask = 0; + for (let sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex) { + const localSampleMask = 1 << sampleIndex; + const multisampleOffset = fragmentOffsets[sampleIndex]; + const sampleFragmentPoint = [x + multisampleOffset[0], y + multisampleOffset[1]]; + const sampleBarycentricCoords = calcBarycentricCoordinates( + windowPoints2D, + sampleFragmentPoint + ); + + const inside = isInsideTriangle(sampleBarycentricCoords); + if (inside) { + sampleMask |= localSampleMask; + } + } + + for (let sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex) { + const fragmentPoint = [x + 0.5, y + 0.5]; + const multisampleOffset = fragmentOffsets[sampleIndex]; + const sampleFragmentPoint = [x + multisampleOffset[0], y + multisampleOffset[1]]; + const fragmentBarycentricCoords = calcBarycentricCoordinates( + windowPoints2D, + fragmentPoint + ); + const sampleBarycentricCoords = calcBarycentricCoordinates( + windowPoints2D, + sampleFragmentPoint + ); + + const inside = isInsideTriangle(sampleBarycentricCoords); + if (inside) { + const output = interpolateFn({ + baseVertexIndex: vertexIndex, + fragmentPoint, + fragmentBarycentricCoords, + sampleBarycentricCoords, + clipSpacePoints, + ndcPoints, + windowPoints, + sampleIndex, + sampleMask, + frontFacing + }); + + const offset = ((y * width + x) * sampleCount + sampleIndex) * 4; + expected.set(output, offset); + } + } + } + } + } + return expected; +} + +/** + * Computes 'builtin(position)` + */ +function computeFragmentPosition({ + fragmentPoint, + fragmentBarycentricCoords, + clipSpacePoints, + windowPoints +}) { + return [ + fragmentPoint[0], + fragmentPoint[1], + linearInterpolation(fragmentBarycentricCoords, getColumn(windowPoints, kZ)), + 1 / + perspectiveInterpolation( + fragmentBarycentricCoords, + clipSpacePoints, + getColumn(clipSpacePoints, kW) + )]; + +} + +/** + * Creates a function that will compute the interpolation of an inter-stage variable. + */ +function createInterStageInterpolationFn( +interStagePoints, +type, +sampling) +{ + return function ({ + baseVertexIndex, + fragmentBarycentricCoords, + sampleBarycentricCoords, + clipSpacePoints + }) { + const triangleInterStagePoints = interStagePoints.slice(baseVertexIndex, baseVertexIndex + 3); + const barycentricCoords = + sampling === 'center' ? fragmentBarycentricCoords : sampleBarycentricCoords; + switch (type) { + case 'perspective': + return triangleInterStagePoints[0].map((_, colNum) => + perspectiveInterpolation( + barycentricCoords, + clipSpacePoints, + getColumn(triangleInterStagePoints, colNum) + ) + ); + break; + case 'linear': + return triangleInterStagePoints[0].map((_, colNum) => + linearInterpolation(barycentricCoords, getColumn(triangleInterStagePoints, colNum)) + ); + break; + case 'flat': + return triangleInterStagePoints[0]; + break; + default: + unreachable(); + } + }; +} + +/** + * Creates a function that will compute the interpolation of an inter-stage variable + * and then return [1, 0, 0, 0] if all interpolated values are between 0.0 and 1.0 inclusive + * or [-1, 0, 0, 0] otherwise. + */ +function createInterStageInterpolationBetween0And1TestFn( +interStagePoints, +type, +sampling) +{ + const interpolateFn = createInterStageInterpolationFn(interStagePoints, type, sampling); + return function (fragData) { + const interpolatedValues = interpolateFn(fragData); + const allTrue = interpolatedValues.reduce((all, v) => all && v >= 0 && v <= 1, true); + return [allTrue ? 1 : -1, 0, 0, 0]; + }; +} + +/** + * Computes 'builtin(sample_index)' + */ +function computeFragmentSampleIndex({ sampleIndex }) { + return [sampleIndex, 0, 0, 0]; +} + +/** + * Computes 'builtin(front_facing)' + */ +function computeFragmentFrontFacing({ frontFacing }) { + return [frontFacing ? 1 : 0, 0, 0, 0]; +} + +/** + * Computes 'builtin(sample_mask)' + */ +function computeSampleMask({ sampleMask }) { + return [sampleMask, 0, 0, 0]; +} + +/** + * Renders float32 fragment shader inputs values to 4 rgba8unorm textures that + * can be multisampled textures. It stores each of the channels, r, g, b, a of + * the shader input to a separate texture, doing the math required to store the + * float32 value into an rgba8unorm texel. + * + * Note: We could try to store the output to an vec4f storage buffer. + * Unfortunately, using a storage buffer has the issue that we need to compute + * an index with the very thing we're trying to test. Similarly, if we used a + * storage texture we would need to compute texture locations with the things + * we're trying to test. Also, using a storage buffer seems to affect certain + * backends like M1 Mac so it seems better to stick to rgba8unorm here and test + * using a storage buffer in a fragment shader separately. + * + * We can't use rgba32float because it's optional. We can't use rgba16float + * because it's optional in compat. We can't we use rgba32uint as that can't be + * multisampled. + */ +async function renderFragmentShaderInputsTo4TexturesAndReadbackValues( +t, +{ + interpolationType, + interpolationSampling, + sampleCount, + width, + height, + nearFar, + frontFace, + clipSpacePoints, + interStagePoints, + fragInCode, + outputCode + + + + + + + + + + + + +}) +{ + const interpolate = `${interpolationType}${ + interpolationSampling ? `, ${interpolationSampling}` : '' + }`; + const module = t.device.createShaderModule({ + code: ` + struct Uniforms { + resolution: vec2f, + }; + + @group(0) @binding(0) var uni: Uniforms; + + struct VertexOut { + @builtin(position) position: vec4f, + @location(0) @interpolate(${interpolate}) interpolatedValue: vec4f, + }; + + @vertex fn vs(@builtin(vertex_index) vNdx: u32) -> VertexOut { + let pos = array( + ${clipSpacePoints.map((p) => `vec4f(${p.join(', ')})`).join(', ')} + ); + let interStage = array( + ${interStagePoints.map((p) => `vec4f(${p.join(', ')})`).join(', ')} + ); + var v: VertexOut; + v.position = pos[vNdx]; + v.interpolatedValue = interStage[vNdx]; + _ = uni; + return v; + } + + struct FragmentIn { + @builtin(position) position: vec4f, + @location(0) @interpolate(${interpolate}) interpolatedValue: vec4f, + ${fragInCode} + }; + + struct FragOut { + @location(0) out0: vec4f, + @location(1) out1: vec4f, + @location(2) out2: vec4f, + @location(3) out3: vec4f, + }; + + fn u32ToRGBAUnorm(u: u32) -> vec4f { + return vec4f( + f32((u >> 24) & 0xFF) / 255.0, + f32((u >> 16) & 0xFF) / 255.0, + f32((u >> 8) & 0xFF) / 255.0, + f32((u >> 0) & 0xFF) / 255.0, + ); + } + + @fragment fn fs(fin: FragmentIn) -> FragOut { + var f: FragOut; + let v = ${outputCode}; + let u = bitcast(v); + f.out0 = u32ToRGBAUnorm(u[0]); + f.out1 = u32ToRGBAUnorm(u[1]); + f.out2 = u32ToRGBAUnorm(u[2]); + f.out3 = u32ToRGBAUnorm(u[3]); + _ = fin.interpolatedValue; + return f; + } + ` + }); + + const textures = range(4, () => { + const texture = t.device.createTexture({ + size: [width, height], + usage: + GPUTextureUsage.RENDER_ATTACHMENT | + GPUTextureUsage.TEXTURE_BINDING | + GPUTextureUsage.COPY_SRC, + format: 'rgba8unorm', + sampleCount + }); + t.trackForCleanup(texture); + return texture; + }); + + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { + module, + entryPoint: 'vs' + }, + fragment: { + module, + entryPoint: 'fs', + targets: textures.map(() => ({ format: 'rgba8unorm' })) + }, + ...(frontFace && { + primitive: { + frontFace + } + }), + multisample: { + count: sampleCount + } + }); + + const uniformBuffer = t.device.createBuffer({ + size: 8, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST + }); + t.trackForCleanup(uniformBuffer); + t.device.queue.writeBuffer(uniformBuffer, 0, new Float32Array([width, height])); + + const viewport = [0, 0, width, height, ...nearFar]; + + const bindGroup = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [{ binding: 0, resource: { buffer: uniformBuffer } }] + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ + colorAttachments: textures.map((texture) => ({ + view: texture.createView(), + loadOp: 'clear', + storeOp: 'store' + })) + }); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bindGroup); + pass.setViewport(viewport[0], viewport[1], viewport[2], viewport[3], viewport[4], viewport[5]); + pass.draw(clipSpacePoints.length); + pass.end(); + t.queue.submit([encoder.finish()]); + + const buffer = copyRGBA8EncodedFloatTexturesToBufferIncludingMultisampledTextures(t, textures); + await buffer.mapAsync(GPUMapMode.READ); + return new Float32Array(buffer.getMappedRange()); +} + +function checkSampleRectsApproximatelyEqual({ + width, + height, + sampleCount, + actual, + expected, + maxDiffULPsForFloatFormat + + + + + + + +}) { + const subrectOrigin = [0, 0, 0]; + const subrectSize = [width * sampleCount, height, 1]; + const areaDesc = { + bytesPerRow: width * sampleCount * 4 * 4, + rowsPerImage: height, + subrectOrigin, + subrectSize + }; + + const format = 'rgba32float'; + const actTexelView = TexelView.fromTextureDataByReference( + format, + new Uint8Array(actual.buffer), + areaDesc + ); + const expTexelView = TexelView.fromTextureDataByReference( + format, + new Uint8Array(expected.buffer), + areaDesc + ); + + const failedPixelsMessage = findFailedPixels( + format, + { x: 0, y: 0, z: 0 }, + { width: width * sampleCount, height, depthOrArrayLayers: 1 }, + { actTexelView, expTexelView }, + { maxDiffULPsForFloatFormat } + ); + + if (failedPixelsMessage !== undefined) { + const msg = 'Texture level had unexpected contents:\n' + failedPixelsMessage; + return new ErrorWithExtra(msg, () => ({ + expTexelView, + actTexelView + })); + } + + return undefined; +} + +g.test('inputs,position'). +desc( + ` + Test fragment shader builtin(position) values. + + Note: @builtin(position) is always a fragment position, never a sample position. + ` +). +params((u) => +u // +.combine('nearFar', [[0, 1], [0.25, 0.75]]). +combine('sampleCount', [1, 4]). +combine('interpolation', [ +{ type: 'perspective', sampling: 'center' }, +{ type: 'perspective', sampling: 'centroid' }, +{ type: 'perspective', sampling: 'sample' }, +{ type: 'linear', sampling: 'center' }, +{ type: 'linear', sampling: 'centroid' }, +{ type: 'linear', sampling: 'sample' }, +{ type: 'flat' }] +) +). +beforeAllSubcases((t) => { + const { + interpolation: { type, sampling } + } = t.params; + t.skipIfInterpolationTypeOrSamplingNotSupported({ type, sampling }); +}). +fn(async (t) => { + const { + nearFar, + sampleCount, + interpolation: { type, sampling } + } = t.params; + + const clipSpacePoints = [// ndc values + [0.333, 0.333, 0.333, 0.333], // 1, 1, 1 + [1.0, -3.0, 0.25, 1.0], // 1, -3, 0.25 + [-1.5, 0.5, 0.25, 0.5] // -3, 1, 0.5 + ]; + + const interStagePoints = [ + [1, 2, 3, 4], + [5, 6, 7, 8], + [9, 10, 11, 12]]; + + + const width = 4; + const height = 4; + const actual = await renderFragmentShaderInputsTo4TexturesAndReadbackValues(t, { + interpolationType: type, + interpolationSampling: sampling, + sampleCount, + width, + height, + nearFar, + clipSpacePoints, + interStagePoints, + fragInCode: '', + outputCode: 'fin.position' + }); + + const expected = generateFragmentInputs({ + width, + height, + nearFar, + sampleCount, + clipSpacePoints, + interpolateFn: computeFragmentPosition + }); + + // Since @builtin(position) is always a fragment position, never a sample position, check + // the first coordinate. It should be 0.5, 0.5 always. This is just to double check + // that computeFragmentPosition is generating the correct values. + assert(expected[0] === 0.5); + assert(expected[1] === 0.5); + + t.expectOK( + checkSampleRectsApproximatelyEqual({ + width, + height, + sampleCount, + actual, + expected, + maxDiffULPsForFloatFormat: 4 + }) + ); +}); + +g.test('inputs,interStage'). +desc( + ` + Test fragment shader inter-stage variable values except for centroid interpolation. + ` +). +params((u) => +u // +.combine('nearFar', [[0, 1], [0.25, 0.75]]). +combine('sampleCount', [1, 4]). +combine('interpolation', [ +{ type: 'perspective', sampling: 'center' }, +{ type: 'perspective', sampling: 'sample' }, +{ type: 'linear', sampling: 'center' }, +{ type: 'linear', sampling: 'sample' }, +{ type: 'flat' }] +) +). +beforeAllSubcases((t) => { + const { + interpolation: { type, sampling } + } = t.params; + t.skipIfInterpolationTypeOrSamplingNotSupported({ type, sampling }); +}). +fn(async (t) => { + const { + nearFar, + sampleCount, + interpolation: { type, sampling } + } = t.params; + + const clipSpacePoints = [// ndc values + [0.333, 0.333, 0.333, 0.333], // 1, 1, 1 + [1.0, -3.0, 0.25, 1.0], // 1, -3, 0.25 + [-1.5, 0.5, 0.25, 0.5] // -3, 1, 0.5 + ]; + + const interStagePoints = [ + [1, 2, 3, 4], + [5, 6, 7, 8], + [9, 10, 11, 12]]; + + + const width = 4; + const height = 4; + const actual = await renderFragmentShaderInputsTo4TexturesAndReadbackValues(t, { + interpolationType: type, + interpolationSampling: sampling, + sampleCount, + width, + height, + nearFar, + clipSpacePoints, + interStagePoints, + fragInCode: '', + outputCode: 'fin.interpolatedValue' + }); + + const expected = generateFragmentInputs({ + width, + height, + nearFar, + sampleCount, + clipSpacePoints, + interpolateFn: createInterStageInterpolationFn(interStagePoints, type, sampling) + }); + + t.expectOK( + checkSampleRectsApproximatelyEqual({ + width, + height, + sampleCount, + actual, + expected, + maxDiffULPsForFloatFormat: 4 + }) + ); +}); + +g.test('inputs,interStage,centroid'). +desc( + ` + Test fragment shader inter-stage variable values in centroid sampling mode. + + Centroid sampling mode is trying to solve the following issue + + +-------------+ + |....s1|/ | + |......| | + |...../| s2 | + +------C------+ + |s3./ | | + |../ | | + |./ |s4 | + +-------------+ + + Above is a diagram of a texel where s1, s2, s3, s4 are sample points, + C is the center of the texel and the diagonal line is some edge of + a triangle. s1 and s3 are inside the triangle. In sampling = 'center' + modes, the interpolated value will be relative to C. The problem is, + C is outside of the triangle. In sample = 'centroid' mode, the + interpolated value will be computed relative to some point inside the + portion of the triangle inside the texel. While ideally it would be + the actual centroid, the specs from the various APIs suggest the only + guarantee is it's inside the triangle. + + So, we set the interStage values to barycentric coords. We expect + that when sampling mode is 'center', some interpolated values + will be outside of the triangle (ie, one or more of their values will + be outside the 0 to 1 range). In sampling mode = 'centroid' mode, none + of the values will be outside of the 0 to 1 range. + + Note: generateFragmentInputs below generates "expected". Values not + rendered to will be 0. Values rendered to outside the triangle will + be -1. Values rendered to inside the triangle will be 1. Manually + checking, "expected" for sampling = 'center' should have a couple of + -1 values where as "expected" for sampling = 'centroid' should not. + This was verified with manual testing. + + Since we only care about inside vs outside of the triangle, having + createInterStageInterpolationFn use the interpolated value relative + to the sample point when sampling = 'centroid' will give us a value + inside the triangle, which is good enough for our test. + ` +). +params((u) => +u // +.combine('nearFar', [[0, 1], [0.25, 0.75]]). +combine('sampleCount', [1, 4]). +combine('interpolation', [ +{ type: 'perspective', sampling: 'center' }, +{ type: 'perspective', sampling: 'centroid' }, +{ type: 'linear', sampling: 'center' }, +{ type: 'linear', sampling: 'centroid' }] +) +). +beforeAllSubcases((t) => { + const { + interpolation: { type, sampling } + } = t.params; + t.skipIfInterpolationTypeOrSamplingNotSupported({ type, sampling }); +}). +fn(async (t) => { + const { + nearFar, + sampleCount, + interpolation: { type, sampling } + } = t.params; + // + // We're drawing 1 triangle that cut the viewport + // + // -1 0 1 + // +===+===+ 2 + // |\..|...| + // +---+---+ 1 <--- + // | \|...| | + // +---+---+ 0 | viewport + // | |\..| | + // +---+---+ -1 <--- + // | | \| + // +===+===+ -2 + + + const clipSpacePoints = [// ndc values + [1, -2, 0, 1], + [-1, 2, 0, 1], + [1, 2, 0, 1]]; + + + + const interStagePoints = [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0]]; + + + const width = 4; + const height = 4; + const actual = await renderFragmentShaderInputsTo4TexturesAndReadbackValues(t, { + interpolationType: type, + interpolationSampling: sampling, + sampleCount, + width, + height, + nearFar, + clipSpacePoints, + interStagePoints, + fragInCode: '', + outputCode: + 'vec4f(select(-1.0, 1.0, all(fin.interpolatedValue >= vec4f(0)) && all(fin.interpolatedValue <= vec4f(1))), 0, 0, 0)' + }); + + const expected = generateFragmentInputs({ + width, + height, + nearFar, + sampleCount, + clipSpacePoints, + interpolateFn: createInterStageInterpolationBetween0And1TestFn( + interStagePoints, + type, + sampling + ) + }); + + t.expectOK( + checkSampleRectsApproximatelyEqual({ + width, + height, + sampleCount, + actual, + expected, + maxDiffULPsForFloatFormat: 3 + }) + ); +}); + +g.test('inputs,sample_index'). +desc( + ` + Test fragment shader builtin(sample_index) values. + ` +). +params((u) => +u // +.combine('nearFar', [[0, 1], [0.25, 0.75]]). +combine('sampleCount', [1, 4]). +combine('interpolation', [ +{ type: 'perspective', sampling: 'center' }, +{ type: 'perspective', sampling: 'centroid' }, +{ type: 'perspective', sampling: 'sample' }, +{ type: 'linear', sampling: 'center' }, +{ type: 'linear', sampling: 'centroid' }, +{ type: 'linear', sampling: 'sample' }, +{ type: 'flat' }] +) +). +beforeAllSubcases((t) => { + t.skipIf(t.isCompatibility, 'sample_index is not supported in compatibility mode'); +}). +fn(async (t) => { + const { + nearFar, + sampleCount, + interpolation: { type, sampling } + } = t.params; + + const clipSpacePoints = [// ndc values + [0.333, 0.333, 0.333, 0.333], // 1, 1, 1 + [1.0, -3.0, 0.25, 1.0], // 1, -3, 0.25 + [-1.5, 0.5, 0.25, 0.5] // -3, 1, 0.5 + ]; + + const interStagePoints = [ + [1, 2, 3, 4], + [5, 6, 7, 8], + [9, 10, 11, 12]]; + + + const width = 4; + const height = 4; + const actual = await renderFragmentShaderInputsTo4TexturesAndReadbackValues(t, { + interpolationType: type, + interpolationSampling: sampling, + sampleCount, + width, + height, + nearFar, + clipSpacePoints, + interStagePoints, + fragInCode: `@builtin(sample_index) sampleIndex: u32,`, + outputCode: 'vec4f(f32(fin.sampleIndex), 0, 0, 0)' + }); + + const expected = generateFragmentInputs({ + width, + height, + nearFar, + sampleCount, + clipSpacePoints, + interpolateFn: computeFragmentSampleIndex + }); + + t.expectOK( + checkSampleRectsApproximatelyEqual({ + width, + height, + sampleCount, + actual, + expected, + maxDiffULPsForFloatFormat: 1 + }) + ); +}); + +g.test('inputs,front_facing'). +desc( + ` + Test fragment shader builtin(front_facing) values. + + Draws a quad from 2 triangles that entirely cover clip space. (see diagram below in code) + One triangle is clockwise, the other is counter clockwise. The triangles + bisect pixels so that different samples are covered by each triangle so that some + samples should get different values for front_facing for the same fragment. + ` +). +params((u) => +u // +.combine('nearFar', [[0, 1], [0.25, 0.75]]). +combine('sampleCount', [1, 4]). +combine('frontFace', ['cw', 'ccw']). +combine('interpolation', [ +{ type: 'perspective', sampling: 'center' }, +{ type: 'perspective', sampling: 'centroid' }, +{ type: 'perspective', sampling: 'sample' }, +{ type: 'linear', sampling: 'center' }, +{ type: 'linear', sampling: 'centroid' }, +{ type: 'linear', sampling: 'sample' }, +{ type: 'flat' }] +) +). +beforeAllSubcases((t) => { + const { + interpolation: { type, sampling } + } = t.params; + t.skipIfInterpolationTypeOrSamplingNotSupported({ type, sampling }); +}). +fn(async (t) => { + const { + nearFar, + sampleCount, + frontFace, + interpolation: { type, sampling } + } = t.params; + // + // We're drawing 2 triangles starting at y = -2 to y = +2 + // + // -1 0 1 + // +===+===+ 2 + // |\ | | + // +---+---+ 1 <--- + // | \| | | + // +---+---+ 0 | viewport + // | |\ | | + // +---+---+ -1 <--- + // | | \| + // +===+===+ -2 + + + const clipSpacePoints = [ + // ccw + [-1, -2, 0, 1], + [1, -2, 0, 1], + [-1, 2, 0, 1], + + // cw + [1, -2, 0, 1], + [-1, 2, 0, 1], + [1, 2, 0, 1]]; + + + const interStagePoints = [ + [1, 2, 3, 4], + [5, 6, 7, 8], + [9, 10, 11, 12], + + [13, 14, 15, 16], + [17, 18, 19, 20], + [21, 22, 23, 24]]; + + + const width = 4; + const height = 4; + const actual = await renderFragmentShaderInputsTo4TexturesAndReadbackValues(t, { + interpolationType: type, + interpolationSampling: sampling, + frontFace, + sampleCount, + width, + height, + nearFar, + clipSpacePoints, + interStagePoints, + fragInCode: '@builtin(front_facing) frontFacing: bool,', + outputCode: 'vec4f(select(0.0, 1.0, fin.frontFacing), 0, 0, 0)' + }); + + const expected = generateFragmentInputs({ + width, + height, + nearFar, + sampleCount, + clipSpacePoints, + frontFace, + interpolateFn: computeFragmentFrontFacing + }); + + assert(expected.indexOf(0) >= 0, 'expect some values to be 0'); + assert(expected.findIndex((v) => v !== 0) >= 0, 'expect some values to be non 0'); + + t.expectOK( + checkSampleRectsApproximatelyEqual({ + width, + height, + sampleCount, + actual, + expected, + maxDiffULPsForFloatFormat: 0 + }) + ); +}); + +g.test('inputs,sample_mask'). +desc( + ` + Test fragment shader builtin(sample_mask) values. + + Draws various triangles that should trigger different sample_mask values. + Checks that sample_mask matches what's expected. Note: the triangles + are selected so they do not intersect sample points as we don't want + to test precision issues on whether or not a sample point is inside + or outside the triangle when right on the edge. + + Example: x=-1, y=2, it draws the following triangle + + [ -0.8, -2 ] + [ 1.2, 2 ] + [ -0.8, 2 ] + + On to a 4x4 pixel texture + + -0.8, 2 + .----------------------. 1.2 2 + |...................../ + |..................../ + |.................../ + |................../ + |................./ + +-|---+-----+-----+/----+ --- + | |...|.....|...../ | ^ + | |...|.....|..../| | | + +-|---+-----+---/-+-----+ | + | |...|.....|../ | | | + | |...|.....|./ | | | + +-|---+-----+/----+-----+ texture / clip space + | |...|...../ | | | + | |...|..../| | | | + +-|---+---/-+-----+-----+ | + | |...|../ | | | | + | |...|./ | | | V + +-|---+/----+-----+-----+ --- + |.../ + |../ + |./ + |/ + / + . + -0.8, -2 + + Inside an individual pixel you might see this situation + + +-------------+ + |....s1|/ | + |......| | + |...../| s2 | + +------C------+ + |s3./ | | + |../ | | + |./ |s4 | + +-------------+ + + where s1, s2, s3, s4, are sample points and C is the center. For a sampleCount = 4 texture + the sample_mask is expected to emit sample_mask = 0b0101 + + ref: https://learn.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels + ` +). +params((u) => +u // +.combine('nearFar', [[0, 1], [0.25, 0.75]]). +combine('sampleCount', [1, 4]). +combine('interpolation', [ +// given that 'sample' effects whether things are run per-sample or per-fragment +// we test all of these to make sure they don't affect the result differently than expected. +{ type: 'perspective', sampling: 'center' }, +{ type: 'perspective', sampling: 'centroid' }, +{ type: 'perspective', sampling: 'sample' }, +{ type: 'linear', sampling: 'center' }, +{ type: 'linear', sampling: 'centroid' }, +{ type: 'linear', sampling: 'sample' }, +{ type: 'flat' }] +). +beginSubcases(). +combineWithParams([ +{ x: -1, y: -1 }, +{ x: -1, y: -2 }, +{ x: -1, y: 1 }, +{ x: -1, y: 3 }, +{ x: -2, y: -1 }, +{ x: -2, y: 3 }, +{ x: -3, y: -1 }, +{ x: -3, y: -2 }, +{ x: -3, y: 1 }, +{ x: 1, y: -1 }, +{ x: 1, y: -3 }, +{ x: 1, y: 1 }, +{ x: 1, y: 2 }, +{ x: 2, y: -2 }, +{ x: 2, y: -3 }, +{ x: 2, y: 1 }, +{ x: 2, y: 2 }, +{ x: 3, y: -1 }, +{ x: 3, y: -3 }, +{ x: 3, y: 1 }, +{ x: 3, y: 2 }, +{ x: 3, y: 3 }] +) +). +beforeAllSubcases((t) => { + const { + interpolation: { type, sampling } + } = t.params; + t.skipIfInterpolationTypeOrSamplingNotSupported({ type, sampling }); +}). +fn(async (t) => { + const { + x, + y, + nearFar, + sampleCount, + interpolation: { type, sampling } + } = t.params; + + const clipSpacePoints = [ + [x + 0.2, -y, 0, 1], + [-x + 0.2, y, 0, 1], + [x + 0.2, y, 0, 1]]; + + + const interStagePoints = [ + [13, 14, 15, 16], + [17, 18, 19, 20], + [21, 22, 23, 24]]; + + + const width = 4; + const height = 4; + const actual = await renderFragmentShaderInputsTo4TexturesAndReadbackValues(t, { + interpolationType: type, + interpolationSampling: sampling, + sampleCount, + width, + height, + nearFar, + clipSpacePoints, + interStagePoints, + fragInCode: '@builtin(sample_mask) sample_mask: u32,', + outputCode: 'vec4f(f32(fin.sample_mask), 0, 0, 0)' + }); + + const expected = generateFragmentInputs({ + width, + height, + nearFar, + sampleCount, + clipSpacePoints, + interpolateFn: computeSampleMask + }); + + t.expectOK( + checkSampleRectsApproximatelyEqual({ + width, + height, + sampleCount, + actual, + expected, + maxDiffULPsForFloatFormat: 0 + }) + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/user_io.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/user_io.spec.js new file mode 100644 index 0000000000..3651507e4e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/user_io.spec.js @@ -0,0 +1,213 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Test for user-defined shader I/O. + +passthrough: + * Data passed into vertex shader as uints and converted to test type + * Passed from vertex to fragment as test type + * Output from fragment shader as uint +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { range } from '../../../../common/util/util.js'; +import { GPUTest } from '../../../gpu_test.js'; + +export const g = makeTestGroup(GPUTest); + +function generateInterstagePassthroughCode(type) { + return ` +${type === 'f16' ? 'enable f16;' : ''} +struct IOData { + @builtin(position) pos : vec4f, + @location(0) @interpolate(flat) user0 : ${type}, + @location(1) @interpolate(flat) user1 : vec2<${type}>, + @location(2) @interpolate(flat) user2 : vec4<${type}>, +} + +struct VertexInput { + @builtin(vertex_index) idx : u32, + @location(0) in0 : u32, + @location(1) in1 : vec2u, + @location(2) in2 : vec4u, +} + +@vertex +fn vsMain(input : VertexInput) -> IOData { + const vertices = array( + vec4f(-1, -1, 0, 1), + vec4f(-1, 1, 0, 1), + vec4f( 1, -1, 0, 1), + ); + var data : IOData; + data.pos = vertices[input.idx]; + data.user0 = ${type}(input.in0); + data.user1 = vec2<${type}>(input.in1); + data.user2 = vec4<${type}>(input.in2); + return data; +} + +struct FragOutput { + @location(0) out0 : u32, + @location(1) out1 : vec2u, + @location(2) out2 : vec4u, +} + +@fragment +fn fsMain(input : IOData) -> FragOutput { + var out : FragOutput; + out.out0 = u32(input.user0); + out.out1 = vec2u(input.user1); + out.out2 = vec4u(input.user2); + return out; +} +`; +} + +function drawPassthrough(t, code) { + // Default limit is 32 bytes of color attachments. + // These attachments use 28 bytes (which is why vec3 is skipped). + const formats = ['r32uint', 'rg32uint', 'rgba32uint']; + const components = [1, 2, 4]; + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: t.device.createShaderModule({ code }), + entryPoint: 'vsMain', + buffers: [ + { + arrayStride: 4, + attributes: [ + { + format: 'uint32', + offset: 0, + shaderLocation: 0 + }] + + }, + { + arrayStride: 8, + attributes: [ + { + format: 'uint32x2', + offset: 0, + shaderLocation: 1 + }] + + }, + { + arrayStride: 16, + attributes: [ + { + format: 'uint32x4', + offset: 0, + shaderLocation: 2 + }] + + }] + + }, + fragment: { + module: t.device.createShaderModule({ code }), + entryPoint: 'fsMain', + targets: formats.map((x) => { + return { format: x }; + }) + }, + primitive: { + topology: 'triangle-list' + } + }); + + const vertexBuffer = t.makeBufferWithContents( + new Uint32Array([ + // scalar: offset 0 + 1, 1, 1, 0, + // vec2: offset 16 + 2, 2, 2, 2, 2, 2, 0, 0, + // vec4: offset 48 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3] + ), + GPUBufferUsage.COPY_SRC | GPUBufferUsage.VERTEX + ); + + const bytesPerComponent = 4; + // 256 is the minimum bytes per row for texture to buffer copies. + const width = 256 / bytesPerComponent; + const height = 2; + const copyWidth = 4; + const outputTextures = range(3, (i) => { + const texture = t.device.createTexture({ + size: [width, height], + usage: + GPUTextureUsage.COPY_SRC | + GPUTextureUsage.RENDER_ATTACHMENT | + GPUTextureUsage.TEXTURE_BINDING, + format: formats[i] + }); + t.trackForCleanup(texture); + return texture; + }); + + let bufferSize = 1; + for (const comp of components) { + bufferSize *= comp; + } + bufferSize *= outputTextures.length * bytesPerComponent * copyWidth; + const outputBuffer = t.device.createBuffer({ + size: bufferSize, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + }); + t.trackForCleanup(outputBuffer); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ + colorAttachments: outputTextures.map((t) => ({ + view: t.createView(), + loadOp: 'clear', + storeOp: 'store' + })) + }); + pass.setPipeline(pipeline); + pass.setVertexBuffer(0, vertexBuffer, 0, 12); + pass.setVertexBuffer(1, vertexBuffer, 16, 24); + pass.setVertexBuffer(2, vertexBuffer, 48, 48); + pass.draw(3); + pass.end(); + + // Copy 'copyWidth' samples from each attachment into a buffer to check the results. + let offset = 0; + let expectArray = []; + for (let i = 0; i < outputTextures.length; i++) { + encoder.copyTextureToBuffer( + { texture: outputTextures[i] }, + { + buffer: outputBuffer, + offset, + bytesPerRow: bytesPerComponent * components[i] * width, + rowsPerImage: height + }, + { width: copyWidth, height: 1 } + ); + offset += components[i] * bytesPerComponent * copyWidth; + for (let j = 0; j < components[i]; j++) { + const value = i + 1; + expectArray = expectArray.concat([value, value, value, value]); + } + } + t.queue.submit([encoder.finish()]); + + const expect = new Uint32Array(expectArray); + t.expectGPUBufferValuesEqual(outputBuffer, expect); +} + +g.test('passthrough'). +desc('Tests passing user-defined data from vertex input through fragment output'). +params((u) => u.combine('type', ['f32', 'f16', 'i32', 'u32'])). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const code = generateInterstagePassthroughCode(t.params.type); + drawPassthrough(t, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/workgroup_size.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/workgroup_size.spec.js new file mode 100644 index 0000000000..a683d35272 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/workgroup_size.spec.js @@ -0,0 +1,150 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Test that workgroup size is set correctly`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { iterRange } from '../../../../common/util/util.js'; +import { GPUTest } from '../../../gpu_test.js'; + +export const g = makeTestGroup(GPUTest); + +function checkResults( +sizeX, +sizeY, +sizeZ, +numWGs, +data) +{ + const totalInvocations = sizeX * sizeY * sizeZ; + for (let i = 0; i < numWGs; i++) { + const wgx_data = data[4 * i + 0]; + const wgy_data = data[4 * i + 1]; + const wgz_data = data[4 * i + 2]; + const total_data = data[4 * i + 3]; + if (wgx_data !== sizeX) { + let msg = `Incorrect workgroup size x dimension for wg ${i}:\n`; + msg += `- expected: ${wgx_data}\n`; + msg += `- got: ${sizeX}`; + return Error(msg); + } + if (wgy_data !== sizeY) { + let msg = `Incorrect workgroup size y dimension for wg ${i}:\n`; + msg += `- expected: ${wgy_data}\n`; + msg += `- got: ${sizeY}`; + return Error(msg); + } + if (wgz_data !== sizeZ) { + let msg = `Incorrect workgroup size y dimension for wg ${i}:\n`; + msg += `- expected: ${wgz_data}\n`; + msg += `- got: ${sizeZ}`; + return Error(msg); + } + if (total_data !== totalInvocations) { + let msg = `Incorrect workgroup total invocations for wg ${i}:\n`; + msg += `- expected: ${total_data}\n`; + msg += `- got: ${totalInvocations}`; + return Error(msg); + } + } + return undefined; +} + +g.test('workgroup_size'). +desc(`Test workgroup size is set correctly`). +params((u) => +u. +combine('wgx', [1, 3, 4, 8, 11, 16, 51, 64, 128, 256]). +combine('wgy', [1, 3, 4, 8, 16, 51, 64, 256]). +combine('wgz', [1, 3, 11, 16, 128, 256]). +beginSubcases() +). +fn(async (t) => { + const { + maxComputeWorkgroupSizeX, + maxComputeWorkgroupSizeY, + maxComputeWorkgroupSizeZ, + maxComputeInvocationsPerWorkgroup + } = t.device.limits; + t.skipIf( + t.params.wgx > maxComputeWorkgroupSizeX, + `workgroup size x: ${t.params.wgx} > limit: ${maxComputeWorkgroupSizeX}` + ); + t.skipIf( + t.params.wgy > maxComputeWorkgroupSizeY, + `workgroup size x: ${t.params.wgy} > limit: ${maxComputeWorkgroupSizeY}` + ); + t.skipIf( + t.params.wgz > maxComputeWorkgroupSizeZ, + `workgroup size x: ${t.params.wgz} > limit: ${maxComputeWorkgroupSizeZ}` + ); + const totalInvocations = t.params.wgx * t.params.wgy * t.params.wgz; + t.skipIf( + totalInvocations > maxComputeInvocationsPerWorkgroup, + `workgroup size: ${totalInvocations} > limit: ${maxComputeInvocationsPerWorkgroup}` + ); + + const code = ` +struct Values { + x : atomic, + y : atomic, + z : atomic, + total : atomic, +} + +@group(0) @binding(0) +var v : array; + +@compute @workgroup_size(${t.params.wgx}, ${t.params.wgy}, ${t.params.wgz}) +fn main(@builtin(local_invocation_id) lid : vec3u, + @builtin(workgroup_id) wgid : vec3u) { + atomicMax(&v[wgid.x].x, lid.x + 1); + atomicMax(&v[wgid.x].y, lid.y + 1); + atomicMax(&v[wgid.x].z, lid.z + 1); + atomicAdd(&v[wgid.x].total, 1); +}`; + + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ + code + }), + entryPoint: 'main' + } + }); + + const numWorkgroups = totalInvocations < 256 ? 5 : 3; + const buffer = t.makeBufferWithContents( + new Uint32Array([...iterRange(numWorkgroups * 4, (_i) => 0)]), + GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + ); + t.trackForCleanup(buffer); + + const bg = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: { + buffer + } + }] + + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bg); + pass.dispatchWorkgroups(numWorkgroups, 1, 1); + pass.end(); + t.queue.submit([encoder.finish()]); + + const bufferReadback = await t.readGPUBufferRangeTyped(buffer, { + srcByteOffset: 0, + type: Uint32Array, + typedLength: 4 * numWorkgroups, + method: 'copy' + }); + const data = bufferReadback.data; + + t.expectOK(checkResults(t.params.wgx, t.params.wgy, t.params.wgz, numWorkgroups, data)); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/stage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/stage.spec.js new file mode 100644 index 0000000000..df09954c3f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/stage.spec.js @@ -0,0 +1,133 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Test trivial shaders for each shader stage kind`; // There are many many more shaders executed in other tests. + +import { makeTestGroup } from '../../../common/framework/test_group.js'; +import { GPUTest } from '../../gpu_test.js'; +import { checkElementsEqual } from '../../util/check_contents.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('basic_compute'). +desc(`Test a trivial compute shader`). +fn(async (t) => { + const code = ` + +@group(0) @binding(0) +var v : vec4u; + +@compute @workgroup_size(1) +fn main() { + v = vec4u(1,2,3,42); +}`; + + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ + code + }), + entryPoint: 'main' + } + }); + + const buffer = t.makeBufferWithContents( + new Uint32Array([0, 0, 0, 0]), + GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + ); + t.trackForCleanup(buffer); + + const bg = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: { + buffer + } + }] + + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bg); + pass.dispatchWorkgroups(1, 1, 1); + pass.end(); + t.queue.submit([encoder.finish()]); + + const bufferReadback = await t.readGPUBufferRangeTyped(buffer, { + srcByteOffset: 0, + type: Uint32Array, + typedLength: 4, + method: 'copy' + }); + const got = bufferReadback.data; + const expected = new Uint32Array([1, 2, 3, 42]); + + t.expectOK(checkElementsEqual(got, expected)); +}); + +g.test('basic_render'). +desc(`Test trivial vertex and fragment shaders`). +fn((t) => { + const code = ` +@vertex +fn vert_main(@builtin(vertex_index) idx: u32) -> @builtin(position) vec4f { + // A right triangle covering the whole framebuffer. + const pos = array( + vec2f(-1,-3), + vec2f(3,1), + vec2f(-1,1)); + return vec4f(pos[idx], 0, 1); +} + +@fragment +fn frag_main() -> @location(0) vec4f { + return vec4(0, 1, 0, 1); // green +} +`; + const module = t.device.createShaderModule({ code }); + + const [width, height] = [8, 8]; + const format = 'rgba8unorm'; + const texture = t.device.createTexture({ + size: { width, height }, + usage: + GPUTextureUsage.RENDER_ATTACHMENT | + GPUTextureUsage.TEXTURE_BINDING | + GPUTextureUsage.COPY_SRC, + format + }); + + // We'll copy one pixel only. + const dst = t.device.createBuffer({ + size: 4, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + }); + + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { module, entryPoint: 'vert_main' }, + fragment: { module, entryPoint: 'frag_main', targets: [{ format }] } + }); + + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ + colorAttachments: [{ view: texture.createView(), loadOp: 'clear', storeOp: 'store' }] + }); + pass.setPipeline(pipeline); + pass.draw(3); + pass.end(); + + encoder.copyTextureToBuffer( + { texture, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } }, + { buffer: dst, bytesPerRow: 256 }, + { width: 1, height: 1, depthOrArrayLayers: 1 } + ); + t.queue.submit([encoder.finish()]); + + // Expect one green pixel. + t.expectGPUBufferValuesEqual(dst, new Uint8Array([0x00, 0xff, 0x00, 0xff])); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/statement/compound.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/statement/compound.spec.js new file mode 100644 index 0000000000..0c7f0edcae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/statement/compound.spec.js @@ -0,0 +1,137 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Compound statement execution. +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; + +import { GPUTest } from '../../../gpu_test.js'; + +export const g = makeTestGroup(GPUTest); + +/** + * Builds, runs then checks the output of a statement shader test. + * + * @param t The test object + * @param ty The WGSL scalar type to be written + * @param values The expected output values of type ty + * @param wgsl_main The body of the WGSL entry point. + */ +export function runStatementTest( +t, +ty, +values, +wgsl_main) +{ + const wgsl = ` +struct Outputs { + data : array<${ty}>, +}; +var count: u32 = 0; + +@group(0) @binding(1) var outputs : Outputs; + +fn put(value : ${ty}) { + outputs.data[count] = value; + count += 1; +} + +@compute @workgroup_size(1) +fn main() { + _ = &outputs; + ${wgsl_main} +} +`; + + const pipeline = t.device.createComputePipeline({ + layout: 'auto', + compute: { + module: t.device.createShaderModule({ code: wgsl }), + entryPoint: 'main' + } + }); + + const maxOutputValues = 1000; + const outputBuffer = t.device.createBuffer({ + size: 4 * (1 + maxOutputValues), + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC + }); + + const bindGroup = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [{ binding: 1, resource: { buffer: outputBuffer } }] + }); + + // Run the shader. + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bindGroup); + pass.dispatchWorkgroups(1); + pass.end(); + t.queue.submit([encoder.finish()]); + + t.expectGPUBufferValuesEqual(outputBuffer, values); +} + +// Consider a declaration X of identifier 'x' inside a compound statement. +// Check the value of 'x' at various places relative to X: +// a { b; X=c; d; { e; } } f; + +const kTests = { + uses: { + // Observe values without conflicting declarations. + src: `let x = 1; + put(x); + { + put(x); + let x = x+1; // The declaration in question + put(x); + { + put(x); + } + put(x); + } + put(x);`, + values: [1, 1, 2, 2, 2, 1] + }, + shadowed: { + // Observe values when shadowed + src: `let x = 1; + put(x); + { + put(x); + let x = x+1; // The declaration in question + put(x); + { + let x = x+1; // A shadow + put(x); + } + put(x); + } + put(x);`, + values: [1, 1, 2, 3, 2, 1] + }, + gone: { + // The declaration goes out of scope. + src: `{ + let x = 2; // The declaration in question + put(x); + } + let x = 1; + put(x);`, + values: [2, 1] + } +}; + +g.test('decl'). +desc('Tests the value of a declared value in a compound statment.'). +params((u) => u.combine('case', keysOf(kTests))). +fn((t) => { + runStatementTest( + t, + 'i32', + new Int32Array(kTests[t.params.case].values), + kTests[t.params.case].src + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/statement/discard.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/statement/discard.spec.js new file mode 100644 index 0000000000..bcd4fd9e52 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/statement/discard.spec.js @@ -0,0 +1,645 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Execution tests for discard. + +The discard statement converts invocations into helpers. +This results in the following conditions: + * No outputs are written + * No resources are written + * Atomics are undefined + +Conditions that still occur: + * Derivative calculations are correct + * Reads + * Writes to non-external memory +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { iterRange } from '../../../../common/util/util.js'; +import { GPUTest } from '../../../gpu_test.js'; +import { checkElementsPassPredicate } from '../../../util/check_contents.js'; + +export const g = makeTestGroup(GPUTest); + +// Framebuffer dimensions +const kWidth = 64; +const kHeight = 64; + +const kSharedCode = ` +@group(0) @binding(0) var output: array; +@group(0) @binding(1) var atomicIndex : atomic; +@group(0) @binding(2) var uniformValues : array; + +@vertex +fn vsMain(@builtin(vertex_index) index : u32) -> @builtin(position) vec4f { + const vertices = array( + vec2(-1, -1), vec2(-1, 0), vec2( 0, -1), + vec2(-1, 0), vec2( 0, 0), vec2( 0, -1), + + vec2( 0, -1), vec2( 0, 0), vec2( 1, -1), + vec2( 0, 0), vec2( 1, 0), vec2( 1, -1), + + vec2(-1, 0), vec2(-1, 1), vec2( 0, 0), + vec2(-1, 1), vec2( 0, 1), vec2( 0, 0), + + vec2( 0, 0), vec2( 0, 1), vec2( 1, 0), + vec2( 0, 1), vec2( 1, 1), vec2( 1, 0), + ); + return vec4f(vec2f(vertices[index]), 0, 1); +} +`; + +function drawFullScreen( +t, +code, +dataChecker, +framebufferChecker) +{ + const pipeline = t.device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: t.device.createShaderModule({ code }), + entryPoint: 'vsMain' + }, + fragment: { + module: t.device.createShaderModule({ code }), + entryPoint: 'fsMain', + targets: [{ format: 'r32uint' }] + }, + primitive: { + topology: 'triangle-list' + } + }); + + const bytesPerWord = 4; + const framebuffer = t.device.createTexture({ + size: [kWidth, kHeight], + usage: + GPUTextureUsage.COPY_SRC | + GPUTextureUsage.COPY_DST | + GPUTextureUsage.RENDER_ATTACHMENT | + GPUTextureUsage.TEXTURE_BINDING, + format: 'r32uint' + }); + t.trackForCleanup(framebuffer); + + // Create a buffer to copy the framebuffer contents into. + // Initialize with a sentinel value and load this buffer to detect unintended writes. + const fbBuffer = t.makeBufferWithContents( + new Uint32Array([...iterRange(kWidth * kHeight, (x) => kWidth * kHeight)]), + GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + ); + + // Create a buffer to hold the storage shader resources. + // (0,0) = vec2u width * height + // (0,1) = u32 + const dataSize = 2 * kWidth * kHeight * bytesPerWord; + const dataBufferSize = dataSize + bytesPerWord; + const dataBuffer = t.device.createBuffer({ + size: dataBufferSize, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE + }); + + const uniformSize = bytesPerWord * 5; + const uniformBuffer = t.makeBufferWithContents( + // Loop bound, [derivative constants]. + new Uint32Array([4, 1, 4, 4, 7]), + GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE + ); + + // 'atomicIndex' packed at the end of the buffer. + const bg = t.device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: { + buffer: dataBuffer, + offset: 0, + size: dataSize + } + }, + { + binding: 1, + resource: { + buffer: dataBuffer, + offset: dataSize, + size: bytesPerWord + } + }, + { + binding: 2, + resource: { + buffer: uniformBuffer, + offset: 0, + size: uniformSize + } + }] + + }); + + const encoder = t.device.createCommandEncoder(); + encoder.copyBufferToTexture( + { + buffer: fbBuffer, + offset: 0, + bytesPerRow: kWidth * bytesPerWord, + rowsPerImage: kHeight + }, + { texture: framebuffer }, + { width: kWidth, height: kHeight } + ); + const pass = encoder.beginRenderPass({ + colorAttachments: [ + { + view: framebuffer.createView(), + loadOp: 'load', + storeOp: 'store' + }] + + }); + pass.setPipeline(pipeline); + pass.setBindGroup(0, bg); + pass.draw(24); + pass.end(); + encoder.copyTextureToBuffer( + { texture: framebuffer }, + { + buffer: fbBuffer, + offset: 0, + bytesPerRow: kWidth * bytesPerWord, + rowsPerImage: kHeight + }, + { width: kWidth, height: kHeight } + ); + t.queue.submit([encoder.finish()]); + + t.expectGPUBufferValuesPassCheck(dataBuffer, dataChecker, { + type: Float32Array, + typedLength: dataSize / bytesPerWord + }); + + t.expectGPUBufferValuesPassCheck(fbBuffer, framebufferChecker, { + type: Uint32Array, + typedLength: kWidth * kHeight + }); +} + +g.test('all'). +desc('Test a shader that discards all fragments'). +fn((t) => { + const code = ` +${kSharedCode} + +@fragment +fn fsMain(@builtin(position) pos : vec4f) -> @location(0) u32 { + _ = uniformValues[0]; + discard; + let idx = atomicAdd(&atomicIndex, 1); + output[idx] = pos.xy; + return 1; +} +`; + + // No storage writes occur. + const dataChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + return value === 0; + }, + { + predicatePrinter: [ + { + leftHeader: 'data exp ==', + getValueForCell: (idx) => { + return 0; + } + }] + + } + ); + }; + + // No fragment outputs occur. + const fbChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + return value === kWidth * kHeight; + }, + { + predicatePrinter: [ + { + leftHeader: 'fb exp ==', + getValueForCell: (idx) => { + return 0; + } + }] + + } + ); + }; + + drawFullScreen(t, code, dataChecker, fbChecker); +}); + +g.test('three_quarters'). +desc('Test a shader that discards all but the upper-left quadrant fragments'). +fn((t) => { + const code = ` +${kSharedCode} + +@fragment +fn fsMain(@builtin(position) pos : vec4f) -> @location(0) u32 { + _ = uniformValues[0]; + if (pos.x >= 0.5 * ${kWidth} || pos.y >= 0.5 * ${kHeight}) { + discard; + } + let idx = atomicAdd(&atomicIndex, 1); + output[idx] = pos.xy; + return idx; +} +`; + + // Only the the upper left quadrant is kept. + const dataChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + const is_x = idx % 2 === 0; + if (is_x) { + return value < 0.5 * kWidth; + } else { + return value < 0.5 * kHeight; + } + }, + { + predicatePrinter: [ + { + leftHeader: 'data exp ==', + getValueForCell: (idx) => { + const is_x = idx % 2 === 0; + if (is_x) { + const x = Math.floor(idx / 2) % kWidth; + if (x >= kWidth / 2) { + return 0; + } + } else { + const y = Math.floor((idx - 1) / kWidth); + if (y >= kHeight / 2) { + return 0; + } + } + if (is_x) { + return `< ${0.5 * kWidth}`; + } else { + return `< ${0.5 * kHeight}`; + } + } + }] + + } + ); + }; + const fbChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + const x = idx % kWidth; + const y = Math.floor(idx / kWidth); + if (x < kWidth / 2 && y < kHeight / 2) { + return value < kWidth * kHeight / 4; + } else { + return value === kWidth * kHeight; + } + return value < kWidth * kHeight / 4; + }, + { + predicatePrinter: [ + { + leftHeader: 'fb exp ==', + getValueForCell: (idx) => { + const x = idx % kWidth; + const y = Math.floor(idx / kWidth); + if (x < kWidth / 2 && y < kHeight / 2) { + return 'any'; + } else { + return 0; + } + } + }] + + } + ); + }; + + drawFullScreen(t, code, dataChecker, fbChecker); +}); + +g.test('function_call'). +desc('Test discards happening in a function call'). +fn((t) => { + const code = ` +${kSharedCode} + +fn foo(pos : vec2f) { + let p = vec2i(pos); + if p.x <= ${kWidth} / 2 && p.y <= ${kHeight} / 2 { + discard; + } + if p.x >= ${kWidth} / 2 && p.y >= ${kHeight} / 2 { + discard; + } +} + +@fragment +fn fsMain(@builtin(position) pos : vec4f) -> @location(0) u32 { + _ = uniformValues[0]; + foo(pos.xy); + let idx = atomicAdd(&atomicIndex, 1); + output[idx] = pos.xy; + return idx; +} +`; + + // Only the upper right and bottom left quadrants are kept. + const dataChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + const is_x = idx % 2 === 0; + if (value === 0.0) { + return is_x ? a[idx + 1] === 0 : a[idx - 1] === 0; + } + + let expect = is_x ? kWidth : kHeight; + expect = 0.5 * expect; + if (value < expect) { + return is_x ? a[idx + 1] > 0.5 * kWidth : a[idx - 1] > 0.5 * kHeight; + } else { + return is_x ? a[idx + 1] < 0.5 * kWidth : a[idx - 1] < 0.5 * kHeight; + } + }, + { + predicatePrinter: [ + { + leftHeader: 'data exp ==', + getValueForCell: (idx) => { + if (idx < kWidth * kHeight / 2) { + return 'any'; + } else { + return 0; + } + } + }] + + } + ); + }; + const fbChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + const x = idx % kWidth; + const y = Math.floor(idx / kWidth); + if (x >= kWidth / 2 && y >= kHeight / 2 || x <= kWidth / 2 && y <= kHeight / 2) { + return value === kWidth * kHeight; + } else { + return value < kWidth * kHeight / 2; + } + }, + { + predicatePrinter: [ + { + leftHeader: 'fb exp ==', + getValueForCell: (idx) => { + const x = idx % kWidth; + const y = Math.floor(idx / kWidth); + if ( + x <= kWidth / 2 && y <= kHeight / 2 || + x >= kWidth / 2 && y >= kHeight / 2) + { + return kWidth * kHeight; + } + return 'any'; + } + }] + + } + ); + }; + + drawFullScreen(t, code, dataChecker, fbChecker); +}); + +g.test('loop'). +desc('Test discards in a loop'). +fn((t) => { + const code = ` +${kSharedCode} + +@fragment +fn fsMain(@builtin(position) pos : vec4f) -> @location(0) u32 { + _ = uniformValues[0]; + for (var i = 0; i < 2; i++) { + if i > 0 { + discard; + } + } + let idx = atomicAdd(&atomicIndex, 1); + output[idx] = pos.xy; + return 1; +} +`; + + // No storage writes occur. + const dataChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + return value === 0; + }, + { + predicatePrinter: [ + { + leftHeader: 'data exp ==', + getValueForCell: (idx) => { + return 0; + } + }] + + } + ); + }; + + // No fragment outputs occur. + const fbChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + return value === kWidth * kHeight; + }, + { + predicatePrinter: [ + { + leftHeader: 'fb exp ==', + getValueForCell: (idx) => { + return kWidth * kHeight; + } + }] + + } + ); + }; + + drawFullScreen(t, code, dataChecker, fbChecker); +}); + +g.test('uniform_read_loop'). +desc('Test that helpers read a uniform value in a loop'). +fn((t) => { + const code = ` +${kSharedCode} + +@fragment +fn fsMain(@builtin(position) pos : vec4f) -> @location(0) u32 { + discard; + for (var i = 0u; i < uniformValues[0]; i++) { + } + let idx = atomicAdd(&atomicIndex, 1); + output[idx] = pos.xy; + return 1; +} +`; + + // No storage writes occur. + const dataChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + return value === 0; + }, + { + predicatePrinter: [ + { + leftHeader: 'data exp ==', + getValueForCell: (idx) => { + return 0; + } + }] + + } + ); + }; + + // No fragment outputs occur. + const fbChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + return value === kWidth * kHeight; + }, + { + predicatePrinter: [ + { + leftHeader: 'fb exp ==', + getValueForCell: (idx) => { + return kWidth * kHeight; + } + }] + + } + ); + }; + + drawFullScreen(t, code, dataChecker, fbChecker); +}); + +g.test('derivatives'). +desc('Test that derivatives are correct in the presence of discard'). +fn((t) => { + const code = ` +${kSharedCode} + +@fragment +fn fsMain(@builtin(position) pos : vec4f) -> @location(0) u32 { + let ipos = vec2i(pos.xy); + let lsb = ipos & vec2(0x1); + let left_sel = select(2, 4, lsb.y == 1); + let right_sel = select(1, 3, lsb.y == 1); + let uidx = select(left_sel, right_sel, lsb.x == 1); + if ((lsb.x | lsb.y) & 0x1) == 0 { + discard; + } + + let v = uniformValues[uidx]; + let idx = atomicAdd(&atomicIndex, 1); + let dx = dpdx(f32(v)); + let dy = dpdy(f32(v)); + output[idx] = vec2(dx, dy); + return idx; +} +`; + + // One pixel per quad is discarded. The derivatives values are always the same +/- 3. + const dataChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + if (idx < 3 * (2 * kWidth * kHeight) / 4) { + return value === -3 || value === 3; + } else { + return value === 0; + } + }, + { + predicatePrinter: [ + { + leftHeader: 'data exp ==', + getValueForCell: (idx) => { + if (idx < 3 * (2 * kWidth * kHeight) / 4) { + return '+/- 3'; + } else { + return 0; + } + } + }] + + } + ); + }; + + // 3/4 of the fragments are written. + const fbChecker = (a) => { + return checkElementsPassPredicate( + a, + (idx, value) => { + const x = idx % kWidth; + const y = Math.floor(idx / kWidth); + if (((x | y) & 0x1) === 0) { + return value === kWidth * kHeight; + } else { + return value < 3 * (kWidth * kHeight) / 4; + } + }, + { + predicatePrinter: [ + { + leftHeader: 'fb exp ==', + getValueForCell: (idx) => { + const x = idx % kWidth; + const y = Math.floor(idx / kWidth); + if (((x | y) & 0x1) === 0) { + return kWidth * kHeight; + } else { + return 'any'; + } + } + }] + + } + ); + }; + + drawFullScreen(t, code, dataChecker, fbChecker); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/zero_init.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/zero_init.spec.js index c7b21d5699..fe0c3cbe29 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/zero_init.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/zero_init.spec.js @@ -107,6 +107,10 @@ expandWithParams(function* (p) { [true, false] : [false]) { for (const scalarType of supportedScalarTypes({ isAtomic, ...p })) { + // Fewer subcases: supportedScalarTypes was expanded to include f16 + // but that may take too much time. It would require more complex code. + if (scalarType === 'f16') continue; + // Fewer subcases: For nested types, skip atomic u32 and non-atomic i32. if (p._containerDepth > 0) { if (scalarType === 'u32' && isAtomic) continue; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/types.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/types.js index 5810b8e9f1..ef84746565 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/types.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/types.js @@ -2,19 +2,32 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { keysOf } from '../../common/util/data_tables.js';import { assert } from '../../common/util/util.js';import { align } from '../util/math.js'; -const kArrayLength = 3; +const kDefaultArrayLength = 3; // never is the same as "must not" -export const HostSharableTypes = ['i32', 'u32', 'f32']; +export const HostSharableTypes = ['i32', 'u32', 'f16', 'f32']; + +// The alignment and size of a host shareable type. +// See "Alignment and Size" in the WGSL spec. https://w3.org/TR/WGSL/#alignment-and-size +// Note this is independent of the address space that values of this type might appear in. +// See RequiredAlignOf(...) for the 16-byte granularity requirement when +// values of a type are placed in the uniform address space. + + + + + + /** Info for each plain scalar type. */ export const kScalarTypeInfo = { 'i32': { layout: { alignment: 4, size: 4 }, supportsAtomics: true, arrayLength: 1, innerLength: 0 }, 'u32': { layout: { alignment: 4, size: 4 }, supportsAtomics: true, arrayLength: 1, innerLength: 0 }, + 'f16': { layout: { alignment: 2, size: 2 }, supportsAtomics: false, arrayLength: 1, innerLength: 0, feature: 'shader-f16' }, 'f32': { layout: { alignment: 4, size: 4 }, supportsAtomics: false, arrayLength: 1, innerLength: 0 }, 'bool': { layout: undefined, supportsAtomics: false, arrayLength: 1, innerLength: 0 } }; @@ -24,29 +37,71 @@ export const kScalarTypes = keysOf(kScalarTypeInfo); /** Info for each vecN<> container type. */ export const kVectorContainerTypeInfo = { - 'vec2': { layout: { alignment: 8, size: 8 }, arrayLength: 2, innerLength: 0 }, - 'vec3': { layout: { alignment: 16, size: 12 }, arrayLength: 3, innerLength: 0 }, - 'vec4': { layout: { alignment: 16, size: 16 }, arrayLength: 4, innerLength: 0 } + 'vec2': { arrayLength: 2, innerLength: 0 }, + 'vec3': { arrayLength: 3, innerLength: 0 }, + 'vec4': { arrayLength: 4, innerLength: 0 } }; /** List of all vecN<> container types. */ export const kVectorContainerTypes = keysOf(kVectorContainerTypeInfo); +/** Returns the vector layout for a given vector container and base type, or undefined if that base type has no layout */ +function vectorLayout( +vectorContainer, +baseType) +{ + const n = kVectorContainerTypeInfo[vectorContainer].arrayLength; + const scalarLayout = kScalarTypeInfo[baseType].layout; + if (scalarLayout === undefined) { + return undefined; + } + if (n === 3) { + return { alignment: scalarLayout.alignment * 4, size: scalarLayout.size * 3 }; + } + return { alignment: scalarLayout.alignment * n, size: scalarLayout.size * n }; +} + /** Info for each matNxN<> container type. */ export const kMatrixContainerTypeInfo = { - 'mat2x2': { layout: { alignment: 8, size: 16 }, arrayLength: 2, innerLength: 2 }, - 'mat3x2': { layout: { alignment: 8, size: 24 }, arrayLength: 3, innerLength: 2 }, - 'mat4x2': { layout: { alignment: 8, size: 32 }, arrayLength: 4, innerLength: 2 }, - 'mat2x3': { layout: { alignment: 16, size: 32 }, arrayLength: 2, innerLength: 3 }, - 'mat3x3': { layout: { alignment: 16, size: 48 }, arrayLength: 3, innerLength: 3 }, - 'mat4x3': { layout: { alignment: 16, size: 64 }, arrayLength: 4, innerLength: 3 }, - 'mat2x4': { layout: { alignment: 16, size: 32 }, arrayLength: 2, innerLength: 4 }, - 'mat3x4': { layout: { alignment: 16, size: 48 }, arrayLength: 3, innerLength: 4 }, - 'mat4x4': { layout: { alignment: 16, size: 64 }, arrayLength: 4, innerLength: 4 } + 'mat2x2': { arrayLength: 2, innerLength: 2 }, + 'mat3x2': { arrayLength: 3, innerLength: 2 }, + 'mat4x2': { arrayLength: 4, innerLength: 2 }, + 'mat2x3': { arrayLength: 2, innerLength: 3 }, + 'mat3x3': { arrayLength: 3, innerLength: 3 }, + 'mat4x3': { arrayLength: 4, innerLength: 3 }, + 'mat2x4': { arrayLength: 2, innerLength: 4 }, + 'mat3x4': { arrayLength: 3, innerLength: 4 }, + 'mat4x4': { arrayLength: 4, innerLength: 4 } }; /** List of all matNxN<> container types. */ export const kMatrixContainerTypes = keysOf(kMatrixContainerTypeInfo); +export const kMatrixContainerTypeLayoutInfo = +{ + 'f16': { + 'mat2x2': { layout: { alignment: 4, size: 8 } }, + 'mat3x2': { layout: { alignment: 4, size: 12 } }, + 'mat4x2': { layout: { alignment: 4, size: 16 } }, + 'mat2x3': { layout: { alignment: 8, size: 16 } }, + 'mat3x3': { layout: { alignment: 8, size: 24 } }, + 'mat4x3': { layout: { alignment: 8, size: 32 } }, + 'mat2x4': { layout: { alignment: 8, size: 16 } }, + 'mat3x4': { layout: { alignment: 8, size: 24 } }, + 'mat4x4': { layout: { alignment: 8, size: 32 } } + }, + 'f32': { + 'mat2x2': { layout: { alignment: 8, size: 16 } }, + 'mat3x2': { layout: { alignment: 8, size: 24 } }, + 'mat4x2': { layout: { alignment: 8, size: 32 } }, + 'mat2x3': { layout: { alignment: 16, size: 32 } }, + 'mat3x3': { layout: { alignment: 16, size: 48 } }, + 'mat4x3': { layout: { alignment: 16, size: 64 } }, + 'mat2x4': { layout: { alignment: 16, size: 32 } }, + 'mat3x4': { layout: { alignment: 16, size: 48 } }, + 'mat4x4': { layout: { alignment: 16, size: 64 } } + } +}; + @@ -161,10 +216,39 @@ export function* generateTypes({ -}) { +}) + + + + + + + + + + + + + + + + + + + + + + + + +{ const scalarInfo = kScalarTypeInfo[baseType]; if (isAtomic) { assert(scalarInfo.supportsAtomics, 'type does not support atomics'); + assert( + containerType === 'scalar' || containerType === 'array', + "can only generate atomic inner types with containerType 'scalar' or 'array'" + ); } const scalarType = isAtomic ? `atomic<${baseType}>` : baseType; @@ -189,21 +273,29 @@ export function* generateTypes({ for (const vectorType of kVectorContainerTypes) { yield { type: `${vectorType}<${scalarType}>`, - _kTypeInfo: { elementBaseType: baseType, ...kVectorContainerTypeInfo[vectorType] } + _kTypeInfo: { + elementBaseType: baseType, + ...kVectorContainerTypeInfo[vectorType], + layout: vectorLayout(vectorType, scalarType), + supportsAtomics: false + } }; } } if (containerType === 'matrix') { - // Matrices can only be f32. - if (baseType === 'f32') { + // Matrices can only be f16 or f32. + if (baseType === 'f16' || baseType === 'f32') { for (const matrixType of kMatrixContainerTypes) { - const matrixInfo = kMatrixContainerTypeInfo[matrixType]; + const matrixDimInfo = kMatrixContainerTypeInfo[matrixType]; + const matrixLayoutInfo = kMatrixContainerTypeLayoutInfo[baseType][matrixType]; yield { type: `${matrixType}<${scalarType}>`, _kTypeInfo: { - elementBaseType: `vec${matrixInfo.innerLength}<${scalarType}>`, - ...matrixInfo + elementBaseType: `vec${matrixDimInfo.innerLength}<${scalarType}>`, + ...matrixDimInfo, + ...matrixLayoutInfo, + supportsAtomics: false } }; } @@ -212,37 +304,53 @@ export function* generateTypes({ // Array types if (containerType === 'array') { + let arrayElemType = scalarType; + let arrayElementCount = kDefaultArrayLength; + let supportsAtomics = scalarInfo.supportsAtomics; + let layout = undefined; + if (scalarInfo.layout) { + // Compute the layout of the array type. + // Adjust the array element count or element type as needed. + if (addressSpace === 'uniform') { + // Use a vec4 of the scalar type, to achieve a 16 byte alignment without internal padding. + // This works for 4-byte scalar types, and does not work for f16. + // It is the caller's responsibility to filter out the f16 case. + assert(!isAtomic, 'the uniform case is making vec4 of scalar, which cannot handle atomics'); + arrayElemType = `vec4<${baseType}>`; + supportsAtomics = false; + const arrayElemLayout = vectorLayout('vec4', baseType); + // assert(arrayElemLayout.alignment % 16 === 0); // Callers responsibility to avoid + arrayElementCount = align(arrayElementCount, 4) / 4; + const arrayByteSize = arrayElementCount * arrayElemLayout.size; + layout = { alignment: arrayElemLayout.alignment, size: arrayByteSize }; + } else { + // The ordinary case. Use scalarType as the element type. + const stride = arrayStride(scalarInfo.layout); + let arrayByteSize = arrayElementCount * stride; + if (addressSpace === 'storage') { + // The buffer effective binding size must be a multiple of 4. + // Adjust the array element count as needed. + while (arrayByteSize % 4 > 0) { + arrayElementCount++; + arrayByteSize = arrayElementCount * stride; + } + } + layout = { alignment: scalarInfo.layout.alignment, size: arrayByteSize }; + } + } + const arrayTypeInfo = { elementBaseType: `${baseType}`, - arrayLength: kArrayLength, - layout: scalarInfo.layout ? - { - alignment: scalarInfo.layout.alignment, - size: - addressSpace === 'uniform' ? - // Uniform storage class must have array elements aligned to 16. - kArrayLength * - arrayStride({ - ...scalarInfo.layout, - alignment: 16 - }) : - kArrayLength * arrayStride(scalarInfo.layout) - } : - undefined + arrayLength: arrayElementCount, + layout, + supportsAtomics }; // Sized - if (addressSpace === 'uniform') { - yield { - type: `array,${kArrayLength}>`, - _kTypeInfo: arrayTypeInfo - }; - } else { - yield { type: `array<${scalarType},${kArrayLength}>`, _kTypeInfo: arrayTypeInfo }; - } + yield { type: `array<${arrayElemType},${arrayElementCount}>`, _kTypeInfo: arrayTypeInfo }; // Unsized if (addressSpace === 'storage') { - yield { type: `array<${scalarType}>`, _kTypeInfo: arrayTypeInfo }; + yield { type: `array<${arrayElemType}>`, _kTypeInfo: arrayTypeInfo }; } } @@ -272,7 +380,7 @@ export function supportsAtomics(p) } -/** Generates an iterator of supported base types (i32/u32/f32/bool) */ +/** Generates an iterator of supported base types (i32/u32/f16/f32/bool) */ export function* supportedScalarTypes(p) { for (const scalarType of kScalarTypes) { const info = kScalarTypeInfo[scalarType]; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/const_assert/const_assert.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/const_assert/const_assert.spec.js index 13e7e687f8..4a32098f6c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/const_assert/const_assert.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/const_assert/const_assert.spec.js @@ -59,9 +59,9 @@ g.test('constant_expression_no_assert'). desc(`Test that const_assert does not assert on a true conditional expression`). params((u) => u. -combine('case', keysOf(kConditionCases)). combine('scope', ['module', 'function']). -beginSubcases() +beginSubcases(). +combine('case', keysOf(kConditionCases)) ). fn((t) => { const expr = kConditionCases[t.params.case].expr; @@ -76,9 +76,9 @@ g.test('constant_expression_assert'). desc(`Test that const_assert does assert on a false conditional expression`). params((u) => u. -combine('case', keysOf(kConditionCases)). combine('scope', ['module', 'function']). -beginSubcases() +beginSubcases(). +combine('case', keysOf(kConditionCases)) ). fn((t) => { const expr = kConditionCases[t.params.case].expr; @@ -95,10 +95,10 @@ desc( ). params((u) => u. -combine('lhs', keysOf(kConditionCases)). -combine('rhs', keysOf(kConditionCases)). combine('scope', ['module', 'function']). -beginSubcases() +beginSubcases(). +combine('lhs', keysOf(kConditionCases)). +combine('rhs', keysOf(kConditionCases)) ). fn((t) => { const expr = `(${kConditionCases[t.params.lhs].expr}) || (${ @@ -117,10 +117,10 @@ desc( ). params((u) => u. -combine('lhs', keysOf(kConditionCases)). -combine('rhs', keysOf(kConditionCases)). combine('scope', ['module', 'function']). -beginSubcases() +beginSubcases(). +combine('lhs', keysOf(kConditionCases)). +combine('rhs', keysOf(kConditionCases)) ). fn((t) => { const expr = `(${kConditionCases[t.params.lhs].expr}) || (${ @@ -139,10 +139,10 @@ desc( ). params((u) => u. -combine('lhs', keysOf(kConditionCases)). -combine('rhs', keysOf(kConditionCases)). combine('scope', ['module', 'function']). -beginSubcases() +beginSubcases(). +combine('lhs', keysOf(kConditionCases)). +combine('rhs', keysOf(kConditionCases)) ). fn((t) => { const expr = `(${kConditionCases[t.params.lhs].expr}) && (${ @@ -161,10 +161,10 @@ desc( ). params((u) => u. -combine('lhs', keysOf(kConditionCases)). -combine('rhs', keysOf(kConditionCases)). combine('scope', ['module', 'function']). -beginSubcases() +beginSubcases(). +combine('lhs', keysOf(kConditionCases)). +combine('rhs', keysOf(kConditionCases)) ). fn((t) => { const expr = `(${kConditionCases[t.params.lhs].expr}) && (${ diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/compound_statement.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/compound_statement.spec.js new file mode 100644 index 0000000000..f7bcf6d9d6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/compound_statement.spec.js @@ -0,0 +1,98 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for declarations in compound statements. +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// 9.1 Compound Statements +// When a declaration is one of those statements, its identifier is in scope from +// the start of the next statement until the end of the compound statement. +// +// Enumerating cases: Consider a declaration X inside a compound statement. +// The X declaration should be tested with potential uses and potentially +// conflicting declarations in positions [a, b, c, d, e], in the following: +// a { b; X; c; { d; } } e; + +const kConflictTests = { + a: { + src: 'let x = 1; { let x = 1; }', + pass: true + }, + bc: { + src: '{let x = 1; let x = 1; }', + pass: false + }, + d: { + src: '{let x = 1; { let x = 1; }}', + pass: true + }, + e: { + src: '{let x = 1; } let x = 1;', + pass: true + } +}; + +g.test('decl_conflict'). +desc( + 'Test a potentially conflicting declaration relative to a declaration in a compound statement' +). +params((u) => u.combine('case', keysOf(kConflictTests))). +fn((t) => { + const wgsl = ` +@vertex fn vtx() -> @builtin(position) vec4f { + ${kConflictTests[t.params.case].src} + return vec4f(1); +}`; + t.expectCompileResult(kConflictTests[t.params.case].pass, wgsl); +}); + +const kUseTests = { + a: { + src: 'let y = x; { let x = 1; }', + pass: false // not visible + }, + b: { + src: '{ let y = x; let x = 1; }', + pass: false // not visible + }, + self: { + src: '{ let x = (x);}', + pass: false // not visible + }, + c_yes: { + src: '{ const x = 1; const_assert x == 1; }', + pass: true + }, + c_no: { + src: '{ const x = 1; const_assert x == 2; }', + pass: false + }, + d_yes: { + src: '{ const x = 1; { const_assert x == 1; }}', + pass: true + }, + d_no: { + src: '{ const x = 1; { const_assert x == 2; }}', + pass: false + }, + e: { + src: '{ const x = 1; } let y = x;', + pass: false // not visible + } +}; + +g.test('decl_use'). +desc('Test a use of a declaration in a compound statement'). +params((u) => u.combine('case', keysOf(kUseTests))). +fn((t) => { + const wgsl = ` +@vertex fn vtx() -> @builtin(position) vec4f { + ${kUseTests[t.params.case].src} + return vec4f(1); +}`; + t.expectCompileResult(kUseTests[t.params.case].pass, wgsl); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/const.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/const.spec.js index 2ab34e65bf..0ba21b64eb 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/const.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/const.spec.js @@ -3,6 +3,7 @@ **/export const description = ` Validation tests for const declarations `;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; import { ShaderValidationTest } from '../shader_validation_test.js'; export const g = makeTestGroup(ShaderValidationTest); @@ -58,4 +59,161 @@ const a = 4; const b = S(4).a; `; t.expectCompileResult(t.params.target === 'a', wgsl); +}); + +const kTypeCases = { + bool: { + code: `const x : bool = true;`, + valid: true + }, + i32: { + code: `const x : i32 = 1i;`, + valid: true + }, + u32: { + code: `const x : u32 = 1u;`, + valid: true + }, + f32: { + code: `const x : f32 = 1f;`, + valid: true + }, + f16: { + code: `enable f16;\nconst x : f16 = 1h;`, + valid: true + }, + abstract_int: { + code: ` + const x = 0xffffffffff; + const_assert x == 0xffffffffff;`, + valid: true + }, + abstract_float: { + code: ` + const x = 3937509.87755102; + const_assert x != 3937510.0; + const_assert x != 3937509.75;`, + valid: true + }, + vec2i: { + code: `const x : vec2i = vec2i();`, + valid: true + }, + vec3u: { + code: `const x : vec3u = vec3u();`, + valid: true + }, + vec4f: { + code: `const x : vec4f = vec4f();`, + valid: true + }, + mat2x2: { + code: `const x : mat2x2f = mat2x2f();`, + valid: true + }, + mat4x3f: { + code: `const x : mat4x3 = mat4x3();`, + valid: true + }, + array_sized: { + code: `const x : array = array(1,2,3,4);`, + valid: true + }, + array_runtime: { + code: `const x : array = array(1,2,3);`, + valid: false + }, + struct: { + code: `struct S { x : u32 }\nconst x : S = S(0);`, + valid: true + }, + atomic: { + code: `const x : atomic = 0;`, + valid: false + }, + vec_abstract_int: { + code: ` + const x = vec2(0xffffffffff,0xfffffffff0); + const_assert x.x == 0xffffffffff; + const_assert x.y == 0xfffffffff0;`, + valid: true + }, + array_abstract_int: { + code: ` + const x = array(0xffffffffff,0xfffffffff0); + const_assert x[0] == 0xffffffffff; + const_assert x[1] == 0xfffffffff0;`, + valid: true + } +}; + +g.test('type'). +desc('Test const types'). +params((u) => u.combine('case', keysOf(kTypeCases))). +beforeAllSubcases((t) => { + if (t.params.case === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const testcase = kTypeCases[t.params.case]; + const code = testcase.code; + const expect = testcase.valid; + t.expectCompileResult(expect, code); +}); + +const kInitCases = { + no_init: { + code: `const x : u32;`, + valid: false + }, + no_type: { + code: `const x = 0;`, + valid: true + }, + init_matching_type: { + code: `const x : i32 = 1i;`, + valid: true + }, + init_mismatch_type: { + code: `const x : u32 = 1i;`, + valid: false + }, + abs_int_init_convert: { + code: `const x : u32 = 1;`, + valid: true + }, + abs_float_init_convert: { + code: `const x : f32 = 1.0;`, + valid: true + }, + init_const_expr: { + code: `const x = 0;\nconst y = x + 2;`, + valid: true + }, + init_override_expr: { + code: `override x : u32;\nconst y = x * 2;`, + valid: false + }, + init_runtime_expr: { + code: `var x = 1i;\nconst y = x - 1;`, + valid: false + } +}; + +g.test('initializer'). +desc('Test const initializers'). +params((u) => u.combine('case', keysOf(kInitCases))). +fn((t) => { + const testcase = kInitCases[t.params.case]; + const code = testcase.code; + const expect = testcase.valid; + t.expectCompileResult(expect, code); +}); + +g.test('function_scope'). +desc('Test that const declarations are allowed in functions'). +fn((t) => { + const code = `fn foo() { const x = 0; }`; + t.expectCompileResult(true, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/context_dependent_resolution.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/context_dependent_resolution.spec.js new file mode 100644 index 0000000000..b821f03957 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/context_dependent_resolution.spec.js @@ -0,0 +1,338 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Tests that context dependent names do not participate in name resolution. +That is, a declaration named the same as a context dependent name will not interfere. + +Context-dependent names: + * Attribute names + * Built-in value names + * Diagnostic severity control + * Diagnostic triggering rules + * Enable extensions + * Language extensions + * Swizzles + * Interpolation type + * Interpolation sampling +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kAttributeCases = { + align: `struct S { @align(16) x : u32 }`, + binding: `@group(0) @binding(0) var s : sampler;`, + builtin: `@vertex fn main() -> @builtin(position) vec4f { return vec4f(); }`, + // const is not writable + // diagnostic is a keyword + group: `@group(0) @binding(0) var s : sampler;`, + id: `@id(1) override x : i32;`, + interpolate: `@fragment fn main(@location(0) @interpolate(flat) x : i32) { }`, + invariant: `@fragment fn main(@builtin(position) @invariant pos : vec4f) { }`, + location: `@fragment fn main(@location(0) x : f32) { }`, + must_use: `@must_use fn foo() -> u32 { return 0; }`, + size: `struct S { @size(4) x : u32 }`, + workgroup_size: `@compute @workgroup_size(1) fn main() { }`, + compute: `@compute @workgroup_size(1) fn main() { }`, + fragment: `@fragment fn main() { }`, + vertex: `@vertex fn main() -> @builtin(position) vec4f { return vec4f(); }` +}; + +g.test('attribute_names'). +desc('Tests attribute names do not use name resolution'). +params((u) => +u. +combine('case', keysOf(kAttributeCases)). +beginSubcases(). +combine('decl', ['override', 'const', 'var']) +). +fn((t) => { + const code = ` + ${t.params.decl} ${t.params.case} : u32 = 0; + ${kAttributeCases[t.params.case]} + fn use_var() -> u32 { + return ${t.params.case}; + } + `; + + t.expectCompileResult(true, code); +}); + +const kBuiltinCases = { + vertex_index: ` + @vertex + fn main(@builtin(vertex_index) idx : u32) -> @builtin(position) vec4f + { return vec4f(); }`, + instance_index: ` + @vertex + fn main(@builtin(instance_index) idx : u32) -> @builtin(position) vec4f + { return vec4f(); }`, + position_vertex: ` + @vertex fn main() -> @builtin(position) vec4f + { return vec4f(); }`, + position_fragment: `@fragment fn main(@builtin(position) pos : vec4f) { }`, + front_facing: `@fragment fn main(@builtin(front_facing) x : bool) { }`, + frag_depth: `@fragment fn main() -> @builtin(frag_depth) f32 { return 0; }`, + sample_index: `@fragment fn main(@builtin(sample_index) x : u32) { }`, + sample_mask_input: `@fragment fn main(@builtin(sample_mask) x : u32) { }`, + sample_mask_output: `@fragment fn main() -> @builtin(sample_mask) u32 { return 0; }`, + local_invocation_id: ` + @compute @workgroup_size(1) + fn main(@builtin(local_invocation_id) id : vec3u) { }`, + local_invocation_index: ` + @compute @workgroup_size(1) + fn main(@builtin(local_invocation_index) id : u32) { }`, + global_invocation_id: ` + @compute @workgroup_size(1) + fn main(@builtin(global_invocation_id) id : vec3u) { }`, + workgroup_id: ` + @compute @workgroup_size(1) + fn main(@builtin(workgroup_id) id : vec3u) { }`, + num_workgroups: ` + @compute @workgroup_size(1) + fn main(@builtin(num_workgroups) id : vec3u) { }` +}; + +g.test('builtin_value_names'). +desc('Tests builtin value names do not use name resolution'). +params((u) => +u. +combine('case', keysOf(kBuiltinCases)). +beginSubcases(). +combine('decl', ['override', 'const', 'var']) +). +fn((t) => { + const code = ` + ${t.params.decl} ${t.params.case} : u32 = 0; + ${kBuiltinCases[t.params.case]} + fn use_var() -> u32 { + return ${t.params.case}; + } + `; + + t.expectCompileResult(true, code); +}); + +const kDiagnosticSeverityCases = { + error: ` + diagnostic(error, derivative_uniformity); + @diagnostic(error, derivative_uniformity) fn foo() { } + `, + warning: ` + diagnostic(warning, derivative_uniformity); + @diagnostic(warning, derivative_uniformity) fn foo() { } + `, + off: ` + diagnostic(off, derivative_uniformity); + @diagnostic(off, derivative_uniformity) fn foo() { } + `, + info: ` + diagnostic(info, derivative_uniformity); + @diagnostic(info, derivative_uniformity) fn foo() { } + ` +}; + +g.test('diagnostic_severity_names'). +desc('Tests diagnostic severity names do not use name resolution'). +params((u) => +u. +combine('case', keysOf(kDiagnosticSeverityCases)). +beginSubcases(). +combine('decl', ['override', 'const', 'var']) +). +fn((t) => { + const code = ` + ${kDiagnosticSeverityCases[t.params.case]} + ${t.params.decl} ${t.params.case} : u32 = 0; + fn use_var() -> u32 { + return ${t.params.case}; + } + `; + + t.expectCompileResult(true, code); +}); + +const kDiagnosticRuleCases = { + derivative_uniformity: ` + diagnostic(off, derivative_uniformity); + @diagnostic(warning, derivative_uniformity) fn foo() { }`, + unknown_rule: ` + diagnostic(off, unknown_rule); + @diagnostic(warning, unknown_rule) fn foo() { }`, + unknown: ` + diagnostic(off, unknown.rule); + @diagnostic(warning, unknown.rule) fn foo() { }`, + rule: ` + diagnostic(off, unknown.rule); + @diagnostic(warning, unknown.rule) fn foo() { }` +}; + +g.test('diagnostic_rule_names'). +desc('Tests diagnostic rule names do not use name resolution'). +params((u) => +u. +combine('case', keysOf(kDiagnosticRuleCases)). +beginSubcases(). +combine('decl', ['override', 'const', 'var']) +). +fn((t) => { + const code = ` + ${kDiagnosticRuleCases[t.params.case]} + ${t.params.decl} ${t.params.case} : u32 = 0; + fn use_var() -> u32 { + return ${t.params.case}; + } + `; + + t.expectCompileResult(true, code); +}); + +const kEnableCases = { + f16: `enable f16;` +}; + +g.test('enable_names'). +desc('Tests enable extension names do not use name resolution'). +params((u) => +u. +combine('case', keysOf(kEnableCases)). +beginSubcases(). +combine('decl', ['override', 'const', 'var']) +). +beforeAllSubcases((t) => { + t.selectDeviceOrSkipTestCase('shader-f16'); +}). +fn((t) => { + const code = ` + ${kEnableCases[t.params.case]} + ${t.params.decl} ${t.params.case} : u32 = 0; + fn use_var() -> u32 { + return ${t.params.case}; + } + `; + + t.expectCompileResult(true, code); +}); + +const kLanguageCases = { + readonly_and_readwrite_storage_textures: `requires readonly_and_readwrite_storage_textures;`, + packed_4x8_integer_dot_product: `requires packed_4x8_integer_dot_product;`, + unrestricted_pointer_parameters: `requires unrestricted_pointer_parameters;`, + pointer_composite_access: `requires pointer_composite_access;` +}; + +g.test('language_names'). +desc('Tests language extension names do not use name resolution'). +params((u) => +u. +combine('case', keysOf(kLanguageCases)). +beginSubcases(). +combine('decl', ['override', 'const', 'var']) +). +fn((t) => { + t.skipIf(!t.hasLanguageFeature(t.params.case), 'Missing language feature'); + const code = ` + ${kLanguageCases[t.params.case]} + ${t.params.decl} ${t.params.case} : u32 = 0; + fn use_var() -> u32 { + return ${t.params.case}; + } + `; + + t.expectCompileResult(true, code); +}); + +const kSwizzleCases = [ +'x', +'y', +'z', +'w', +'xy', +'yxz', +'wxyz', +'xyxy', +'r', +'g', +'b', +'a', +'rgb', +'arr', +'bgra', +'agra']; + + +g.test('swizzle_names'). +desc('Tests swizzle names do not use name resolution'). +params((u) => +u. +combine('case', kSwizzleCases). +beginSubcases(). +combine('decl', ['override', 'const', 'var']) +). +fn((t) => { + let code = `${t.params.decl} ${t.params.case} : u32 = 0;\n`; + if (t.params.case.length === 1) { + for (let i = 2; i <= 4; i++) { + code += `${t.params.decl} ${t.params.case.padEnd(i, t.params.case[0])} : u32 = 0;\n`; + } + } + code += `fn foo() { + var x : vec4f; + _ = x.${t.params.case}; + `; + if (t.params.case.length === 1) { + for (let i = 2; i <= 4; i++) { + code += `_ = x.${t.params.case.padEnd(i, t.params.case[0])};\n`; + } + } + code += `} + fn use_var() -> u32 { + return ${t.params.case}; + }`; + t.expectCompileResult(true, code); +}); + +const kInterpolationTypeCases = ['perspective', 'linear', 'flat']; + +g.test('interpolation_type_names'). +desc('Tests interpolation type names do not use name resolution'). +params((u) => +u. +combine('case', kInterpolationTypeCases). +beginSubcases(). +combine('decl', ['override', 'const', 'var']) +). +fn((t) => { + const code = ` + ${t.params.decl} ${t.params.case} : u32 = 0; + @fragment fn main(@location(0) @interpolate(${t.params.case}) x : f32) { } + fn use_var() -> u32 { + return ${t.params.case}; + } + `; + + t.expectCompileResult(true, code); +}); + +const kInterpolationSamplingCases = ['center', 'centroid', 'sample']; + +g.test('interpolation_sampling_names'). +desc('Tests interpolation type names do not use name resolution'). +params((u) => +u. +combine('case', kInterpolationSamplingCases). +beginSubcases(). +combine('decl', ['override', 'const', 'var']) +). +fn((t) => { + const code = ` + ${t.params.decl} ${t.params.case} : u32 = 0; + @fragment fn main(@location(0) @interpolate(perspective, ${t.params.case}) x : f32) { } + fn use_var() -> u32 { + return ${t.params.case}; + } + `; + + t.expectCompileResult(true, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/let.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/let.spec.js new file mode 100644 index 0000000000..2c6d1937b6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/let.spec.js @@ -0,0 +1,180 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for let declarations +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + + + + + + + +const kTypeCases = { + bool: { + code: `let x : bool = true;`, + valid: true + }, + i32: { + code: `let x : i32 = 1i;`, + valid: true + }, + u32: { + code: `let x : u32 = 1u;`, + valid: true + }, + f32: { + code: `let x : f32 = 1f;`, + valid: true + }, + f16: { + code: `let x : f16 = 1h;`, + valid: true + }, + vec2i: { + code: `let x : vec2i = vec2i();`, + valid: true + }, + vec3u: { + code: `let x : vec3u = vec3u();`, + valid: true + }, + vec4f: { + code: `let x : vec4f = vec4f();`, + valid: true + }, + mat2x2: { + code: `let x : mat2x2f = mat2x2f();`, + valid: true + }, + mat4x3f: { + code: `let x : mat4x3 = mat4x3();`, + valid: true + }, + array_sized: { + code: `let x : array = array(1,2,3,4);`, + valid: true + }, + array_runtime: { + code: `let x : array = array(1,2,3);`, + valid: false + }, + struct: { + code: `let x : S = S(0);`, + valid: true, + decls: `struct S { x : u32 }` + }, + atomic: { + code: `let x : atomic = 0;`, + valid: false + }, + ptr_function: { + code: ` + var x : i32; + let y : ptr = &x;`, + valid: true + }, + ptr_storage: { + code: `let y : ptr = &x[0];`, + valid: true, + decls: `@group(0) @binding(0) var x : array;` + }, + load_rule: { + code: ` + var x : i32 = 1; + let y : i32 = x;`, + valid: true + } +}; + +g.test('type'). +desc('Test let types'). +params((u) => u.combine('case', keysOf(kTypeCases))). +beforeAllSubcases((t) => { + if (t.params.case === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const testcase = kTypeCases[t.params.case]; + const code = ` +${t.params.case === 'f16' ? 'enable f16;' : ''} +${testcase.decls ?? ''} +fn foo() { + ${testcase.code} +}`; + const expect = testcase.valid; + t.expectCompileResult(expect, code); +}); + +const kInitCases = { + no_init: { + code: `let x : u32;`, + valid: false + }, + no_type: { + code: `let x = 1;`, + valid: true + }, + init_matching_type: { + code: `let x : u32 = 1u;`, + valid: true + }, + init_mismatch_type: { + code: `let x : u32 = 1i;`, + valid: false + }, + ptr_type_mismatch: { + code: `var x : i32;\nlet y : ptr = &x;`, + valid: false + }, + ptr_access_mismatch: { + code: `let y : ptr = &x;`, + valid: false, + decls: `@group(0) @binding(0) var x : u32;` + }, + ptr_addrspace_mismatch: { + code: `let y = ptr = &x;`, + valid: false, + decls: `@group(0) @binding(0) var x : u32;` + }, + init_const_expr: { + code: `let y = x * 2;`, + valid: true, + decls: `const x = 1;` + }, + init_override_expr: { + code: `let y = x + 1;`, + valid: true, + decls: `override x = 1;` + }, + init_runtime_expr: { + code: `var x = 1;\nlet y = x << 1;`, + valid: true + } +}; + +g.test('initializer'). +desc('Test let initializers'). +params((u) => u.combine('case', keysOf(kInitCases))). +fn((t) => { + const testcase = kInitCases[t.params.case]; + const code = ` +${testcase.decls ?? ''} +fn foo() { + ${testcase.code} +}`; + const expect = testcase.valid; + t.expectCompileResult(expect, code); +}); + +g.test('module_scope'). +desc('Test that let declarations are disallowed module scope'). +fn((t) => { + const code = `let x = 0;`; + t.expectCompileResult(false, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/override.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/override.spec.js index 561527a622..ec31582ae5 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/override.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/override.spec.js @@ -3,6 +3,7 @@ **/export const description = ` Validation tests for override declarations `;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; import { ShaderValidationTest } from '../shader_validation_test.js'; export const g = makeTestGroup(ShaderValidationTest); @@ -28,4 +29,181 @@ override b : i32 = c; override c : i32 = ${t.params.target}; `; t.expectCompileResult(t.params.target === 'a', wgsl); +}); + +const kIdCases = { + min: { + code: `@id(0) override x = 1;`, + valid: true + }, + max: { + code: `@id(65535) override x = 1;`, + valid: true + }, + neg: { + code: `@id(-1) override x = 1;`, + valid: false + }, + too_large: { + code: `@id(65536) override x = 1;`, + valid: false + }, + duplicate: { + code: ` + @id(1) override x = 1; + @id(1) override y = 1;`, + valid: false + } +}; + +g.test('id'). +desc('Test id attributes'). +params((u) => u.combine('case', keysOf(kIdCases))). +fn((t) => { + const testcase = kIdCases[t.params.case]; + const code = testcase.code; + const expect = testcase.valid; + t.expectCompileResult(expect, code); +}); + +const kTypeCases = { + bool: { + code: `override x : bool;`, + valid: true + }, + i32: { + code: `override x : i32;`, + valid: true + }, + u32: { + code: `override x : u32;`, + valid: true + }, + f32: { + code: `override x : f32;`, + valid: true + }, + f16: { + code: `enable f16;\noverride x : f16;`, + valid: true + }, + abs_int_conversion: { + code: `override x = 1;`, + valid: true + }, + abs_float_conversion: { + code: `override x = 1.0;`, + valid: true + }, + vec2_bool: { + code: `override x : vec2;`, + valid: false + }, + vec2i: { + code: `override x : vec2i;`, + valid: false + }, + vec3u: { + code: `override x : vec3u;`, + valid: false + }, + vec4f: { + code: `override x : vec4f;`, + valid: false + }, + mat2x2f: { + code: `override x : mat2x2f;`, + valid: false + }, + matrix: { + code: `override x : mat4x3;`, + valid: false + }, + array: { + code: `override x : array;`, + valid: false + }, + struct: { + code: `struct S { x : u32 }\noverride x : S;`, + valid: false + }, + atomic: { + code: `override x : atomic;`, + valid: false + } +}; + +g.test('type'). +desc('Test override types'). +params((u) => u.combine('case', keysOf(kTypeCases))). +beforeAllSubcases((t) => { + if (t.params.case === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const testcase = kTypeCases[t.params.case]; + const code = testcase.code; + const expect = testcase.valid; + t.expectCompileResult(expect, code); +}); + +const kInitCases = { + no_init_no_type: { + code: `override x;`, + valid: false + }, + no_init: { + code: `override x : u32;`, + valid: true + }, + no_type: { + code: `override x = 1;`, + valid: true + }, + init_matching_type: { + code: `override x : u32 = 1u;`, + valid: true + }, + init_mismatch_type: { + code: `override x : u32 = 1i;`, + valid: false + }, + abs_int_init_convert: { + code: `override x : f32 = 1;`, + valid: true + }, + abs_float_init_convert: { + code: `override x : f32 = 1.0;`, + valid: true + }, + init_const_expr: { + code: `const x = 1;\noverride y = 2 * x;`, + valid: true + }, + init_override_expr: { + code: `override x = 1;\noverride y = x + 2;`, + valid: true + }, + init_runtime_expr: { + code: `var x = 2;\noverride y = x;`, + valid: false + } +}; + +g.test('initializer'). +desc('Test override initializers'). +params((u) => u.combine('case', keysOf(kInitCases))). +fn((t) => { + const testcase = kInitCases[t.params.case]; + const code = testcase.code; + const expect = testcase.valid; + t.expectCompileResult(expect, code); +}); + +g.test('function_scope'). +desc('Test that override declarations are disallowed in functions'). +fn((t) => { + const code = `fn foo() { override x : u32; }`; + t.expectCompileResult(false, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/var.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/var.spec.js new file mode 100644 index 0000000000..ff4f705d87 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/decl/var.spec.js @@ -0,0 +1,529 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for host-shareable types. +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// The set of types and their properties. +const kTypes = { + // Scalars. + bool: { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + i32: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + u32: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + f32: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + f16: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: true + }, + + // Vectors. + 'vec2': { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + vec3i: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + vec4u: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + vec2f: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + vec3h: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: true + }, + + // Matrices. + mat2x2f: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + mat3x4h: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: true + }, + + // Atomics. + 'atomic': { + isHostShareable: true, + isConstructible: false, + isFixedFootprint: true, + requiresF16: false + }, + 'atomic': { + isHostShareable: true, + isConstructible: false, + isFixedFootprint: true, + requiresF16: false + }, + + // Arrays. + 'array>': { + isHostShareable: false, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false + }, + 'array, 4>': { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + 'array': { + isHostShareable: true, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false + }, + 'array': { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + 'array': { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + 'array': { + isHostShareable: false, + isConstructible: false, + isFixedFootprint: true, + requiresF16: false + }, + + // Structures. + S_u32: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + S_bool: { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + S_S_bool: { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + S_array_vec4u: { + isHostShareable: true, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false + }, + S_array_vec4u_4: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + S_array_bool_4: { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false + }, + + // Misc. + 'ptr': { + isHostShareable: false, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false + }, + sampler: { + isHostShareable: false, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false + }, + 'texture_2d': { + isHostShareable: false, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false + } +}; + +g.test('module_scope_types'). +desc('Test that only types that are allowed for a given address space are accepted.'). +params((u) => +u. +combine('type', keysOf(kTypes)). +combine('kind', [ +'comment', +'handle', +'private', +'storage_ro', +'storage_rw', +'uniform', +'workgroup'] +). +combine('via_alias', [false, true]) +). +beforeAllSubcases((t) => { + if (kTypes[t.params.type].requiresF16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kTypes[t.params.type]; + const isAtomic = t.params.type.indexOf('atomic') > -1; + + let decl = '<>'; + let shouldPass = false; + switch (t.params.kind) { + case 'comment': + // Control case to make sure all types are spelled correctly. + // We always emit an alias to the target type. + decl = '// '; + shouldPass = true; + break; + case 'handle': + decl = '@group(0) @binding(0) var foo : '; + shouldPass = t.params.type.indexOf('texture') > -1 || t.params.type.indexOf('sampler') > -1; + break; + case 'private': + decl = 'var foo : '; + shouldPass = type.isConstructible; + break; + case 'storage_ro': + decl = '@group(0) @binding(0) var foo : '; + shouldPass = type.isHostShareable && !isAtomic; + break; + case 'storage_rw': + decl = '@group(0) @binding(0) var foo : '; + shouldPass = type.isHostShareable; + break; + case 'uniform': + decl = '@group(0) @binding(0) var foo : '; + shouldPass = type.isHostShareable && type.isConstructible; + break; + case 'workgroup': + decl = 'var foo : '; + shouldPass = type.isFixedFootprint; + break; + } + + const wgsl = `${type.requiresF16 ? 'enable f16;' : ''} + const array_size_const = 4; + override array_size_override = 4; + + struct S_u32 { a : u32 } + struct S_bool { a : bool } + struct S_S_bool { a : S_bool } + struct S_array_vec4u { a : array } + struct S_array_vec4u_4 { a : array } + struct S_array_bool_4 { a : array } + + alias MyType = ${t.params.type}; + + ${decl} ${t.params.via_alias ? 'MyType' : t.params.type}; + `; + + t.expectCompileResult(shouldPass, wgsl); +}); + +g.test('function_scope_types'). +desc('Test that only types that are allowed for a given address space are accepted.'). +params((u) => +u. +combine('type', keysOf(kTypes)). +combine('kind', ['comment', 'var']). +combine('via_alias', [false, true]) +). +beforeAllSubcases((t) => { + if (kTypes[t.params.type].requiresF16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kTypes[t.params.type]; + + let decl = '<>'; + let shouldPass = false; + switch (t.params.kind) { + case 'comment': + // Control case to make sure all types are spelled correctly. + // We always emit an alias to the target type. + decl = '// '; + shouldPass = true; + break; + case 'var': + decl = 'var foo : '; + shouldPass = type.isConstructible; + break; + } + + const wgsl = `${type.requiresF16 ? 'enable f16;' : ''} + const array_size_const = 4; + override array_size_override = 4; + + struct S_u32 { a : u32 } + struct S_bool { a : bool } + struct S_S_bool { a : S_bool } + struct S_array_vec4u { a : array } + struct S_array_vec4u_4 { a : array } + struct S_array_bool_4 { a : array } + + alias MyType = ${t.params.type}; + + fn foo() { + ${decl} ${t.params.via_alias ? 'MyType' : t.params.type}; + }`; + + t.expectCompileResult(shouldPass, wgsl); +}); + +g.test('module_scope_initializers'). +desc('Test that initializers are only supported on address spaces that allow them.'). +params((u) => +u. +combine('initializer', [false, true]). +combine('kind', ['private', 'storage_ro', 'storage_rw', 'uniform', 'workgroup']) +). +fn((t) => { + let decl = '<>'; + switch (t.params.kind) { + case 'private': + decl = 'var foo : '; + break; + case 'storage_ro': + decl = '@group(0) @binding(0) var foo : '; + break; + case 'storage_rw': + decl = '@group(0) @binding(0) var foo : '; + break; + case 'uniform': + decl = '@group(0) @binding(0) var foo : '; + break; + case 'workgroup': + decl = 'var foo : '; + break; + } + + const wgsl = `${decl} u32${t.params.initializer ? ' = 42u' : ''};`; + t.expectCompileResult(t.params.kind === 'private' || !t.params.initializer, wgsl); +}); + +g.test('handle_initializer'). +desc('Test that initializers are not allowed for handle types'). +params((u) => +u.combine('initializer', [false, true]).combine('type', ['sampler', 'texture_2d']) +). +fn((t) => { + const wgsl = ` + @group(0) @binding(0) var foo : ${t.params.type}; + @group(0) @binding(1) var bar : ${t.params.type}${t.params.initializer ? ' = foo' : ''};`; + t.expectCompileResult(!t.params.initializer, wgsl); +}); + +// A list of u32 initializers and their validity for the private address space. +const kInitializers = { + 'u32()': true, + '42u': true, + 'u32(sqrt(42.0))': true, + 'user_func()': false, + my_const_42u: true, + my_override_42u: true, + another_private_var: false, + 'vec4u(1, 2, 3, 4)[my_const_42u / 20]': true, + 'vec4u(1, 2, 3, 4)[my_override_42u / 20]': true, + 'vec4u(1, 2, 3, 4)[another_private_var / 20]': false +}; + +g.test('initializer_kind'). +desc( + 'Test that initializers must be const-expression or override-expression for the private address space.' +). +params((u) => +u.combine('initializer', keysOf(kInitializers)).combine('addrspace', ['private', 'function']) +). +fn((t) => { + let wgsl = ` + const my_const_42u = 42u; + override my_override_42u : u32; + var another_private_var = 42u; + + fn user_func() -> u32 { + return 42u; + } + `; + + if (t.params.addrspace === 'private') { + wgsl += ` + var foo : u32 = ${t.params.initializer};`; + } else { + wgsl += ` + fn foo() { + var bar : u32 = ${t.params.initializer}; + }`; + } + t.expectCompileResult( + t.params.addrspace === 'function' || kInitializers[t.params.initializer], + wgsl + ); +}); + +g.test('function_addrspace_at_module_scope'). +desc('Test that the function address space is not allowed at module scope.'). +params((u) => u.combine('addrspace', ['private', 'function'])). +fn((t) => { + t.expectCompileResult( + t.params.addrspace === 'private', + `var<${t.params.addrspace}> foo : i32;` + ); +}); + +// A list of resource variable declarations. +const kResourceDecls = { + uniform: 'var buffer : vec4f;', + storage: 'var buffer : vec4f;', + texture: 'var t : texture_2d;', + sampler: 'var s : sampler;' +}; + +g.test('binding_point_on_resources'). +desc('Test that resource variables must have both @group and @binding attributes.'). +params((u) => +u. +combine('decl', keysOf(kResourceDecls)). +combine('group', ['', '@group(0)']). +combine('binding', ['', '@binding(0)']) +). +fn((t) => { + const shouldPass = t.params.group !== '' && t.params.binding !== ''; + const wgsl = `${t.params.group} ${t.params.binding} ${kResourceDecls[t.params.decl]}`; + t.expectCompileResult(shouldPass, wgsl); +}); + +g.test('binding_point_on_non_resources'). +desc('Test that non-resource variables cannot have either @group or @binding attributes.'). +params((u) => +u. +combine('addrspace', ['private', 'workgroup']). +combine('group', ['', '@group(0)']). +combine('binding', ['', '@binding(0)']) +). +fn((t) => { + const shouldPass = t.params.group === '' && t.params.binding === ''; + const wgsl = `${t.params.group} ${t.params.binding} var<${t.params.addrspace}> foo : i32;`; + t.expectCompileResult(shouldPass, wgsl); +}); + +g.test('binding_point_on_function_var'). +desc('Test that function variables cannot have either @group or @binding attributes.'). +params((u) => u.combine('group', ['', '@group(0)']).combine('binding', ['', '@binding(0)'])). +fn((t) => { + const shouldPass = t.params.group === '' && t.params.binding === ''; + const wgsl = ` + fn foo() { + ${t.params.group} ${t.params.binding} var bar : i32; + }`; + t.expectCompileResult(shouldPass, wgsl); +}); + +g.test('binding_collisions'). +desc('Test that binding points can collide iff they are not used by the same entry point.'). +params((u) => +u. +combine('a_group', [0, 1]). +combine('b_group', [0, 1]). +combine('a_binding', [0, 1]). +combine('b_binding', [0, 1]). +combine('b_use', ['same', 'different']) +). +fn((t) => { + const wgsl = ` + @group(${t.params.a_group}) @binding(${t.params.a_binding}) var a : vec4f; + @group(${t.params.b_group}) @binding(${t.params.b_binding}) var b : vec4f; + + @fragment + fn main1() { + _ = a; + ${ + t.params.b_use === 'same' ? + '' : + ` + } + + @fragment + fn main2() {` + } + _ = b; + }`; + + const collision = + t.params.a_group === t.params.b_group && t.params.a_binding === t.params.b_binding; + const shouldFail = collision && t.params.b_use === 'same'; + t.expectCompileResult(!shouldFail, wgsl); +}); + +g.test('binding_collision_unused_helper'). +desc('Test that binding points can collide in an unused helper function.'). +fn((t) => { + const wgsl = ` + @group(0) @binding(0) var a : vec4f; + @group(0) @binding(0) var b : vec4f; + + fn foo() { + _ = a; + _ = b; + }`; + + t.expectCompileResult(true, wgsl); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/access/vector.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/access/vector.spec.js index 7408ea2b04..b881b8ccf5 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/access/vector.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/access/vector.spec.js @@ -178,10 +178,11 @@ g.test('vector'). desc('Tests validation of vector indexed and swizzles'). params((u) => u. -combine('case', keysOf(kCases)) // -.combine('vector_decl', ['const', 'let', 'var', 'param']). +combine('vector_decl', ['const', 'let', 'var', 'param']). combine('vector_width', [2, 3, 4]). -combine('element_type', ['i32', 'u32', 'f32', 'f16', 'bool']) +combine('element_type', ['i32', 'u32', 'f32', 'f16', 'bool']). +beginSubcases(). +combine('case', keysOf(kCases)) ). beforeAllSubcases((t) => { if (t.params.element_type === 'f16') { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/add_sub_mul.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/add_sub_mul.spec.js new file mode 100644 index 0000000000..d49a029830 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/add_sub_mul.spec.js @@ -0,0 +1,320 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for add/sub/mul expressions. +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../common/util/data_tables.js'; +import { assert } from '../../../../../common/util/util.js'; +import { kBit } from '../../../../util/constants.js'; +import { + kAllScalarsAndVectors, + kConcreteNumericScalarsAndVectors, + kConvertableToFloatScalar, + ScalarType, + scalarTypeOf, + Type, + + VectorType } from +'../../../../util/conversion.js'; +import { nextAfterF16, nextAfterF32 } from '../../../../util/math.js'; +import { reinterpretU16AsF16, reinterpretU32AsF32 } from '../../../../util/reinterpret.js'; +import { ShaderValidationTest } from '../../shader_validation_test.js'; +import { + kConstantAndOverrideStages, + validateConstOrOverrideBinaryOpEval } from +'../call/builtin/const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// A list of operators tested in this file. +const kOperators = { + add: { op: '+' }, + sub: { op: '-' }, + mul: { op: '*' } +}; + +// A list of scalar and vector types. +const kScalarAndVectorTypes = objectsToRecord(kAllScalarsAndVectors); +const kConcreteNumericScalarAndVectorTypes = objectsToRecord(kConcreteNumericScalarsAndVectors); + +g.test('scalar_vector'). +desc( + ` + Validates that scalar and vector expressions are only accepted for compatible numeric types. + ` +). +params((u) => +u. +combine('lhs', keysOf(kScalarAndVectorTypes)). +combine( + 'rhs', + // Skip vec3 and vec4 on the RHS to keep the number of subcases down. + // vec3 + vec3 and vec4 + vec4 is tested in execution tests. + keysOf(kScalarAndVectorTypes).filter( + (value) => !(value.startsWith('vec3') || value.startsWith('vec4')) + ) +). +beginSubcases(). +combine('op', keysOf(kOperators)) +). +beforeAllSubcases((t) => { + if ( + scalarTypeOf(kScalarAndVectorTypes[t.params.lhs]) === Type.f16 || + scalarTypeOf(kScalarAndVectorTypes[t.params.rhs]) === Type.f16) + { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const op = kOperators[t.params.op]; + const lhs = kScalarAndVectorTypes[t.params.lhs]; + const rhs = kScalarAndVectorTypes[t.params.rhs]; + const lhsElement = scalarTypeOf(lhs); + const rhsElement = scalarTypeOf(rhs); + const hasF16 = lhsElement === Type.f16 || rhsElement === Type.f16; + const code = ` +${hasF16 ? 'enable f16;' : ''} +const lhs = ${lhs.create(0).wgsl()}; +const rhs = ${rhs.create(0).wgsl()}; +const foo = lhs ${op.op} rhs; +`; + + let elementsCompatible = lhsElement === rhsElement; + const elementTypes = [lhsElement, rhsElement]; + + // Booleans are not allowed for arithmetic expressions. + if (elementTypes.includes(Type.bool)) { + elementsCompatible = false; + + // AbstractInt is allowed with everything but booleans which are already checked above. + } else if (elementTypes.includes(Type.abstractInt)) { + elementsCompatible = true; + + // AbstractFloat is allowed with AbstractInt (checked above) or float types + } else if (elementTypes.includes(Type.abstractFloat)) { + elementsCompatible = elementTypes.every((e) => kConvertableToFloatScalar.includes(e)); + } + + // Determine if the full type is compatible. The only invalid case is mixed vector sizes. + let valid = elementsCompatible; + if (lhs instanceof VectorType && rhs instanceof VectorType) { + valid = valid && lhs.width === rhs.width; + } + + t.expectCompileResult(valid, code); +}); + +g.test('scalar_vector_out_of_range'). +desc( + ` + Checks that constant or override evaluation of add/sub/mul operations on scalar/vectors that produce out of range values cause validation errors. + - Checks for all concrete numeric scalar and vector types, including scalar * vector and vector * scalar. + - Checks for all vector elements that could cause the out of range to happen. + - Checks for pairs of values at one ULP difference at the boundary of the out of range. + ` +). +params((u) => +u. +combine('op', keysOf(kOperators)). +combine('lhs', keysOf(kConcreteNumericScalarAndVectorTypes)). +expand('rhs', (p) => { + if (kScalarAndVectorTypes[p.lhs] instanceof VectorType) { + return [p.lhs, scalarTypeOf(kScalarAndVectorTypes[p.lhs]).toString()]; + } + return [p.lhs]; +}). +beginSubcases(). +expand('swap', (p) => { + if (p.lhs === p.rhs) { + return [false]; + } + return [false, true]; +}). +combine('nonZeroIndex', [0, 1, 2, 3]). +filter((p) => { + const lType = kScalarAndVectorTypes[p.lhs]; + if (lType instanceof VectorType) { + return lType.width > p.nonZeroIndex; + } + return p.nonZeroIndex === 0; +}). +combine('valueCase', ['halfmax', 'halfmax+ulp', 'sqrtmax', 'sqrtmax+ulp']). +combine('stage', kConstantAndOverrideStages) +). +beforeAllSubcases((t) => { + if ( + scalarTypeOf(kScalarAndVectorTypes[t.params.lhs]) === Type.f16 || + scalarTypeOf(kScalarAndVectorTypes[t.params.rhs]) === Type.f16) + { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const { op, valueCase, nonZeroIndex, swap } = t.params; + let { lhs, rhs } = t.params; + + const elementType = scalarTypeOf(kScalarAndVectorTypes[lhs]); + + // Handle the swapping of LHS and RHS to test all cases of scalar * vector. + if (swap) { + [rhs, lhs] = [lhs, rhs]; + } + + // What is the maximum representable value for the type? Also how do we add a ULP? + let maxValue = 0; + let nextAfter = (v) => v + 1; + let outOfRangeIsError = false; + switch (elementType) { + case Type.f16: + maxValue = reinterpretU16AsF16(kBit.f16.positive.max); + nextAfter = (v) => nextAfterF16(v, 'positive', 'no-flush'); + outOfRangeIsError = true; + break; + case Type.f32: + maxValue = reinterpretU32AsF32(kBit.f32.positive.max); + nextAfter = (v) => nextAfterF32(v, 'positive', 'no-flush'); + outOfRangeIsError = true; + break; + case Type.u32: + maxValue = kBit.u32.max; + break; + case Type.i32: + maxValue = kBit.i32.positive.max; + break; + } + + // Decide on the test value that may or may not do an out of range computation. + let value; + switch (valueCase) { + case 'halfmax': + value = Math.floor(maxValue / 2); + break; + case 'halfmax+ulp': + value = nextAfter(Math.ceil(maxValue / 2)); + break; + case 'sqrtmax': + value = Math.floor(Math.sqrt(maxValue)); + break; + case 'sqrtmax+ulp': + value = nextAfter(Math.ceil(Math.sqrt(maxValue))); + break; + } + + // What value will be computed by the test? + let computedValue; + let leftValue = value; + const rightValue = value; + switch (op) { + case 'add': + computedValue = value + value; + break; + case 'sub': + computedValue = -value - value; + leftValue = -value; + break; + case 'mul': + computedValue = value * value; + break; + } + + // Creates either a scalar with the value, or a vector with the value only at a specific index. + const create = (type, index, value) => { + if (type instanceof ScalarType) { + return type.create(value); + } else { + assert(type instanceof VectorType); + const values = new Array(type.width); + values.fill(0); + values[index] = value; + return type.create(values); + } + }; + + // Check if there is overflow + const success = Math.abs(computedValue) <= maxValue || !outOfRangeIsError; + validateConstOrOverrideBinaryOpEval( + t, + kOperators[op].op, + success, + t.params.stage, + create(kScalarAndVectorTypes[lhs], nonZeroIndex, leftValue), + t.params.stage, + create(kScalarAndVectorTypes[rhs], nonZeroIndex, rightValue) + ); +}); + + + + + + + +const kInvalidTypes = { + array: { + expr: 'arr', + control: (e) => `${e}[0]` + }, + + ptr: { + expr: '(&u)', + control: (e) => `*${e}` + }, + + atomic: { + expr: 'a', + control: (e) => `atomicLoad(&${e})` + }, + + texture: { + expr: 't', + control: (e) => `i32(textureLoad(${e}, vec2(), 0).x)` + }, + + sampler: { + expr: 's', + control: (e) => `i32(textureSampleLevel(t, ${e}, vec2(), 0).x)` + }, + + struct: { + expr: 'str', + control: (e) => `${e}.u` + } +}; + +g.test('invalid_type_with_itself'). +desc( + ` + Validates that expressions are never accepted for non-scalar, non-vector, and non-matrix types. + ` +). +params((u) => +u. +combine('op', keysOf(kOperators)). +combine('type', keysOf(kInvalidTypes)). +combine('control', [true, false]). +beginSubcases() +). +fn((t) => { + const op = kOperators[t.params.op]; + const type = kInvalidTypes[t.params.type]; + const expr = t.params.control ? type.control(type.expr) : type.expr; + const code = ` +@group(0) @binding(0) var t : texture_2d; +@group(0) @binding(1) var s : sampler; +@group(0) @binding(2) var a : atomic; + +struct S { u : u32 } + +var u : u32; +var m : mat2x2f; +var arr : array; +var str : S; + +@compute @workgroup_size(1) +fn main() { + let foo = ${expr} ${op.op} ${expr}; +} +`; + + t.expectCompileResult(t.params.control, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/and_or_xor.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/and_or_xor.spec.js new file mode 100644 index 0000000000..9acede3030 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/and_or_xor.spec.js @@ -0,0 +1,182 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for logical and bitwise and/or/xor expressions. +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../common/util/data_tables.js'; +import { + kAllScalarsAndVectors, + ScalarType, + scalarTypeOf, + Type, + VectorType } from +'../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// A list of operators and a flag for whether they support boolean values or not. +const kOperators = { + and: { op: '&', supportsBool: true }, + or: { op: '|', supportsBool: true }, + xor: { op: '^', supportsBool: false } +}; + +// A list of scalar and vector types. +const kScalarAndVectorTypes = objectsToRecord(kAllScalarsAndVectors); + +g.test('scalar_vector'). +desc( + ` + Validates that scalar and vector expressions are only accepted for bool or compatible integer types. + ` +). +params((u) => +u. +combine('lhs', keysOf(kScalarAndVectorTypes)). +combine( + 'rhs', + // Skip vec3 and vec4 on the RHS to keep the number of subcases down. + // vec3 + vec3 and vec4 + vec4 is tested in execution tests. + keysOf(kScalarAndVectorTypes).filter( + (value) => !(value.startsWith('vec3') || value.startsWith('vec4')) + ) +). +beginSubcases(). +combine('op', keysOf(kOperators)) +). +beforeAllSubcases((t) => { + if ( + scalarTypeOf(kScalarAndVectorTypes[t.params.lhs]) === Type.f16 || + scalarTypeOf(kScalarAndVectorTypes[t.params.rhs]) === Type.f16) + { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const op = kOperators[t.params.op]; + const lhs = kScalarAndVectorTypes[t.params.lhs]; + const rhs = kScalarAndVectorTypes[t.params.rhs]; + const lhsElement = scalarTypeOf(lhs); + const rhsElement = scalarTypeOf(rhs); + const hasF16 = lhsElement === Type.f16 || rhsElement === Type.f16; + const code = ` +${hasF16 ? 'enable f16;' : ''} +const lhs = ${lhs.create(0).wgsl()}; +const rhs = ${rhs.create(0).wgsl()}; +const foo = lhs ${op.op} rhs; +`; + + // Determine if the element types are compatible. + const kIntegerTypes = [Type.abstractInt, Type.i32, Type.u32]; + let elementIsCompatible = false; + if (lhsElement === Type.abstractInt) { + // Abstract integers are compatible with any other integer type. + elementIsCompatible = kIntegerTypes.includes(rhsElement); + } else if (rhsElement === Type.abstractInt) { + // Abstract integers are compatible with any other numeric type. + elementIsCompatible = kIntegerTypes.includes(lhsElement); + } else if (kIntegerTypes.includes(lhsElement)) { + // Concrete integers are only compatible with values with the exact same type. + elementIsCompatible = lhsElement === rhsElement; + } else if (lhsElement === Type.bool) { + // Booleans are only compatible with other booleans. + elementIsCompatible = rhsElement === Type.bool; + } + + // Determine if the full type is compatible. + let valid = false; + if (lhs instanceof ScalarType && rhs instanceof ScalarType) { + valid = elementIsCompatible; + } else if (lhs instanceof VectorType && rhs instanceof VectorType) { + // Vectors are only compatible with if the vector widths match. + valid = lhs.width === rhs.width && elementIsCompatible; + } + + if (lhsElement === Type.bool) { + valid &&= op.supportsBool; + } + + t.expectCompileResult(valid, code); +}); + + + + + + + +const kInvalidTypes = { + mat2x2f: { + expr: 'm', + control: (e) => `i32(${e}[0][0])` + }, + + array: { + expr: 'arr', + control: (e) => `${e}[0]` + }, + + ptr: { + expr: '(&u)', + control: (e) => `*${e}` + }, + + atomic: { + expr: 'a', + control: (e) => `atomicLoad(&${e})` + }, + + texture: { + expr: 't', + control: (e) => `i32(textureLoad(${e}, vec2(), 0).x)` + }, + + sampler: { + expr: 's', + control: (e) => `i32(textureSampleLevel(t, ${e}, vec2(), 0).x)` + }, + + struct: { + expr: 'str', + control: (e) => `${e}.u` + } +}; + +g.test('invalid_types'). +desc( + ` + Validates that expressions are never accepted for non-scalar and non-vector types. + ` +). +params((u) => +u. +combine('op', keysOf(kOperators)). +combine('type', keysOf(kInvalidTypes)). +combine('control', [true, false]). +beginSubcases() +). +fn((t) => { + const op = kOperators[t.params.op]; + const type = kInvalidTypes[t.params.type]; + const expr = t.params.control ? type.control(type.expr) : type.expr; + const code = ` +@group(0) @binding(0) var t : texture_2d; +@group(0) @binding(1) var s : sampler; +@group(0) @binding(2) var a : atomic; + +struct S { u : u32 } + +var u : u32; +var m : mat2x2f; +var arr : array; +var str : S; + +@compute @workgroup_size(1) +fn main() { + let foo = ${expr} ${op.op} ${expr}; +} +`; + + t.expectCompileResult(t.params.control, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/bitwise_shift.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/bitwise_shift.spec.js index ff3e1ae525..0ad5ae30b9 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/bitwise_shift.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/bitwise_shift.spec.js @@ -3,6 +3,13 @@ **/export const description = ` Validation tests for the bitwise shift binary expression operations `;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../common/util/data_tables.js'; +import { + Type, + kAllScalarsAndVectors, + numElementsOf, + scalarTypeOf } from +'../../../../util/conversion.js'; import { ShaderValidationTest } from '../../shader_validation_test.js'; export const g = makeTestGroup(ShaderValidationTest); @@ -21,6 +28,137 @@ function vectorize(v, size) { return v; } +// A list of scalar and vector types. +const kScalarAndVectorTypes = objectsToRecord(kAllScalarsAndVectors); + +g.test('scalar_vector'). +desc( + ` + Validates that scalar and vector expressions are only accepted when the LHS is an integer and the RHS is abstract or unsigned. + ` +). +params((u) => +u. +combine('lhs', keysOf(kScalarAndVectorTypes)). +combine( + 'rhs', + // Skip vec3 and vec4 on the RHS to keep the number of subcases down. + keysOf(kScalarAndVectorTypes).filter( + (value) => !(value.startsWith('vec3') || value.startsWith('vec4')) + ) +). +beginSubcases(). +combine('op', ['<<', '>>']) +). +beforeAllSubcases((t) => { + if ( + scalarTypeOf(kScalarAndVectorTypes[t.params.lhs]) === Type.f16 || + scalarTypeOf(kScalarAndVectorTypes[t.params.rhs]) === Type.f16) + { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const lhs = kScalarAndVectorTypes[t.params.lhs]; + const rhs = kScalarAndVectorTypes[t.params.rhs]; + const lhsElement = scalarTypeOf(lhs); + const rhsElement = scalarTypeOf(rhs); + const hasF16 = lhsElement === Type.f16 || rhsElement === Type.f16; + const code = ` +${hasF16 ? 'enable f16;' : ''} +const lhs = ${lhs.create(0).wgsl()}; +const rhs = ${rhs.create(0).wgsl()}; +const foo = lhs ${t.params.op} rhs; +`; + + // The LHS must be an integer, and the RHS must be an abstract/unsigned integer. + // The vector widths must also match. + const lhs_valid = [Type.abstractInt, Type.i32, Type.u32].includes(lhsElement); + const rhs_valid = [Type.abstractInt, Type.u32].includes(rhsElement); + const valid = lhs_valid && rhs_valid && numElementsOf(lhs) === numElementsOf(rhs); + t.expectCompileResult(valid, code); +}); + + + + + + + +const kInvalidTypes = { + mat2x2f: { + expr: 'm', + control: (e) => `u32(${e}[0][0])` + }, + + array: { + expr: 'arr', + control: (e) => `${e}[0]` + }, + + ptr: { + expr: '(&u)', + control: (e) => `*${e}` + }, + + atomic: { + expr: 'a', + control: (e) => `atomicLoad(&${e})` + }, + + texture: { + expr: 't', + control: (e) => `u32(textureLoad(${e}, vec2(), 0).x)` + }, + + sampler: { + expr: 's', + control: (e) => `u32(textureSampleLevel(t, ${e}, vec2(), 0).x)` + }, + + struct: { + expr: 'str', + control: (e) => `${e}.u` + } +}; + +g.test('invalid_types'). +desc( + ` + Validates that expressions are never accepted for non-scalar and non-vector types. + ` +). +params((u) => +u. +combine('op', ['<<', '>>']). +combine('type', keysOf(kInvalidTypes)). +combine('control', [true, false]). +beginSubcases() +). +fn((t) => { + const type = kInvalidTypes[t.params.type]; + const expr = t.params.control ? type.control(type.expr) : type.expr; + const code = ` +@group(0) @binding(0) var t : texture_2d; +@group(0) @binding(1) var s : sampler; +@group(0) @binding(2) var a : atomic; + +struct S { u : u32 } + +var u : u32; +var m : mat2x2f; +var arr : array; +var str : S; + +@compute @workgroup_size(1) +fn main() { + let foo = ${expr} ${t.params.op} ${expr}; +} +`; + + t.expectCompileResult(t.params.control, code); +}); + const kLeftShiftCases = [ // rhs >= bitwidth fails { lhs: `0u`, rhs: `31u`, pass: true }, @@ -80,28 +218,6 @@ fn main() { t.expectCompileResult(t.params.case.pass, code); }); -g.test('shift_left_vec_size_mismatch'). -desc('Tests validation of binary left shift of vectors with mismatched sizes'). -params((u) => -u. -combine('vectorize_lhs', [2, 3, 4]) // -.combine('vectorize_rhs', [2, 3, 4]) -). -fn((t) => { - const lhs = `1`; - const rhs = `1`; - const lhs_vec_size = t.params.vectorize_lhs; - const rhs_vec_size = t.params.vectorize_rhs; - const code = ` -@compute @workgroup_size(1) -fn main() { - const r = ${vectorize(lhs, lhs_vec_size)} << ${vectorize(rhs, rhs_vec_size)}; -} - `; - const pass = lhs_vec_size === rhs_vec_size; - t.expectCompileResult(pass, code); -}); - const kRightShiftCases = [ // rhs >= bitwidth fails { lhs: `0u`, rhs: `31u`, pass: true }, @@ -141,26 +257,4 @@ fn main() { } `; t.expectCompileResult(t.params.case.pass, code); -}); - -g.test('shift_right_vec_size_mismatch'). -desc('Tests validation of binary right shift of vectors with mismatched sizes'). -params((u) => -u. -combine('vectorize_lhs', [2, 3, 4]) // -.combine('vectorize_rhs', [2, 3, 4]) -). -fn((t) => { - const lhs = `1`; - const rhs = `1`; - const lhs_vec_size = t.params.vectorize_lhs; - const rhs_vec_size = t.params.vectorize_rhs; - const code = ` -@compute @workgroup_size(1) -fn main() { - const r = ${vectorize(lhs, lhs_vec_size)} >> ${vectorize(rhs, rhs_vec_size)}; -} - `; - const pass = lhs_vec_size === rhs_vec_size; - t.expectCompileResult(pass, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/comparison.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/comparison.spec.js new file mode 100644 index 0000000000..75ab1b6daa --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/comparison.spec.js @@ -0,0 +1,186 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for comparison expressions. +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../common/util/data_tables.js'; +import { + isFloatType, + kAllScalarsAndVectors, + ScalarType, + scalarTypeOf, + Type, + VectorType } from +'../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// A list of scalar and vector types. +const kScalarAndVectorTypes = objectsToRecord(kAllScalarsAndVectors); + +// A list of comparison operators and a flag for whether they support boolean values or not. +const kComparisonOperators = { + eq: { op: '==', supportsBool: true }, + ne: { op: '!=', supportsBool: true }, + gt: { op: '>', supportsBool: false }, + ge: { op: '>=', supportsBool: false }, + lt: { op: '<', supportsBool: false }, + le: { op: '<=', supportsBool: false } +}; + +g.test('scalar_vector'). +desc( + ` + Validates that scalar and vector comparison expressions are only accepted for compatible types. + ` +). +params((u) => +u. +combine('lhs', keysOf(kScalarAndVectorTypes)). +combine( + 'rhs', + // Skip vec3 and vec4 on the RHS to keep the number of subcases down. + keysOf(kScalarAndVectorTypes).filter( + (value) => !(value.startsWith('vec3') || value.startsWith('vec4')) + ) +). +beginSubcases(). +combine('op', keysOf(kComparisonOperators)) +). +beforeAllSubcases((t) => { + if ( + scalarTypeOf(kScalarAndVectorTypes[t.params.lhs]) === Type.f16 || + scalarTypeOf(kScalarAndVectorTypes[t.params.rhs]) === Type.f16) + { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const lhs = kScalarAndVectorTypes[t.params.lhs]; + const rhs = kScalarAndVectorTypes[t.params.rhs]; + const lhsElement = scalarTypeOf(lhs); + const rhsElement = scalarTypeOf(rhs); + const hasF16 = lhsElement === Type.f16 || rhsElement === Type.f16; + const code = ` +${hasF16 ? 'enable f16;' : ''} +const lhs = ${lhs.create(0).wgsl()}; +const rhs = ${rhs.create(0).wgsl()}; +const foo = lhs ${kComparisonOperators[t.params.op].op} rhs; +`; + + let valid = false; + + // Determine if the element types are comparable. + let elementIsCompatible = false; + if (lhsElement === Type.abstractInt) { + // Abstract integers are comparable to any other numeric type. + elementIsCompatible = rhsElement !== Type.bool; + } else if (rhsElement === Type.abstractInt) { + // Abstract integers are comparable to any other numeric type. + elementIsCompatible = lhsElement !== Type.bool; + } else if (lhsElement === Type.abstractFloat) { + // Abstract floats are comparable to any other float type. + elementIsCompatible = isFloatType(rhsElement); + } else if (rhsElement === Type.abstractFloat) { + // Abstract floats are comparable to any other float type. + elementIsCompatible = isFloatType(lhsElement); + } else { + // Non-abstract types are only comparable to values with the exact same type. + elementIsCompatible = lhsElement === rhsElement; + } + + // Determine if the full type is comparable. + if (lhs instanceof ScalarType && rhs instanceof ScalarType) { + valid = elementIsCompatible; + } else if (lhs instanceof VectorType && rhs instanceof VectorType) { + // Vectors are only comparable if the vector widths match. + valid = lhs.width === rhs.width && elementIsCompatible; + } + + if (lhsElement === Type.bool) { + valid &&= kComparisonOperators[t.params.op].supportsBool; + } + + t.expectCompileResult(valid, code); +}); + + + + + + + +const kInvalidTypes = { + mat2x2f: { + expr: 'm', + control: (e) => `${e}[0]` + }, + + array: { + expr: 'arr', + control: (e) => `${e}[0]` + }, + + ptr: { + expr: '(&u)', + control: (e) => `*${e}` + }, + + atomic: { + expr: 'a', + control: (e) => `atomicLoad(&${e})` + }, + + texture: { + expr: 't', + control: (e) => `textureLoad(${e}, vec2(), 0)` + }, + + sampler: { + expr: 's', + control: (e) => `textureSampleLevel(t, ${e}, vec2(), 0)` + }, + + struct: { + expr: 'str', + control: (e) => `${e}.u` + } +}; + +g.test('invalid_types'). +desc( + ` + Validates that comparison expressions are never accepted for non-scalar and non-vector types. + ` +). +params((u) => +u. +combine('op', keysOf(kComparisonOperators)). +combine('type', keysOf(kInvalidTypes)). +combine('control', [true, false]). +beginSubcases() +). +fn((t) => { + const type = kInvalidTypes[t.params.type]; + const expr = t.params.control ? type.control(type.expr) : type.expr; + const code = ` +@group(0) @binding(0) var t : texture_2d; +@group(0) @binding(1) var s : sampler; +@group(0) @binding(2) var a : atomic; + +struct S { u : u32 } + +var u : u32; +var m : mat2x2f; +var arr : array; +var str : S; + +@compute @workgroup_size(1) +fn main() { + let foo = ${expr} ${kComparisonOperators[t.params.op].op} ${expr}; +} +`; + + t.expectCompileResult(t.params.control, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/div_rem.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/div_rem.spec.js new file mode 100644 index 0000000000..75d26c4132 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/binary/div_rem.spec.js @@ -0,0 +1,279 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for division and remainder expressions. +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../common/util/data_tables.js'; +import { assert } from '../../../../../common/util/util.js'; +import { kBit } from '../../../../util/constants.js'; +import { + ScalarType, + Type, + + VectorType, + kAllScalarsAndVectors, + kConcreteNumericScalarsAndVectors, + kConvertableToFloatScalar, + scalarTypeOf } from +'../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../shader_validation_test.js'; +import { + kConstantAndOverrideStages, + validateConstOrOverrideBinaryOpEval } from +'../call/builtin/const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// A list of operators tested in this file. +const kOperators = { + div: { op: '/' }, + rem: { op: '%' } +}; + +// A list of scalar and vector types. +const kScalarAndVectorTypes = objectsToRecord(kAllScalarsAndVectors); +const kConcreteNumericScalarAndVectorTypes = objectsToRecord(kConcreteNumericScalarsAndVectors); + +g.test('scalar_vector'). +desc( + ` + Validates that scalar and vector expressions are only accepted for compatible numeric types. + ` +). +params((u) => +u. +combine('lhs', keysOf(kScalarAndVectorTypes)). +combine( + 'rhs', + // Skip vec3 and vec4 on the RHS to keep the number of subcases down. + // vec3 + vec3 and vec4 + vec4 is tested in execution tests. + keysOf(kScalarAndVectorTypes).filter( + (value) => !(value.startsWith('vec3') || value.startsWith('vec4')) + ) +). +beginSubcases(). +combine('op', keysOf(kOperators)) +). +beforeAllSubcases((t) => { + if ( + scalarTypeOf(kScalarAndVectorTypes[t.params.lhs]) === Type.f16 || + scalarTypeOf(kScalarAndVectorTypes[t.params.rhs]) === Type.f16) + { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const op = kOperators[t.params.op]; + const lhs = kScalarAndVectorTypes[t.params.lhs]; + const rhs = kScalarAndVectorTypes[t.params.rhs]; + const lhsElement = scalarTypeOf(lhs); + const rhsElement = scalarTypeOf(rhs); + const hasF16 = lhsElement === Type.f16 || rhsElement === Type.f16; + const code = ` +${hasF16 ? 'enable f16;' : ''} +const lhs = ${lhs.create(1).wgsl()}; +const rhs = ${rhs.create(1).wgsl()}; +const foo = lhs ${op.op} rhs; +`; + + let elementsCompatible = lhsElement === rhsElement; + const elementTypes = [lhsElement, rhsElement]; + + // Booleans are not allowed for arithmetic expressions. + if (elementTypes.includes(Type.bool)) { + elementsCompatible = false; + + // AbstractInt is allowed with everything but booleans which are already checked above. + } else if (elementTypes.includes(Type.abstractInt)) { + elementsCompatible = true; + + // AbstractFloat is allowed with AbstractInt (checked above) or float types + } else if (elementTypes.includes(Type.abstractFloat)) { + elementsCompatible = elementTypes.every((e) => kConvertableToFloatScalar.includes(e)); + } + + // Determine if the full type is compatible. The only invalid case is mixed vector sizes. + let valid = elementsCompatible; + if (lhs instanceof VectorType && rhs instanceof VectorType) { + valid = valid && lhs.width === rhs.width; + } + + t.expectCompileResult(valid, code); +}); + +g.test('scalar_vector_out_of_range'). +desc( + ` + Checks that constant or override evaluation of div/rem operations on scalar/vectors that produce out of division by 0 or out of range values cause validation errors. + - Checks for all concrete numeric scalar and vector types, including scalar * vector and vector * scalar. + - Checks for all vector elements that could cause the out of range to happen. + - Checks for valid small cases and 0, also the minimum i32. + ` +). +params((u) => +u. +combine('op', keysOf(kOperators)). +combine('lhs', keysOf(kConcreteNumericScalarAndVectorTypes)). +expand('rhs', (p) => { + if (kScalarAndVectorTypes[p.lhs] instanceof VectorType) { + return [p.lhs, scalarTypeOf(kScalarAndVectorTypes[p.lhs]).toString()]; + } + return [p.lhs]; +}). +beginSubcases(). +expand('swap', (p) => { + if (p.lhs === p.rhs) { + return [false]; + } + return [false, true]; +}). +combine('nonOneIndex', [0, 1, 2, 3]). +filter((p) => { + const lType = kScalarAndVectorTypes[p.lhs]; + if (lType instanceof VectorType) { + return lType.width > p.nonOneIndex; + } + return p.nonOneIndex === 0; +}). +expandWithParams((p) => { + const cases = [ + { leftValue: 42, rightValue: 0, error: true, leftRuntime: false }, + { leftValue: 42, rightValue: 0, error: true, leftRuntime: true }, + { leftValue: 0, rightValue: 0, error: true, leftRuntime: true }, + { leftValue: 0, rightValue: 42, error: false, leftRuntime: false }]; + + if (p.lhs === 'i32') { + cases.push({ + leftValue: -kBit.i32.negative.min, + rightValue: -1, + error: true, + leftRuntime: false + }); + cases.push({ + leftValue: -kBit.i32.negative.min + 1, + rightValue: -1, + error: false, + leftRuntime: false + }); + } + return cases; +}). +combine('stage', kConstantAndOverrideStages) +). +beforeAllSubcases((t) => { + if ( + scalarTypeOf(kScalarAndVectorTypes[t.params.lhs]) === Type.f16 || + scalarTypeOf(kScalarAndVectorTypes[t.params.rhs]) === Type.f16) + { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const { op, leftValue, rightValue, error, leftRuntime, nonOneIndex, swap } = t.params; + let { lhs, rhs } = t.params; + + // Handle the swapping of LHS and RHS to test all cases of scalar * vector. + if (swap) { + [rhs, lhs] = [lhs, rhs]; + } + + // Creates either a scalar with the value, or a vector with the value only at a specific index. + const create = (type, index, value) => { + if (type instanceof ScalarType) { + return type.create(value); + } else { + assert(type instanceof VectorType); + const values = new Array(type.width); + values.fill(1); + values[index] = value; + return type.create(values); + } + }; + + // Check if there is overflow + validateConstOrOverrideBinaryOpEval( + t, + kOperators[op].op, + !error, + leftRuntime ? 'runtime' : t.params.stage, + create(kScalarAndVectorTypes[lhs], nonOneIndex, leftValue), + t.params.stage, + create(kScalarAndVectorTypes[rhs], nonOneIndex, rightValue) + ); +}); + + + + + + + +const kInvalidTypes = { + array: { + expr: 'arr', + control: (e) => `${e}[0]` + }, + + ptr: { + expr: '(&u)', + control: (e) => `*${e}` + }, + + atomic: { + expr: 'a', + control: (e) => `atomicLoad(&${e})` + }, + + texture: { + expr: 't', + control: (e) => `i32(textureLoad(${e}, vec2(), 0).x)` + }, + + sampler: { + expr: 's', + control: (e) => `i32(textureSampleLevel(t, ${e}, vec2(), 0).x)` + }, + + struct: { + expr: 'str', + control: (e) => `${e}.u` + } +}; + +g.test('invalid_type_with_itself'). +desc( + ` + Validates that expressions are never accepted for non-scalar, non-vector, and non-matrix types. + ` +). +params((u) => +u. +combine('op', keysOf(kOperators)). +combine('type', keysOf(kInvalidTypes)). +combine('control', [true, false]). +beginSubcases() +). +fn((t) => { + const op = kOperators[t.params.op]; + const type = kInvalidTypes[t.params.type]; + const expr = t.params.control ? type.control(type.expr) : type.expr; + const code = ` +@group(0) @binding(0) var t : texture_2d; +@group(0) @binding(1) var s : sampler; +@group(0) @binding(2) var a : atomic; + +struct S { u : u32 } + +var u : u32; +var m : mat2x2f; +var arr : array; +var str : S; + +@compute @workgroup_size(1) +fn main() { + let foo = ${expr} ${op.op} ${expr}; +} +`; + + t.expectCompileResult(t.params.control, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/abs.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/abs.spec.js index 255c8ab2e2..5492d8cd1a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/abs.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/abs.spec.js @@ -6,9 +6,9 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - elementType, - kAllFloatAndIntegerScalarsAndVectors } from + Type, + kAllNumericScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -21,7 +21,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatAndIntegerScalarsAndVectors); +const kValuesTypes = objectsToRecord(kAllNumericScalarsAndVectors); g.test('values'). desc( @@ -38,7 +38,7 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -51,4 +51,108 @@ fn((t) => { [kValuesTypes[t.params.type].create(t.params.value)], t.params.stage ); +}); + +const kTests = { + valid: { + src: `_ = abs(1);`, + pass: true + }, + alias: { + src: `_ = abs(i32_alias(1));`, + pass: true + }, + + bool: { + src: `_ = abs(false);`, + pass: false + }, + vec_bool: { + src: `_ = abs(vec2(false, true));`, + pass: false + }, + matrix: { + src: `_ = abs(mat2x2(1, 1, 1, 1));`, + pass: false + }, + atomic: { + src: ` _ = abs(a);`, + pass: false + }, + array: { + src: `var a: array; + _ = abs(a);`, + pass: false + }, + array_runtime: { + src: `_ = abs(k.arry);`, + pass: false + }, + struct: { + src: `var a: A; + _ = abs(a);`, + pass: false + }, + enumerant: { + src: `_ = abs(read_write);`, + pass: false + }, + ptr: { + src: `var a = 1u; + let p: ptr = &a; + _ = abs(p);`, + pass: false + }, + ptr_deref: { + src: `var a = 1u; + let p: ptr = &a; + _ = abs(*p);`, + pass: true + }, + sampler: { + src: `_ = abs(s);`, + pass: false + }, + texture: { + src: `_ = abs(t);`, + pass: false + }, + no_params: { + src: `_ = abs();`, + pass: false + }, + too_many_params: { + src: `_ = abs(1, 2);`, + pass: false + } +}; + +g.test('parameters'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const src = kTests[t.params.test].src; + const code = ` +alias i32_alias = i32; + +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: texture_2d; + +var a: atomic; + +struct A { + i: u32, +} +struct B { + arry: array, +} +@group(0) @binding(3) var k: B; + + +@vertex +fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); +}`; + t.expectCompileResult(kTests[t.params.test].pass, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/acos.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/acos.spec.js index d7caeca828..fdc7c9e0aa 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/acos.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/acos.spec.js @@ -6,18 +6,18 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; +import { absBigInt } from '../../../../../util/math.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kMinusTwoToTwo, + minusTwoToTwoRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -25,7 +25,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -39,15 +39,23 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('value', (u) => unique(kMinusTwoToTwo, fullRangeForType(kValuesTypes[u.type]))) +expand('value', (u) => +unique( + minusTwoToTwoRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type]) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { - const expectedResult = Math.abs(t.params.value) <= 1; + const expectedResult = + typeof t.params.value === 'bigint' ? + absBigInt(t.params.value) <= 1n : + Math.abs(t.params.value) <= 1; validateConstOrOverrideBuiltinEval( t, builtin, @@ -57,7 +65,8 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +// f32 is included here to confirm that validation is failing due to a type issue and not something else. +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -71,8 +80,137 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(0)], 'constant' ); +}); + +const kTests = { + valid: { + src: `_ = acos(1);`, + pass: true + }, + alias: { + src: `_ = acos(f32_alias(1));`, + pass: true + }, + + bool: { + src: `_ = acos(false);`, + pass: false + }, + i32: { + src: `_ = acos(1i);`, + pass: false + }, + u32: { + src: `_ = acos(1u);`, + pass: false + }, + vec_bool: { + src: `_ = acos(vec2(false, true));`, + pass: false + }, + vec_i32: { + src: `_ = acos(vec2(1, 1));`, + pass: false + }, + vec_u32: { + src: `_ = acos(vec2(1, 1));`, + pass: false + }, + matrix: { + src: `_ = acos(mat2x2(1, 1, 1, 1));`, + pass: false + }, + atomic: { + src: ` _ = acos(a);`, + pass: false + }, + array: { + src: `var a: array; + _ = acos(a);`, + pass: false + }, + array_runtime: { + src: `_ = acos(k.arry);`, + pass: false + }, + struct: { + src: `var a: A; + _ = acos(a);`, + pass: false + }, + enumerant: { + src: `_ = acos(read_write);`, + pass: false + }, + ptr: { + src: `var a = 1f; + let p: ptr = &a; + _ = acos(p);`, + pass: false + }, + ptr_deref: { + src: `var a = 1f; + let p: ptr = &a; + _ = acos(*p);`, + pass: true + }, + sampler: { + src: `_ = acos(s);`, + pass: false + }, + texture: { + src: `_ = acos(t);`, + pass: false + }, + no_params: { + src: `_ = acos();`, + pass: false + }, + too_many_params: { + src: `_ = acos(1, 2);`, + pass: false + }, + + greater_then_one: { + src: `_ = acos(1.1f);`, + pass: false + }, + less_then_negative_one: { + src: `_ = acos(-1.1f);`, + pass: false + } +}; + +g.test('parameters'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const src = kTests[t.params.test].src; + const code = ` +alias f32_alias = f32; + +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: texture_2d; + +var a: atomic; + +struct A { + i: u32, +} +struct B { + arry: array, +} +@group(0) @binding(3) var k: B; + + +@vertex +fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); +}`; + t.expectCompileResult(kTests[t.params.test].pass, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/acosh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/acosh.spec.js index 037d058fb6..5db033436f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/acosh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/acosh.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -18,7 +17,7 @@ import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kMinusTwoToTwo, + minusTwoToTwoRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -26,7 +25,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -40,16 +39,25 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('value', (u) => unique(fullRangeForType(kValuesTypes[u.type]), kMinusTwoToTwo)) +expand('value', (u) => +unique( + minusTwoToTwoRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type]) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; - const expectedResult = isRepresentable(Math.acosh(t.params.value), elementType(type)); + const expectedResult = isRepresentable( + Math.acosh(Number(t.params.value)), + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); validateConstOrOverrideBuiltinEval( t, builtin, @@ -59,7 +67,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord(kConcreteIntegerScalarsAndVectors); g.test('integer_argument'). desc( @@ -73,8 +81,132 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, - [type.create(1)], + /* expectedResult */type === Type.f32, + [type.create(type === Type.abstractInt ? 1n : 1)], 'constant' ); +}); + +const kTests = { + valid: { + src: `_ = acosh(1);`, + pass: true + }, + alias: { + src: `_ = acosh(f32_alias(1));`, + pass: true + }, + + bool: { + src: `_ = acosh(false);`, + pass: false + }, + i32: { + src: `_ = acosh(1i);`, + pass: false + }, + u32: { + src: `_ = acosh(1u);`, + pass: false + }, + vec_bool: { + src: `_ = acosh(vec2(false, true));`, + pass: false + }, + vec_i32: { + src: `_ = acosh(vec2(1, 1));`, + pass: false + }, + vec_u32: { + src: `_ = acosh(vec2(1, 1));`, + pass: false + }, + matrix: { + src: `_ = acosh(mat2x2(1, 1, 1, 1));`, + pass: false + }, + atomic: { + src: ` _ = acosh(a);`, + pass: false + }, + array: { + src: `var a: array; + _ = acosh(a);`, + pass: false + }, + array_runtime: { + src: `_ = acosh(k.arry);`, + pass: false + }, + struct: { + src: `var a: A; + _ = acosh(a);`, + pass: false + }, + enumerant: { + src: `_ = acosh(read_write);`, + pass: false + }, + ptr: { + src: `var a = 1f; + let p: ptr = &a; + _ = acosh(p);`, + pass: false + }, + ptr_deref: { + src: `var a = 1f; + let p: ptr = &a; + _ = acosh(*p);`, + pass: true + }, + sampler: { + src: `_ = acosh(s);`, + pass: false + }, + texture: { + src: `_ = acosh(t);`, + pass: false + }, + no_params: { + src: `_ = acosh();`, + pass: false + }, + too_many_params: { + src: `_ = acosh(1, 2);`, + pass: false + }, + + less_then_one: { + src: `_ = acosh(.9f);`, + pass: false + } +}; + +g.test('parameters'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const src = kTests[t.params.test].src; + const code = ` +alias f32_alias = f32; + +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: texture_2d; + +var a: atomic; + +struct A { + i: u32, +} +struct B { + arry: array, +} +@group(0) @binding(3) var k: B; + +@vertex +fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); +}`; + t.expectCompileResult(kTests[t.params.test].pass, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/all.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/all.spec.js new file mode 100644 index 0000000000..83d2cfaf82 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/all.spec.js @@ -0,0 +1,191 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'all';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { Type, elementTypeOf, kAllScalarsAndVectors } from '../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { validateConstOrOverrideBuiltinEval } from './const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kArgumentTypes = objectsToRecord(kAllScalarsAndVectors); + +g.test('argument_types'). +desc( + ` +Validates that scalar and vector arguments are rejected by ${builtin}() if not bool or vecN +` +). +params((u) => u.combine('type', keysOf(kArgumentTypes))). +fn((t) => { + const type = kArgumentTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */elementTypeOf(type) === Type.bool, + [type.create(0)], + 'constant', + /* returnType */Type.bool + ); +}); + +const kTests = { + valid: { + src: `_ = ${builtin}(true);`, + pass: true + }, + alias: { + src: `_ = ${builtin}(bool_alias(true));`, + pass: true + }, + bool: { + src: `_ = ${builtin}(false);`, + pass: true + }, + i32: { + src: `_ = ${builtin}(1i);`, + pass: false + }, + u32: { + src: `_ = ${builtin}(1u);`, + pass: false + }, + f32: { + src: `_ = ${builtin}(1.0f);`, + pass: false + }, + f16: { + src: `_ = ${builtin}(1.0h);`, + pass: false + }, + vec_bool: { + src: `_ = ${builtin}(vec2(false, true));`, + pass: true + }, + vec2_bool_implicit: { + src: `_ = ${builtin}(vec2(false, true));`, + pass: true + }, + vec3_bool_implicit: { + src: `_ = ${builtin}(vec3(true));`, + pass: true + }, + vec_i32: { + src: `_ = ${builtin}(vec2(1, 1));`, + pass: false + }, + vec_u32: { + src: `_ = ${builtin}(vec2(1, 1));`, + pass: false + }, + vec_f32: { + src: `_ = ${builtin}(vec2(1, 1));`, + pass: false + }, + vec_f16: { + src: `_ = ${builtin}(vec2(1, 1));`, + pass: false + }, + matrix: { + src: `_ = ${builtin}(mat2x2(1, 1, 1, 1));`, + pass: false + }, + atomic: { + src: ` _ = ${builtin}(a);`, + pass: false + }, + array: { + src: `var a: array; + _ = ${builtin}(a);`, + pass: false + }, + array_runtime: { + src: `_ = ${builtin}(k.arry);`, + pass: false + }, + struct: { + src: `var a: A; + _ = ${builtin}(a);`, + pass: false + }, + enumerant: { + src: `_ = ${builtin}(read_write);`, + pass: false + }, + ptr: { + src: `var a = true; + let p: ptr = &a; + _ = ${builtin}(p);`, + pass: false + }, + ptr_deref: { + src: `var a = true; + let p: ptr = &a; + _ = ${builtin}(*p);`, + pass: true + }, + sampler: { + src: `_ = ${builtin}(s);`, + pass: false + }, + texture: { + src: `_ = ${builtin}(t);`, + pass: false + }, + no_args: { + src: `_ = ${builtin}();`, + pass: false + }, + too_many_args: { + src: `_ = ${builtin}(true, true);`, + pass: false + } +}; + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(true); }`); +}); + +g.test('arguments'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +beforeAllSubcases((t) => { + if (t.params.test.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const src = kTests[t.params.test].src; + const enables = t.params.test.includes('f16') ? 'enable f16;' : ''; + const code = ` + ${enables} + alias bool_alias = bool; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: bool, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + @vertex + fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); + }`; + t.expectCompileResult(kTests[t.params.test].pass, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/any.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/any.spec.js new file mode 100644 index 0000000000..7298c94130 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/any.spec.js @@ -0,0 +1,191 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'any';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { Type, elementTypeOf, kAllScalarsAndVectors } from '../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { validateConstOrOverrideBuiltinEval } from './const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kArgumentTypes = objectsToRecord(kAllScalarsAndVectors); + +g.test('argument_types'). +desc( + ` +Validates that scalar and vector arguments are rejected by ${builtin}() if not bool or vecN +` +). +params((u) => u.combine('type', keysOf(kArgumentTypes))). +fn((t) => { + const type = kArgumentTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */elementTypeOf(type) === Type.bool, + [type.create(0)], + 'constant', + /* returnType */Type.bool + ); +}); + +const kTests = { + valid: { + src: `_ = ${builtin}(true);`, + pass: true + }, + alias: { + src: `_ = ${builtin}(bool_alias(true));`, + pass: true + }, + bool: { + src: `_ = ${builtin}(false);`, + pass: true + }, + i32: { + src: `_ = ${builtin}(1i);`, + pass: false + }, + u32: { + src: `_ = ${builtin}(1u);`, + pass: false + }, + f32: { + src: `_ = ${builtin}(1.0f);`, + pass: false + }, + f16: { + src: `_ = ${builtin}(1.0h);`, + pass: false + }, + vec_bool: { + src: `_ = ${builtin}(vec2(false, true));`, + pass: true + }, + vec2_bool_implicit: { + src: `_ = ${builtin}(vec2(false, true));`, + pass: true + }, + vec3_bool_implicit: { + src: `_ = ${builtin}(vec3(true));`, + pass: true + }, + vec_i32: { + src: `_ = ${builtin}(vec2(1, 1));`, + pass: false + }, + vec_u32: { + src: `_ = ${builtin}(vec2(1, 1));`, + pass: false + }, + vec_f32: { + src: `_ = ${builtin}(vec2(1, 1));`, + pass: false + }, + vec_f16: { + src: `_ = ${builtin}(vec2(1, 1));`, + pass: false + }, + matrix: { + src: `_ = ${builtin}(mat2x2(1, 1, 1, 1));`, + pass: false + }, + atomic: { + src: ` _ = ${builtin}(a);`, + pass: false + }, + array: { + src: `var a: array; + _ = ${builtin}(a);`, + pass: false + }, + array_runtime: { + src: `_ = ${builtin}(k.arry);`, + pass: false + }, + struct: { + src: `var a: A; + _ = ${builtin}(a);`, + pass: false + }, + enumerant: { + src: `_ = ${builtin}(read_write);`, + pass: false + }, + ptr: { + src: `var a = true; + let p: ptr = &a; + _ = ${builtin}(p);`, + pass: false + }, + ptr_deref: { + src: `var a = true; + let p: ptr = &a; + _ = ${builtin}(*p);`, + pass: true + }, + sampler: { + src: `_ = ${builtin}(s);`, + pass: false + }, + texture: { + src: `_ = ${builtin}(t);`, + pass: false + }, + no_args: { + src: `_ = ${builtin}();`, + pass: false + }, + too_many_args: { + src: `_ = ${builtin}(true, true);`, + pass: false + } +}; + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(true); }`); +}); + +g.test('arguments'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +beforeAllSubcases((t) => { + if (t.params.test.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const src = kTests[t.params.test].src; + const enables = t.params.test.includes('f16') ? 'enable f16;' : ''; + const code = ` + ${enables} + alias bool_alias = bool; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: bool, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + @vertex + fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); + }`; + t.expectCompileResult(kTests[t.params.test].pass, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/arrayLength.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/arrayLength.spec.js new file mode 100644 index 0000000000..9a18b77e36 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/arrayLength.spec.js @@ -0,0 +1,109 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for arrayLength builtins. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('bool_type'). +specURL('https://www.w3.org/TR/WGSL/#arrayLength-builtin'). +desc( + ` +arrayLength accepts only runtime-sized arrays +` +). +fn((t) => { + const code = ` +@compute @workgroup_size(1) +fn main() { + var b = true; + _ = arrayLength(&b); +}`; + + t.expectCompileResult(false, code); +}); + +const atomic_types = ['u32', 'i32'].map((j) => `atomic<${j}>`); +const vec_types = [2, 3, 4]. +map((i) => ['i32', 'u32', 'f32', 'f16'].map((j) => `vec${i}<${j}>`)). +reduce((a, c) => a.concat(c), []); +const f32_matrix_types = [2, 3, 4]. +map((i) => [2, 3, 4].map((j) => `mat${i}x${j}f`)). +reduce((a, c) => a.concat(c), []); +const f16_matrix_types = [2, 3, 4]. +map((i) => [2, 3, 4].map((j) => `mat${i}x${j}`)). +reduce((a, c) => a.concat(c), []); + +g.test('type'). +specURL('https://www.w3.org/TR/WGSL/#arrayLength-builtin'). +desc( + ` +arrayLength accepts only runtime-sized arrays +` +). +params((u) => +u.combine('type', [ +'i32', +'u32', +'f32', +'f16', +...f32_matrix_types, +...f16_matrix_types, +...vec_types, +...atomic_types, +'T', +'array', +'array'] +) +). +beforeAllSubcases((t) => { + if (t.params.type.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const code = ` +struct T { + b: i32, +} +struct S { + ary: ${t.params.type} +} + +@group(0) @binding(0) var items: S; + +@compute @workgroup_size(1) +fn main() { + _ = arrayLength(&items.ary); +}`; + + t.expectCompileResult(t.params.type === 'array', code); +}); + +// Note, the `write` case actually fails because you can't declare a storage buffer of +// access_mode `write`. +g.test('access_mode'). +specURL('https://www.w3.org/TR/WGSL/#arrayLength-builtin'). +desc( + ` +arrayLength runtime-sized array must have an access_mode of read or read_write +` +). +params((u) => u.combine('mode', ['read', 'read_write', 'write'])). +fn((t) => { + const code = ` +struct S { + ary: array, +} + +@group(0) @binding(0) var items: S; + +@compute @workgroup_size(1) +fn main() { + _ = arrayLength(&items.ary); +}`; + + t.expectCompileResult(t.params.mode !== 'write', code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/asin.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/asin.spec.js index ec5c51fe15..957d829ce0 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/asin.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/asin.spec.js @@ -6,18 +6,18 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; +import { absBigInt } from '../../../../../util/math.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kMinusTwoToTwo, + minusTwoToTwoRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -25,7 +25,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -39,15 +39,23 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('value', (u) => unique(kMinusTwoToTwo, fullRangeForType(kValuesTypes[u.type]))) +expand('value', (u) => +unique( + minusTwoToTwoRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type]) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { - const expectedResult = Math.abs(t.params.value) <= 1; + const expectedResult = + typeof t.params.value === 'bigint' ? + absBigInt(t.params.value) <= 1n : + Math.abs(t.params.value) <= 1; validateConstOrOverrideBuiltinEval( t, builtin, @@ -57,7 +65,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -71,8 +79,137 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(0)], 'constant' ); +}); + +const kTests = { + valid: { + src: `_ = asin(1);`, + pass: true + }, + alias: { + src: `_ = asin(f32_alias(1));`, + pass: true + }, + + bool: { + src: `_ = asin(false);`, + pass: false + }, + i32: { + src: `_ = asin(1i);`, + pass: false + }, + u32: { + src: `_ = asin(1u);`, + pass: false + }, + vec_bool: { + src: `_ = asin(vec2(false, true));`, + pass: false + }, + vec_i32: { + src: `_ = asin(vec2(1, 1));`, + pass: false + }, + vec_u32: { + src: `_ = asin(vec2(1, 1));`, + pass: false + }, + matrix: { + src: `_ = asin(mat2x2(1, 1, 1, 1));`, + pass: false + }, + atomic: { + src: ` _ = asin(a);`, + pass: false + }, + array: { + src: `var a: array; + _ = asin(a);`, + pass: false + }, + array_runtime: { + src: `_ = asin(k.arry);`, + pass: false + }, + struct: { + src: `var a: A; + _ = asin(a);`, + pass: false + }, + enumerant: { + src: `_ = asin(read_write);`, + pass: false + }, + ptr: { + src: `var a = 1f; + let p: ptr = &a; + _ = asin(p);`, + pass: false + }, + ptr_deref: { + src: `var a = 1f; + let p: ptr = &a; + _ = asin(*p);`, + pass: true + }, + sampler: { + src: `_ = asin(s);`, + pass: false + }, + texture: { + src: `_ = asin(t);`, + pass: false + }, + no_params: { + src: `_ = asin();`, + pass: false + }, + too_many_params: { + src: `_ = asin(1, 2);`, + pass: false + }, + + greater_then_one: { + src: `_ = asin(1.1f);`, + pass: false + }, + less_then_negative_one: { + src: `_ = asin(-1.1f);`, + pass: false + } +}; + +g.test('parameters'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const src = kTests[t.params.test].src; + const code = ` +alias f32_alias = f32; + +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: texture_2d; + +var a: atomic; + +struct A { + i: u32, +} +struct B { + arry: array, +} +@group(0) @binding(3) var k: B; + + +@vertex +fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); +}`; + t.expectCompileResult(kTests[t.params.test].pass, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/asinh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/asinh.spec.js index ccc73de0fc..e357a0760d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/asinh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/asinh.spec.js @@ -6,19 +6,19 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf, + Type } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; -import { linearRange } from '../../../../../util/math.js'; +import { linearRange, linearRangeBigInt } from '../../../../../util/math.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, + rangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -26,7 +26,12 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); + +const additionalRangeForType = rangeForType( + linearRange(-2000, 2000, 10), + linearRangeBigInt(-2000n, 2000n, 10) +); g.test('values'). desc( @@ -41,17 +46,21 @@ combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). expand('value', (u) => -unique(fullRangeForType(kValuesTypes[u.type]), linearRange(-2000, 2000, 10)) +unique(fullRangeForType(kValuesTypes[u.type]), additionalRangeForType(kValuesTypes[u.type])) ) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; - const expectedResult = isRepresentable(Math.asinh(t.params.value), elementType(type)); + const expectedResult = isRepresentable( + Math.asinh(Number(t.params.value)), + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); validateConstOrOverrideBuiltinEval( t, builtin, @@ -61,7 +70,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -75,8 +84,128 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(1)], 'constant' ); +}); + +const kTests = { + valid: { + src: `_ = asinh(1);`, + pass: true + }, + alias: { + src: `_ = asinh(f32_alias(1));`, + pass: true + }, + + bool: { + src: `_ = asinh(false);`, + pass: false + }, + i32: { + src: `_ = asinh(1i);`, + pass: false + }, + u32: { + src: `_ = asinh(1u);`, + pass: false + }, + vec_bool: { + src: `_ = asinh(vec2(false, true));`, + pass: false + }, + vec_i32: { + src: `_ = asinh(vec2(1, 1));`, + pass: false + }, + vec_u32: { + src: `_ = asinh(vec2(1, 1));`, + pass: false + }, + matrix: { + src: `_ = asinh(mat2x2(1, 1, 1, 1));`, + pass: false + }, + atomic: { + src: ` _ = asinh(a);`, + pass: false + }, + array: { + src: `var a: array; + _ = asinh(a);`, + pass: false + }, + array_runtime: { + src: `_ = asinh(k.arry);`, + pass: false + }, + struct: { + src: `var a: A; + _ = asinh(a);`, + pass: false + }, + enumerant: { + src: `_ = asinh(read_write);`, + pass: false + }, + ptr: { + src: `var a = 1f; + let p: ptr = &a; + _ = asinh(p);`, + pass: false + }, + ptr_deref: { + src: `var a = 1f; + let p: ptr = &a; + _ = asinh(*p);`, + pass: true + }, + sampler: { + src: `_ = asinh(s);`, + pass: false + }, + texture: { + src: `_ = asinh(t);`, + pass: false + }, + no_params: { + src: `_ = asinh();`, + pass: false + }, + too_many_params: { + src: `_ = asinh(1, 2);`, + pass: false + } +}; + +g.test('parameters'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const src = kTests[t.params.test].src; + const code = ` +alias f32_alias = f32; + +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: texture_2d; + +var a: atomic; + +struct A { + i: u32, +} +struct B { + arry: array, +} +@group(0) @binding(3) var k: B; + + +@vertex +fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); +}`; + t.expectCompileResult(kTests[t.params.test].pass, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atan.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atan.spec.js index 2cd971e678..19ff8902cb 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atan.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atan.spec.js @@ -6,18 +6,17 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kMinus3PiTo3Pi, + minusThreePiToThreePiRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -25,7 +24,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -39,10 +38,15 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('value', (u) => unique(kMinus3PiTo3Pi, fullRangeForType(kValuesTypes[u.type]))) +expand('value', (u) => +unique( + minusThreePiToThreePiRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type]) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -58,7 +62,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -72,8 +76,128 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(0)], 'constant' ); +}); + +const kTests = { + valid: { + src: `_ = atan(1);`, + pass: true + }, + alias: { + src: `_ = atan(f32_alias(1));`, + pass: true + }, + + bool: { + src: `_ = atan(false);`, + pass: false + }, + i32: { + src: `_ = atan(1i);`, + pass: false + }, + u32: { + src: `_ = atan(1u);`, + pass: false + }, + vec_bool: { + src: `_ = atan(vec2(false, true));`, + pass: false + }, + vec_i32: { + src: `_ = atan(vec2(1, 1));`, + pass: false + }, + vec_u32: { + src: `_ = atan(vec2(1, 1));`, + pass: false + }, + matrix: { + src: `_ = atan(mat2x2(1, 1, 1, 1));`, + pass: false + }, + atomic: { + src: ` _ = atan(a);`, + pass: false + }, + array: { + src: `var a: array; + _ = atan(a);`, + pass: false + }, + array_runtime: { + src: `_ = atan(k.arry);`, + pass: false + }, + struct: { + src: `var a: A; + _ = atan(a);`, + pass: false + }, + enumerant: { + src: `_ = atan(read_write);`, + pass: false + }, + ptr: { + src: `var a = 1f; + let p: ptr = &a; + _ = atan(p);`, + pass: false + }, + ptr_deref: { + src: `var a = 1f; + let p: ptr = &a; + _ = atan(*p);`, + pass: true + }, + sampler: { + src: `_ = atan(s);`, + pass: false + }, + texture: { + src: `_ = atan(t);`, + pass: false + }, + no_params: { + src: `_ = atan();`, + pass: false + }, + too_many_params: { + src: `_ = atan(1, 2);`, + pass: false + } +}; + +g.test('parameters'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const src = kTests[t.params.test].src; + const code = ` +alias f32_alias = f32; + +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: texture_2d; + +var a: atomic; + +struct A { + i: u32, +} +struct B { + arry: array, +} +@group(0) @binding(3) var k: B; + + +@vertex +fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); +}`; + t.expectCompileResult(kTests[t.params.test].pass, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atan2.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atan2.spec.js index e0fded50b1..999e07298d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atan2.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atan2.spec.js @@ -6,13 +6,13 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - Vector, - VectorType, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + VectorValue, + kFloatScalarsAndVectors, + kConcreteIntegerScalarsAndVectors, + kAllMatrices, + kAllBoolScalarsAndVectors, + scalarTypeOf, + Type } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -20,7 +20,7 @@ import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kSparseMinus3PiTo3Pi, + sparseMinusThreePiToThreePiRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -28,7 +28,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kFloatScalarsAndVectors); g.test('values'). desc( @@ -42,19 +42,29 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('y', (u) => unique(kSparseMinus3PiTo3Pi, fullRangeForType(kValuesTypes[u.type], 4))). -expand('x', (u) => unique(kSparseMinus3PiTo3Pi, fullRangeForType(kValuesTypes[u.type], 4))) +expand('y', (u) => +unique( + sparseMinusThreePiToThreePiRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type], 4) +) +). +expand('x', (u) => +unique( + sparseMinusThreePiToThreePiRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type], 4) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; const expectedResult = isRepresentable( - Math.abs(Math.atan2(t.params.y, t.params.x)), - elementType(type) + Math.abs(Math.atan2(Number(t.params.x), Number(t.params.y))), + scalarTypeOf(type) ); validateConstOrOverrideBuiltinEval( t, @@ -65,42 +75,275 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kInvalidArgumentTypes = objectsToRecord([ +Type.f32, +...kConcreteIntegerScalarsAndVectors, +...kAllBoolScalarsAndVectors, +...kAllMatrices] +); -g.test('integer_argument_y'). +g.test('invalid_argument_y'). desc( ` Validates that scalar and vector integer arguments are rejected by ${builtin}() ` ). -params((u) => u.combine('type', keysOf(kIntegerArgumentTypes))). +params((u) => u.combine('type', keysOf(kInvalidArgumentTypes))). fn((t) => { - const yTy = kIntegerArgumentTypes[t.params.type]; - const xTy = yTy instanceof Vector ? new VectorType(yTy.size, TypeF32) : TypeF32; + const yTy = kInvalidArgumentTypes[t.params.type]; + const xTy = yTy instanceof VectorValue ? Type.vec(yTy.size, Type.f32) : Type.f32; validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */yTy === TypeF32, + /* expectedResult */yTy === Type.f32, [yTy.create(1), xTy.create(1)], 'constant' ); }); -g.test('integer_argument_x'). +g.test('invalid_argument_x'). desc( ` Validates that scalar and vector integer arguments are rejected by ${builtin}() ` ). -params((u) => u.combine('type', keysOf(kIntegerArgumentTypes))). +params((u) => u.combine('type', keysOf(kInvalidArgumentTypes))). fn((t) => { - const xTy = kIntegerArgumentTypes[t.params.type]; - const yTy = xTy instanceof Vector ? new VectorType(xTy.size, TypeF32) : TypeF32; + const xTy = kInvalidArgumentTypes[t.params.type]; + const yTy = xTy instanceof VectorValue ? Type.vec(xTy.size, Type.f32) : Type.f32; validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */xTy === TypeF32, + /* expectedResult */xTy === Type.f32, [yTy.create(1), xTy.create(1)], 'constant' ); +}); + +const kTests = { + af: { + src: `_ = atan2(1.2, 2.2);`, + pass: true, + is_f16: false + }, + ai: { + src: `_ = atan2(1, 2);`, + pass: true, + is_f16: false + }, + ai_af: { + src: `_ = atan2(1, 2.1);`, + pass: true, + is_f16: false + }, + af_ai: { + src: `_ = atan2(1.2, 2);`, + pass: true, + is_f16: false + }, + ai_f32: { + src: `_ = atan2(1, 1.2f);`, + pass: true, + is_f16: false + }, + f32_ai: { + src: `_ = atan2(1.2f, 1);`, + pass: true, + is_f16: false + }, + af_f32: { + src: `_ = atan2(1.2, 2.2f);`, + pass: true, + is_f16: false + }, + f32_af: { + src: `_ = atan2(2.2f, 1.2);`, + pass: true, + is_f16: false + }, + f16_ai: { + src: `_ = atan2(1.2h, 1);`, + pass: true, + is_f16: true + }, + ai_f16: { + src: `_ = atan2(1, 1.2h);`, + pass: true, + is_f16: true + }, + af_f16: { + src: `_ = atan2(1.2, 1.2h);`, + pass: true, + is_f16: true + }, + f16_af: { + src: `_ = atan2(1.2h, 1.2);`, + pass: true, + is_f16: true + }, + + mixed_types: { + src: `_ = atan2(1.2f, vec2(1.2f));`, + pass: false, + is_f16: false + }, + mixed_types_2: { + src: `_ = atan2(vec2(1.2f), 1.2f);`, + pass: false, + is_f16: false + }, + f16_f32: { + src: `_ = atan2(1.2h, 1.2f);`, + pass: false, + is_f16: true + }, + u32_f32: { + src: `_ = atan2(1u, 1.2f);`, + pass: false, + is_f16: false + }, + f32_u32: { + src: `_ = atan2(1.2f, 1u);`, + pass: false, + is_f16: false + }, + f32_i32: { + src: `_ = atan2(1.2f, 1i);`, + pass: false, + is_f16: false + }, + i32_f32: { + src: `_ = atan2(1i, 1.2f);`, + pass: false, + is_f16: false + }, + f32_bool: { + src: `_ = atan2(1.2f, true);`, + pass: false, + is_f16: false + }, + bool_f32: { + src: `_ = atan2(false, 1.2f);`, + pass: false, + is_f16: false + }, + vec_f32: { + src: `_ = atan2(vec2(1i), vec2(1.2f));`, + pass: false, + is_f16: false + }, + f32_vec: { + src: `_ = atan2(vec2(1.2f), vec2(1i));`, + pass: false, + is_f16: false + }, + matrix: { + src: `_ = atan2(mat2x2(1, 1, 1, 1), mat2x2(1, 1, 1, 1));`, + pass: false, + is_f16: false + }, + atomic: { + src: ` _ = atan2(a, a);`, + pass: false, + is_f16: false + }, + array: { + src: `var a: array; + _ = atan2(a, a);`, + pass: false, + is_f16: false + }, + array_runtime: { + src: `_ = atan2(k.arry, k.arry);`, + pass: false, + is_f16: false + }, + struct: { + src: `var a: A; + _ = atan2(a, a);`, + pass: false, + is_f16: false + }, + enumerant: { + src: `_ = atan2(read_write, read_write);`, + pass: false, + is_f16: false + }, + ptr: { + src: `var a = 1f; + let p: ptr = &a; + _ = atan2(p, p);`, + pass: false, + is_f16: false + }, + ptr_deref: { + src: `var a = 1f; + let p: ptr = &a; + _ = atan2(*p, *p);`, + pass: true, + is_f16: false + }, + sampler: { + src: `_ = atan2(s, s);`, + pass: false, + is_f16: false + }, + texture: { + src: `_ = atan2(t, t);`, + pass: false, + is_f16: false + }, + no_params: { + src: `_ = atan2();`, + pass: false, + is_f16: false + }, + too_many_params: { + src: `_ = atan2(1, 2, 3);`, + pass: false, + is_f16: false + } +}; + +g.test('parameters'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +beforeAllSubcases((t) => { + if (kTests[t.params.test].is_f16 === true) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const src = kTests[t.params.test].src; + const code = ` +alias f32_alias = f32; + +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: texture_2d; + +var a: atomic; + +struct A { + i: u32, +} +struct B { + arry: array, +} +@group(0) @binding(3) var k: B; + + +@vertex +fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); +}`; + t.expectCompileResult(kTests[t.params.test].pass, code); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(1, 2); }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atanh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atanh.spec.js index e252551219..32fc3ec87b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atanh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atanh.spec.js @@ -6,18 +6,18 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; +import { absBigInt } from '../../../../../util/math.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kMinusTwoToTwo, + minusTwoToTwoRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -25,7 +25,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -39,15 +39,23 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('value', (u) => unique(kMinusTwoToTwo, fullRangeForType(kValuesTypes[u.type]))) +expand('value', (u) => +unique( + minusTwoToTwoRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type]) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { - const expectedResult = Math.abs(t.params.value) < 1; + const expectedResult = + typeof t.params.value === 'bigint' ? + absBigInt(t.params.value) < 1n : + Math.abs(t.params.value) < 1; validateConstOrOverrideBuiltinEval( t, builtin, @@ -57,7 +65,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -71,8 +79,145 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(0)], 'constant' ); +}); + +const kTests = { + valid: { + src: `_ = atanh(.1);`, + pass: true + }, + alias: { + src: `_ = atanh(f32_alias(.1));`, + pass: true + }, + + bool: { + src: `_ = atanh(false);`, + pass: false + }, + i32: { + src: `_ = atanh(0i);`, + pass: false + }, + u32: { + src: `_ = atanh(0u);`, + pass: false + }, + vec_bool: { + src: `_ = atanh(vec2(false, true));`, + pass: false + }, + vec_i32: { + src: `_ = atanh(vec2(0, 0));`, + pass: false + }, + vec_u32: { + src: `_ = atanh(vec2(0, 0));`, + pass: false + }, + matrix: { + src: `_ = atanh(mat2x2(0, 0, 0, 0));`, + pass: false + }, + atomic: { + src: ` _ = atanh(a);`, + pass: false + }, + array: { + src: `var a: array; + _ = atanh(a);`, + pass: false + }, + array_runtime: { + src: `_ = atanh(k.arry);`, + pass: false + }, + struct: { + src: `var a: A; + _ = atanh(a);`, + pass: false + }, + enumerant: { + src: `_ = atanh(read_write);`, + pass: false + }, + ptr: { + src: `var a = 0f; + let p: ptr = &a; + _ = atanh(p);`, + pass: false + }, + ptr_deref: { + src: `var a = 0f; + let p: ptr = &a; + _ = atanh(*p);`, + pass: true + }, + sampler: { + src: `_ = atanh(s);`, + pass: false + }, + texture: { + src: `_ = atanh(t);`, + pass: false + }, + no_params: { + src: `_ = atanh();`, + pass: false + }, + too_many_params: { + src: `_ = atanh(0, .2);`, + pass: false + }, + + one: { + src: `_ = atanh(1f);`, + pass: false + }, + greater_then_one: { + src: `_ = atanh(1.1f);`, + pass: false + }, + negative_one: { + src: `_ = atanh(-1f);`, + pass: false + }, + less_then_negative_one: { + src: `_ = atanh(-1.1f);`, + pass: false + } +}; + +g.test('parameters'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const src = kTests[t.params.test].src; + const code = ` +alias f32_alias = f32; + +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: texture_2d; + +var a: atomic; + +struct A { + i: u32, +} +struct B { + arry: array, +} +@group(0) @binding(3) var k: B; + + +@vertex +fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); +}`; + t.expectCompileResult(kTests[t.params.test].pass, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atomics.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atomics.spec.js index 3d51650c95..8756d61b3a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atomics.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/atomics.spec.js @@ -8,18 +8,44 @@ import { ShaderValidationTest } from '../../../shader_validation_test.js'; export const g = makeTestGroup(ShaderValidationTest); + + + + const kAtomicOps = { - add: { src: 'atomicAdd(&a,1)' }, - sub: { src: 'atomicSub(&a,1)' }, - max: { src: 'atomicMax(&a,1)' }, - min: { src: 'atomicMin(&a,1)' }, - and: { src: 'atomicAnd(&a,1)' }, - or: { src: 'atomicOr(&a,1)' }, - xor: { src: 'atomicXor(&a,1)' }, - load: { src: 'atomicLoad(&a)' }, - store: { src: 'atomicStore(&a,1)' }, - exchange: { src: 'atomicExchange(&a,1)' }, - compareexchangeweak: { src: 'atomicCompareExchangeWeak(&a,1,1)' } + add: (a) => { + return `atomicAdd(${a},1)`; + }, + sub: (a) => { + return `atomicSub(${a},1)`; + }, + max: (a) => { + return `atomicMax(${a},1)`; + }, + min: (a) => { + return `atomicMin(${a},1)`; + }, + and: (a) => { + return `atomicAnd(${a},1)`; + }, + or: (a) => { + return `atomicOr(${a},1)`; + }, + xor: (a) => { + return `atomicXor(${a},1)`; + }, + load: (a) => { + return `atomicLoad(${a})`; + }, + store: (a) => { + return `atomicStore(${a},1)`; + }, + exchange: (a) => { + return `atomicExchange(${a},1)`; + }, + compareexchangeweak: (a) => { + return `atomicCompareExchangeWeak(${a},1,1)`; + } }; g.test('stage'). @@ -35,7 +61,7 @@ combine('stage', ['fragment', 'vertex', 'compute']) // .combine('atomicOp', keysOf(kAtomicOps)) ). fn((t) => { - const atomicOp = kAtomicOps[t.params.atomicOp].src; + const atomicOp = kAtomicOps[t.params.atomicOp](`&a`); let code = ` @group(0) @binding(0) var a: atomic; `; @@ -67,4 +93,187 @@ fn((t) => { const pass = t.params.stage !== 'vertex'; t.expectCompileResult(pass, code); +}); + +function generateAtomicCode( +type, +access, +aspace, +style, +op) +{ + let moduleVar = ``; + let functionVar = ``; + let param = ``; + let aParam = ``; + if (style === 'var') { + aParam = `&a`; + switch (aspace) { + case 'storage': + moduleVar = `@group(0) @binding(0) var a : atomic<${type}>;\n`; + break; + case 'workgroup': + moduleVar = `var a : atomic<${type}>;\n`; + break; + case 'uniform': + moduleVar = `@group(0) @binding(0) var a : atomic<${type}>;\n`; + break; + case 'private': + moduleVar = `var a : atomic<${type}>;\n`; + break; + case 'function': + functionVar = `var a : atomic<${type}>;\n`; + break; + default: + break; + } + } else { + const aspaceParam = aspace === 'storage' ? `, ${access}` : ``; + param = `p : ptr<${aspace}, atomic<${type}>${aspaceParam}>`; + aParam = `p`; + } + + return ` +${moduleVar} +fn foo(${param}) { + ${functionVar} + ${kAtomicOps[op](aParam)}; +} +`; +} + +g.test('atomic_parameterization'). +desc('Tests the valid atomic parameters'). +params((u) => +u. +combine('op', keysOf(kAtomicOps)). +beginSubcases(). +combine('aspace', ['storage', 'workgroup', 'private', 'uniform', 'function']). +combine('access', ['read', 'read_write']). +combine('type', ['i32', 'u32']). +combine('style', ['param', 'var']). +filter((t) => { + switch (t.aspace) { + case 'uniform': + return t.style === 'param' && t.access === 'read'; + case 'workgroup': + return t.access === 'read_write'; + case 'function': + case 'private': + return t.style === 'param' && t.access === 'read_write'; + default: + return true; + } +}) +). +fn((t) => { + if ( + t.params.style === 'param' && + !(t.params.aspace === 'function' || t.params.aspace === 'private')) + { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + } + + const aspaceOK = t.params.aspace === 'storage' || t.params.aspace === 'workgroup'; + const accessOK = t.params.access === 'read_write'; + t.expectCompileResult( + aspaceOK && accessOK, + generateAtomicCode( + t.params.type, + t.params.access, + t.params.aspace, + t.params.style, + t.params.op + ) + ); +}); + +g.test('data_parameters'). +desc('Validates that data parameters must match atomic type (or be implicitly convertible)'). +params((u) => +u. +combine('op', [ +'atomicStore', +'atomicAdd', +'atomicSub', +'atomicMax', +'atomicMin', +'atomicAnd', +'atomicOr', +'atomicXor', +'atomicExchange', +'atomicCompareExchangeWeak1', +'atomicCompareExchangeWeak2'] +). +beginSubcases(). +combine('atomicType', ['i32', 'u32']). +combine('dataType', ['i32', 'u32', 'f32', 'AbstractInt']) +). +fn((t) => { + let dataValue = ''; + switch (t.params.dataType) { + case 'i32': + dataValue = '1i'; + break; + case 'u32': + dataValue = '1u'; + break; + case 'f32': + dataValue = '1f'; + break; + case 'AbstractInt': + dataValue = '1'; + break; + } + let op = ''; + switch (t.params.op) { + case 'atomicCompareExchangeWeak1': + op = `atomicCompareExchangeWeak(&a, ${dataValue}, 1)`; + break; + case 'atomicCompareExchangeWeak2': + op = `atomicCompareExchangeWeak(&a, 1, ${dataValue})`; + break; + default: + op = `${t.params.op}(&a, ${dataValue})`; + break; + } + const code = ` +var a : atomic<${t.params.atomicType}>; +fn foo() { + ${op}; +} +`; + + const expect = t.params.atomicType === t.params.dataType || t.params.dataType === 'AbstractInt'; + t.expectCompileResult(expect, code); +}); + +g.test('return_types'). +desc('Validates return types of atomics'). +params((u) => +u. +combine('op', keysOf(kAtomicOps)). +beginSubcases(). +combine('atomicType', ['i32', 'u32']). +combine('returnType', ['i32', 'u32', 'f32']) +). +fn((t) => { + let op = `${kAtomicOps[t.params.op]('&a')}`; + switch (t.params.op) { + case 'compareexchangeweak': + op = `let tmp : ${t.params.returnType} = ${op}.old_value`; + break; + default: + op = `let tmp : ${t.params.returnType} = ${op}`; + break; + } + const code = ` +var a : atomic<${t.params.atomicType}>; +fn foo() { + ${op}; +} +`; + + const expect = t.params.atomicType === t.params.returnType && t.params.op !== 'store'; + t.expectCompileResult(expect, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/barriers.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/barriers.spec.js new file mode 100644 index 0000000000..f3bcf33f78 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/barriers.spec.js @@ -0,0 +1,109 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for {storage,texture,workgroup}Barrier() builtins. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kEntryPoints = { + none: { supportsBarrier: true, code: `` }, + compute: { + supportsBarrier: true, + code: `@compute @workgroup_size(1) +fn main() { + foo(); +}` + }, + vertex: { + supportsBarrier: false, + code: `@vertex +fn main() -> @builtin(position) vec4f { + foo(); + return vec4f(); +}` + }, + fragment: { + supportsBarrier: false, + code: `@fragment +fn main() { + foo(); +}` + }, + compute_and_fragment: { + supportsBarrier: false, + code: `@compute @workgroup_size(1) +fn main1() { + foo(); +} + +@fragment +fn main2() { + foo(); +} +` + }, + fragment_without_call: { + supportsBarrier: true, + code: `@fragment +fn main() { +} +` + } +}; + +g.test('only_in_compute'). +specURL('https://www.w3.org/TR/WGSL/#sync-builtin-functions'). +desc( + ` +Synchronization functions must only be used in the compute shader stage. +` +). +params((u) => +u. +combine('entry_point', keysOf(kEntryPoints)). +combine('call', ['bar', 'storageBarrier', 'textureBarrier', 'workgroupBarrier']) +). +fn((t) => { + if (t.params.call.startsWith('textureBarrier')) { + t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); + } + + const config = kEntryPoints[t.params.entry_point]; + const code = ` +${config.code} +fn bar() {} + +fn foo() { + ${t.params.call}(); +}`; + t.expectCompileResult(t.params.call === 'bar' || config.supportsBarrier, code); +}); + +g.test('no_return_value'). +specURL('https://www.w3.org/TR/WGSL/#sync-builtin-functions'). +desc( + ` +Barrier functions do not return a value. +` +). +params((u) => +u. +combine('assign', [false, true]). +combine('rhs', ['bar', 'storageBarrier', 'textureBarrier', 'workgroupBarrier']) +). +fn((t) => { + if (t.params.rhs.startsWith('textureBarrier')) { + t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); + } + + const code = ` +fn bar() {} + +fn foo() { + ${t.params.assign ? '_ = ' : ''} ${t.params.rhs}(); +}`; + t.expectCompileResult(!t.params.assign || t.params.rhs === 'bar()', code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/ceil.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/ceil.spec.js index 9d6fb1e30c..6bceb41298 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/ceil.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/ceil.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -23,7 +22,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -36,10 +35,11 @@ u. combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -54,7 +54,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -68,7 +68,7 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(0)], 'constant' ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/clamp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/clamp.spec.js index ae83f29898..4490d363d5 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/clamp.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/clamp.spec.js @@ -6,9 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - elementType, - kAllFloatAndIntegerScalarsAndVectors } from + Type, + kFloatScalarsAndVectors, + kConcreteIntegerScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -21,7 +22,10 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatAndIntegerScalarsAndVectors); +const kValuesTypes = objectsToRecord([ +...kFloatScalarsAndVectors, +...kConcreteIntegerScalarsAndVectors] +); g.test('values'). desc( @@ -40,7 +44,7 @@ expand('low', (u) => fullRangeForType(kValuesTypes[u.type], 4)). expand('high', (u) => fullRangeForType(kValuesTypes[u.type], 4)) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/const_override_validation.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/const_override_validation.js index 47431b3a02..d9404ee05f 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/const_override_validation.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/const_override_validation.js @@ -1,101 +1,139 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { assert, unreachable } from '../../../../../../common/util/util.js';import { kValue } from '../../../../../util/constants.js';import { + Type, - TypeF16, - - elementType, - elementsOf, - isAbstractType } from + elementTypeOf, + isAbstractType, + scalarElementsOf, + scalarTypeOf } from '../../../../../util/conversion.js'; -import { fullF16Range, fullF32Range, fullF64Range, linearRange } from '../../../../../util/math.js'; +import { + scalarF16Range, + scalarF32Range, + scalarF64Range, + linearRange, + linearRangeBigInt } from +'../../../../../util/math.js'; + + +/** @returns a function that can select between ranges depending on type */ +export function rangeForType( +number_range, +bigint_range) +{ + return (type) => { + switch (scalarTypeOf(type).kind) { + case 'abstract-float': + case 'f32': + case 'f16': + return number_range; + case 'abstract-int': + return bigint_range; + } + unreachable(`Received unexpected type '${type}'`); + }; +} +/* @returns a linear sweep between -2 to 2 for type */ -/// A linear sweep between -2 to 2 -export const kMinusTwoToTwo = linearRange(-2, 2, 10); +export const minusTwoToTwoRangeForType = rangeForType( + linearRange(-2, 2, 10), + [-2n, -1n, 0n, 1n, 2n] +); -/// An array of values ranging from -3π to 3π, with a focus on multiples of π -export const kMinus3PiTo3Pi = [ --3 * Math.PI, --2.999 * Math.PI, +/* @returns array of values ranging from -3π to 3π, with a focus on multiples of π */ +export const minusThreePiToThreePiRangeForType = rangeForType( + [ + -3 * Math.PI, + -2.999 * Math.PI, --2.501 * Math.PI, --2.5 * Math.PI, --2.499 * Math.PI, + -2.501 * Math.PI, + -2.5 * Math.PI, + -2.499 * Math.PI, --2.001 * Math.PI, --2.0 * Math.PI, --1.999 * Math.PI, + -2.001 * Math.PI, + -2.0 * Math.PI, + -1.999 * Math.PI, --1.501 * Math.PI, --1.5 * Math.PI, --1.499 * Math.PI, + -1.501 * Math.PI, + -1.5 * Math.PI, + -1.499 * Math.PI, --1.001 * Math.PI, --1.0 * Math.PI, --0.999 * Math.PI, + -1.001 * Math.PI, + -1.0 * Math.PI, + -0.999 * Math.PI, --0.501 * Math.PI, --0.5 * Math.PI, --0.499 * Math.PI, + -0.501 * Math.PI, + -0.5 * Math.PI, + -0.499 * Math.PI, --0.001, -0, -0.001, + -0.001, + 0, + 0.001, -0.499 * Math.PI, -0.5 * Math.PI, -0.501 * Math.PI, + 0.499 * Math.PI, + 0.5 * Math.PI, + 0.501 * Math.PI, -0.999 * Math.PI, -1.0 * Math.PI, -1.001 * Math.PI, + 0.999 * Math.PI, + 1.0 * Math.PI, + 1.001 * Math.PI, -1.499 * Math.PI, -1.5 * Math.PI, -1.501 * Math.PI, + 1.499 * Math.PI, + 1.5 * Math.PI, + 1.501 * Math.PI, -1.999 * Math.PI, -2.0 * Math.PI, -2.001 * Math.PI, + 1.999 * Math.PI, + 2.0 * Math.PI, + 2.001 * Math.PI, -2.499 * Math.PI, -2.5 * Math.PI, -2.501 * Math.PI, + 2.499 * Math.PI, + 2.5 * Math.PI, + 2.501 * Math.PI, -2.999 * Math.PI, -3 * Math.PI]; + 2.999 * Math.PI, + 3 * Math.PI], + [-2n, -1n, 0n, 1n, 2n] +); -/// A minimal array of values ranging from -3π to 3π, with a focus on multiples -/// of π. Used when multiple parameters are being passed in, so the number of -/// cases becomes the square or more of this list. -export const kSparseMinus3PiTo3Pi = [ --3 * Math.PI, --2.5 * Math.PI, --2.0 * Math.PI, --1.5 * Math.PI, --1.0 * Math.PI, --0.5 * Math.PI, -0, -0.5 * Math.PI, -Math.PI, -1.5 * Math.PI, -2.0 * Math.PI, -2.5 * Math.PI, -3 * Math.PI]; +/** + * @returns a minimal array of values ranging from -3π to 3π, with a focus on + * multiples of π. + * + * Used when multiple parameters are being passed in, so the number of cases + * becomes the square or more of this list. */ +export const sparseMinusThreePiToThreePiRangeForType = rangeForType( + [ + -3 * Math.PI, + -2.5 * Math.PI, + -2.0 * Math.PI, + -1.5 * Math.PI, + -1.0 * Math.PI, + -0.5 * Math.PI, + 0, + 0.5 * Math.PI, + Math.PI, + 1.5 * Math.PI, + 2.0 * Math.PI, + 2.5 * Math.PI, + 3 * Math.PI], + [-2n, -1n, 0n, 1n, 2n] +); /// The evaluation stages to test export const kConstantAndOverrideStages = ['constant', 'override']; + /** * @returns true if evaluation stage `stage` supports expressions of type @p. */ export function stageSupportsType(stage, type) { - if (stage === 'override' && isAbstractType(elementType(type))) { + if (stage === 'override' && isAbstractType(elementTypeOf(type))) { // Abstract numerics are concretized before being used in an override expression. return false; } @@ -110,23 +148,26 @@ export function stageSupportsType(stage, type) { * @param expectedResult false if an error is expected, true if no error is expected * @param args the arguments to pass to the builtin * @param stage the evaluation stage + * @param returnType the explicit return type of the result variable, if provided (implicit otherwise) */ export function validateConstOrOverrideBuiltinEval( t, builtin, expectedResult, args, -stage) +stage, +returnType) { - const elTys = args.map((arg) => elementType(arg.type)); - const enables = elTys.some((ty) => ty === TypeF16) ? 'enable f16;' : ''; + const elTys = args.map((arg) => elementTypeOf(arg.type)); + const enables = elTys.some((ty) => ty === Type.f16) ? 'enable f16;' : ''; + const optionalVarType = returnType ? `: ${returnType.toString()}` : ''; switch (stage) { case 'constant':{ t.expectCompileResult( expectedResult, `${enables} -const v = ${builtin}(${args.map((arg) => arg.wgsl()).join(', ')});` +const v ${optionalVarType} = ${builtin}(${args.map((arg) => arg.wgsl()).join(', ')});` ); break; } @@ -138,7 +179,7 @@ const v = ${builtin}(${args.map((arg) => arg.wgsl()).join(', ')});` let numOverrides = 0; for (const arg of args) { const argOverrides = []; - for (const el of elementsOf(arg)) { + for (const el of scalarElementsOf(arg)) { const name = `o${numOverrides++}`; overrideDecls.push(`override ${name} : ${el.type};`); argOverrides.push(name); @@ -150,7 +191,7 @@ const v = ${builtin}(${args.map((arg) => arg.wgsl()).join(', ')});` expectedResult, code: `${enables} ${overrideDecls.join('\n')} -var v = ${builtin}(${callArgs.join(', ')});`, +var v ${optionalVarType} = ${builtin}(${callArgs.join(', ')});`, constants, reference: ['v'] }); @@ -159,24 +200,92 @@ var v = ${builtin}(${callArgs.join(', ')});`, } } +/** + * Runs a validation test to check that evaluation of `binaryOp` either evaluates with or without + * error at shader creation time or pipeline creation time. + * @param t the ShaderValidationTest + * @param binaryOp the symbol of the binary operator + * @param expectedResult false if an error is expected, true if no error is expected + * @param leftStage the evaluation stage for the left argument + * @param left the left-hand side of the binary operation + * @param rightStage the evaluation stage for the right argument + * @param right the right-hand side of the binary operation + */ +export function validateConstOrOverrideBinaryOpEval( +t, +binaryOp, +expectedResult, +leftStage, +left, +rightStage, +right) +{ + const allArgs = [left, right]; + const elTys = allArgs.map((arg) => elementTypeOf(arg.type)); + const enables = elTys.some((ty) => ty === Type.f16) ? 'enable f16;' : ''; + + const codeLines = [enables]; + const constants = {}; + let numOverrides = 0; + + function addOperand(name, stage, value) { + switch (stage) { + case 'runtime': + assert(!isAbstractType(value.type)); + codeLines.push(`var ${name} = ${value.wgsl()};`); + return name; + + case 'constant': + codeLines.push(`const ${name} = ${value.wgsl()};`); + return name; + + case 'override':{ + assert(!isAbstractType(value.type)); + const argOverrides = []; + for (const el of scalarElementsOf(value)) { + const elName = `o${numOverrides++}`; + codeLines.push(`override ${elName} : ${el.type};`); + constants[elName] = Number(el.value); + argOverrides.push(elName); + } + return `${value.type}(${argOverrides.join(', ')})`; + } + } + } + + const leftOperand = addOperand('left', leftStage, left); + const rightOperand = addOperand('right', rightStage, right); + + if (leftStage === 'override' || rightStage === 'override') { + t.expectPipelineResult({ + expectedResult, + code: codeLines.join('\n'), + constants, + reference: [`${leftOperand} ${binaryOp} ${rightOperand}`] + }); + } else { + codeLines.push(`fn f() { _ = ${leftOperand} ${binaryOp} ${rightOperand}; }`); + t.expectCompileResult(expectedResult, codeLines.join('\n')); + } +} /** @returns a sweep of the representable values for element type of `type` */ export function fullRangeForType(type, count) { if (count === undefined) { count = 25; } - switch (elementType(type)?.kind) { + switch (scalarTypeOf(type)?.kind) { case 'abstract-float': - return fullF64Range({ + return scalarF64Range({ pos_sub: Math.ceil(count * 1 / 5), pos_norm: Math.ceil(count * 4 / 5) }); case 'f32': - return fullF32Range({ + return scalarF32Range({ pos_sub: Math.ceil(count * 1 / 5), pos_norm: Math.ceil(count * 4 / 5) }); case 'f16': - return fullF16Range({ + return scalarF16Range({ pos_sub: Math.ceil(count * 1 / 5), pos_norm: Math.ceil(count * 4 / 5) }); @@ -186,6 +295,9 @@ export function fullRangeForType(type, count) { ); case 'u32': return linearRange(0, kValue.u32.max, count).map((f) => Math.floor(f)); + case 'abstract-int': + // Returned values are already ints, so don't need to be floored. + return linearRangeBigInt(kValue.i64.negative.min, kValue.i64.positive.max, count); } unreachable(); } diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cos.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cos.spec.js index 4f3a485b5f..5d5cde71c7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cos.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cos.spec.js @@ -6,18 +6,17 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kMinus3PiTo3Pi, + minusThreePiToThreePiRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -25,7 +24,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -39,10 +38,15 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('value', (u) => unique(kMinus3PiTo3Pi, fullRangeForType(kValuesTypes[u.type]))) +expand('value', (u) => +unique( + minusThreePiToThreePiRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type]) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -56,7 +60,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -70,8 +74,41 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(0)], 'constant' ); +}); + +const kArgCases = { + good: '(1.1)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2args: '(1.0,2.0)', + // Bad value type for arg 0 + bad_0i32: '(1i)', + bad_0u32: '(1u)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cosh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cosh.spec.js index 27f975252c..a496f0184e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cosh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cosh.spec.js @@ -6,11 +6,9 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -24,7 +22,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -41,13 +39,17 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; - const expectedResult = isRepresentable(Math.cosh(t.params.value), elementType(type)); + const expectedResult = isRepresentable( + Math.cosh(Number(t.params.value)), + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); validateConstOrOverrideBuiltinEval( t, builtin, @@ -57,22 +59,40 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kArgCases = { + good: '(1.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.2, 2.3)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())' +}; -g.test('integer_argument'). -desc( - ` -Validates that scalar and vector integer arguments are rejected by ${builtin}() -` -). -params((u) => u.combine('type', keysOf(kIntegerArgumentTypes))). +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). fn((t) => { - const type = kIntegerArgumentTypes[t.params.type]; - validateConstOrOverrideBuiltinEval( - t, - builtin, - /* expectedResult */type === TypeF32, - [type.create(0)], - 'constant' + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countLeadingZeros.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countLeadingZeros.spec.js new file mode 100644 index 0000000000..549ff06a7d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countLeadingZeros.spec.js @@ -0,0 +1,198 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'countLeadingZeros';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kFloatScalarsAndVectors } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConcreteIntegerScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) +). +fn((t) => { + const expectedResult = true; // countLeadingZeros() should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [kValuesTypes[t.params.type].create(t.params.value)], + t.params.stage + ); +}); + +// u32 is included here to confirm that validation is failing due to a type issue and not something else. +const kFloatTypes = objectsToRecord([Type.u32, ...kFloatScalarsAndVectors]); + +g.test('float_argument'). +desc( + ` +Validates that float arguments are rejected by ${builtin}() +` +). +params((u) => u.combine('type', keysOf(kFloatTypes))). +fn((t) => { + const type = kFloatTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */type === Type.u32, + [type.create(0)], + 'constant' + ); +}); + +const kTests = + + + + + + + + +{ + valid: { + args: '(1u)', + pass: true + }, + // Number of arguments. + no_parens: { + args: '', + pass: false + }, + too_few_args: { + args: '()', + pass: false + }, + too_many_args: { + args: '(1u,2u)', + pass: false + }, + // Arguments types (only 1 argument for this builtin). + alias: { + args: '(u32_alias(1))', + pass: true + }, + bool: { + args: '(false)', + pass: false + }, + vec_bool: { + args: '(vec2(false,true))', + pass: false + }, + matrix: { + args: '(mat2x2(1,1,1,1))', + pass: false + }, + atomic: { + args: '(a)', + pass: false + }, + array: { + preamble: 'var arry: array;', + args: '(arry)', + pass: false + }, + array_runtime: { + args: '(k.arry)', + pass: false + }, + struct: { + preamble: 'var x: A;', + args: '(x)', + pass: false + }, + enumerant: { + args: '(read_write)', + pass: false + }, + ptr: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(p)', + pass: false + }, + ptr_deref: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(*p)', + pass: true + }, + sampler: { + args: '(s)', + pass: false + }, + texture: { + args: '(t)', + pass: false + } +}; + +g.test('arguments'). +desc(`Test compilation validation of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const test = kTests[t.params.test]; + t.expectCompileResult( + test.pass, + `alias u32_alias = u32; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: u32, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + + @vertex + fn main() -> @builtin(position) vec4 { + ${test.preamble ? test.preamble : ''} + _ = ${builtin}${test.args}; + return vec4(.4, .2, .3, .1); + }` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(1u); }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countOneBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countOneBits.spec.js new file mode 100644 index 0000000000..24ff7f79a5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countOneBits.spec.js @@ -0,0 +1,198 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'countOneBits';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kFloatScalarsAndVectors } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConcreteIntegerScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) +). +fn((t) => { + const expectedResult = true; // countOneBits() should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [kValuesTypes[t.params.type].create(t.params.value)], + t.params.stage + ); +}); + +// u32 is included here to confirm that validation is failing due to a type issue and not something else. +const kFloatTypes = objectsToRecord([Type.u32, ...kFloatScalarsAndVectors]); + +g.test('float_argument'). +desc( + ` +Validates that float arguments are rejected by ${builtin}() +` +). +params((u) => u.combine('type', keysOf(kFloatTypes))). +fn((t) => { + const type = kFloatTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */type === Type.u32, + [type.create(0)], + 'constant' + ); +}); + +const kTests = + + + + + + + + +{ + valid: { + args: '(1u)', + pass: true + }, + // Number of arguments. + no_parens: { + args: '', + pass: false + }, + too_few_args: { + args: '()', + pass: false + }, + too_many_args: { + args: '(1u,2u)', + pass: false + }, + // Arguments types (only 1 argument for this builtin). + alias: { + args: '(u32_alias(1))', + pass: true + }, + bool: { + args: '(false)', + pass: false + }, + vec_bool: { + args: '(vec2(false,true))', + pass: false + }, + matrix: { + args: '(mat2x2(1,1,1,1))', + pass: false + }, + atomic: { + args: '(a)', + pass: false + }, + array: { + preamble: 'var arry: array;', + args: '(arry)', + pass: false + }, + array_runtime: { + args: '(k.arry)', + pass: false + }, + struct: { + preamble: 'var x: A;', + args: '(x)', + pass: false + }, + enumerant: { + args: '(read_write)', + pass: false + }, + ptr: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(p)', + pass: false + }, + ptr_deref: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(*p)', + pass: true + }, + sampler: { + args: '(s)', + pass: false + }, + texture: { + args: '(t)', + pass: false + } +}; + +g.test('arguments'). +desc(`Test compilation validation of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const test = kTests[t.params.test]; + t.expectCompileResult( + test.pass, + `alias u32_alias = u32; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: u32, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + + @vertex + fn main() -> @builtin(position) vec4 { + ${test.preamble ? test.preamble : ''} + _ = ${builtin}${test.args}; + return vec4(.4, .2, .3, .1); + }` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(1u); }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countTrailingZeros.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countTrailingZeros.spec.js new file mode 100644 index 0000000000..82af773fd3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/countTrailingZeros.spec.js @@ -0,0 +1,198 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'countTrailingZeros';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kFloatScalarsAndVectors } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConcreteIntegerScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) +). +fn((t) => { + const expectedResult = true; // countTrailingZeros() should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [kValuesTypes[t.params.type].create(t.params.value)], + t.params.stage + ); +}); + +// u32 is included here to confirm that validation is failing due to a type issue and not something else. +const kFloatTypes = objectsToRecord([Type.u32, ...kFloatScalarsAndVectors]); + +g.test('float_argument'). +desc( + ` +Validates that float arguments are rejected by ${builtin}() +` +). +params((u) => u.combine('type', keysOf(kFloatTypes))). +fn((t) => { + const type = kFloatTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */type === Type.u32, + [type.create(0)], + 'constant' + ); +}); + +const kTests = + + + + + + + + +{ + valid: { + args: '(1u)', + pass: true + }, + // Number of arguments. + no_parens: { + args: '', + pass: false + }, + too_few_args: { + args: '()', + pass: false + }, + too_many_args: { + args: '(1u,2u)', + pass: false + }, + // Arguments types (only 1 argument for this builtin). + alias: { + args: '(u32_alias(1))', + pass: true + }, + bool: { + args: '(false)', + pass: false + }, + vec_bool: { + args: '(vec2(false,true))', + pass: false + }, + matrix: { + args: '(mat2x2(1,1,1,1))', + pass: false + }, + atomic: { + args: '(a)', + pass: false + }, + array: { + preamble: 'var arry: array;', + args: '(arry)', + pass: false + }, + array_runtime: { + args: '(k.arry)', + pass: false + }, + struct: { + preamble: 'var x: A;', + args: '(x)', + pass: false + }, + enumerant: { + args: '(read_write)', + pass: false + }, + ptr: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(p)', + pass: false + }, + ptr_deref: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(*p)', + pass: true + }, + sampler: { + args: '(s)', + pass: false + }, + texture: { + args: '(t)', + pass: false + } +}; + +g.test('arguments'). +desc(`Test compilation validation of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const test = kTests[t.params.test]; + t.expectCompileResult( + test.pass, + `alias u32_alias = u32; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: u32, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + + @vertex + fn main() -> @builtin(position) vec4 { + ${test.preamble ? test.preamble : ''} + _ = ${builtin}${test.args}; + return vec4(.4, .2, .3, .1); + }` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(1u); }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cross.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cross.spec.js new file mode 100644 index 0000000000..50f50e44fb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/cross.spec.js @@ -0,0 +1,122 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'cross';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConvertableToFloatVec3, + scalarTypeOf } from + +'../../../../../util/conversion.js'; +import { quantizeToF16, quantizeToF32 } from '../../../../../util/math.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidArgumentTypes = objectsToRecord(kConvertableToFloatVec3); + +function quantizeFunctionForScalarType(type) { + switch (type) { + case Type.f32: + return quantizeToF32; + case Type.f16: + return quantizeToF16; + default: + return (v) => v; + } +} + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValidArgumentTypes)). +filter((u) => stageSupportsType(u.stage, kValidArgumentTypes[u.type])). +beginSubcases(). +expand('a', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)). +expand('b', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValidArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + let expectedResult = true; + + const scalarType = scalarTypeOf(kValidArgumentTypes[t.params.type]); + const quantizeFn = quantizeFunctionForScalarType(scalarType); + + // Should be invalid if the cross product calculations result in intermediate + // values that exceed the maximum representable float value for the given type. + const a = Number(t.params.a); + const b = Number(t.params.b); + const ab = quantizeFn(a * b); + if (ab === Infinity || ab === -Infinity) { + expectedResult = false; + } + + const type = kValidArgumentTypes[t.params.type]; + + // Validates cross(vec3(a, a, a), vec3(b, b, b)); + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.a), type.create(t.params.b)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(vec3(0), vec3(1))', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_1arg: '(1.0)', + bad_3arg: '(1.0, 2.0, 3.0)', + // Wrong vector size + bad_vec2: '(vec2(0), vec2(1))', + bad_vec4: '(vec4(0), vec4(1))', + // Bad value for arg 0 + bad_0bool: '(false, vec3(1))', + bad_0array: '(array(1.1,2.2), vec3(1))', + bad_0struct: '(modf(2.2), vec3(1))', + // Bad value type for arg 1 + bad_1bool: '(vec3(0), true)', + bad_1array: '(vec3(0), array(1.1,2.2))', + bad_1struct: '(vec3(0), modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/degrees.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/degrees.spec.js index 10aac98de2..2262cf9ab8 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/degrees.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/degrees.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -24,7 +23,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -41,13 +40,17 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; - const expectedResult = isRepresentable(t.params.value * 180 / Math.PI, elementType(type)); + const expectedResult = isRepresentable( + Number(t.params.value) * 180 / Math.PI, + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); validateConstOrOverrideBuiltinEval( t, builtin, @@ -57,7 +60,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -71,8 +74,41 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(1)], 'constant' ); +}); + +const kArgCases = { + good: '(1.1)', + bad_no_parens: '', + // Bad number of args + bad_too_few: '()', + bad_too_many: '(1.0,2.0)', + // Bad value type for arg 0 + bad_0i32: '(1i)', + bad_0u32: '(1u)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/derivatives.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/derivatives.spec.js new file mode 100644 index 0000000000..e1b479a8c6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/derivatives.spec.js @@ -0,0 +1,129 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for derivative builtins. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kConcreteF16ScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kDerivativeBuiltins = [ +'dpdx', +'dpdxCoarse', +'dpdxFine', +'dpdy', +'dpdyCoarse', +'dpdyFine', +'fwidth', +'fwidthCoarse', +'fwidthFine']; + + +const kEntryPoints = { + none: { supportsDerivative: true, code: `` }, + fragment: { + supportsDerivative: true, + code: `@fragment +fn main() { + foo(); +}` + }, + vertex: { + supportsDerivative: false, + code: `@vertex +fn main() -> @builtin(position) vec4f { + foo(); + return vec4f(); +}` + }, + compute: { + supportsDerivative: false, + code: `@compute @workgroup_size(1) +fn main() { + foo(); +}` + }, + fragment_and_compute: { + supportsDerivative: false, + code: `@fragment +fn main1() { + foo(); +} + +@compute @workgroup_size(1) +fn main2() { + foo(); +} +` + }, + compute_without_call: { + supportsDerivative: true, + code: `@compute @workgroup_size(1) +fn main() { +} +` + } +}; + +g.test('only_in_fragment'). +specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions'). +desc( + ` +Derivative functions must only be used in the fragment shader stage. +` +). +params((u) => +u.combine('entry_point', keysOf(kEntryPoints)).combine('call', ['bar', ...kDerivativeBuiltins]) +). +fn((t) => { + const config = kEntryPoints[t.params.entry_point]; + const code = ` +${config.code} +fn bar(f : f32) -> f32 { return f; } + +fn foo() { + _ = ${t.params.call}(1.0); +}`; + t.expectCompileResult(t.params.call === 'bar' || config.supportsDerivative, code); +}); + +// The list of invalid argument types to test, with an f32 control case. +const kArgumentTypes = objectsToRecord([ +Type.f32, +...kConcreteIntegerScalarsAndVectors, +...kConcreteF16ScalarsAndVectors, +Type.mat2x2f] +); + +g.test('invalid_argument_types'). +specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions'). +desc( + ` +Derivative builtins only accept f32 scalar and vector types. +` +). +params((u) => +u.combine('type', keysOf(kArgumentTypes)).combine('call', ['', ...kDerivativeBuiltins]) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kArgumentTypes[t.params.type]; + const code = ` +${scalarTypeOf(kArgumentTypes[t.params.type]) === Type.f16 ? 'enable f16;' : ''} + +fn foo() { + let x: ${type.toString()} = ${t.params.call}(${type.create(1).wgsl()}); +}`; + t.expectCompileResult(kArgumentTypes[t.params.type] === Type.f32 || t.params.call === '', code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/determinant.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/determinant.spec.js new file mode 100644 index 0000000000..8bade808a2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/determinant.spec.js @@ -0,0 +1,95 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'determinant';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// Generate a dictionary mapping each matrix type variation (columns,rows, +// floating point type) to a nontrivial matrix value of that type. +const kMatrixCases = [2, 3, 4]. +flatMap((cols) => +[2, 3, 4].flatMap((rows) => +['abstract-int', 'abstract-float', 'f32', 'f16'].map((type) => ({ + [`mat${cols}x${rows}_${type}`]: (() => { + const suffix = (() => { + switch (type) { + case 'abstract-int': + return ''; + case 'abstract-float': + return '.0'; + case 'f32': + return 'f'; + case 'f16': + return 'h'; + } + })(); + return `(mat${cols}x${rows}(${[...Array(cols * rows).keys()]. + map((e) => `${e}${suffix}`). + join(', ')}))`; + })() +})) +) +). +reduce((a, b) => ({ ...a, ...b }), {}); + +g.test('matrix_args'). +desc(`Test compilation failure of ${builtin} with variously shaped matrices`). +params((u) => +u. +combine('cols', [2, 3, 4]). +combine('rows', [2, 3, 4]). +combine('type', ['abstract-int', 'abstract-float', 'f32', 'f16']) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const cols = t.params.cols; + const rows = t.params.rows; + const type = t.params.type; + const arg = kMatrixCases[`mat${cols}x${rows}_${type}`]; + t.expectCompileResult( + cols === rows, + t.wrapInEntryPoint(`const c = ${builtin}${arg};`, type === 'f16' ? ['f16'] : []) + ); +}); + +const kArgCases = { + good: '(mat2x2(0.0, 2.0, 3.0, 4.0))', // Included to check test implementation + bad_no_parens: '', + // Bad number of args + bad_too_few: '()', + bad_too_many: '(mat2x2(0.0, 2.0, 3.0, 4.0), mat2x2(0.0, 2.0, 3.0, 4.0))', + // Bad value type for arg 0 + bad_0i32: '(1i)', + bad_0u32: '(1u)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/distance.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/distance.spec.js new file mode 100644 index 0000000000..b08c12faf5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/distance.spec.js @@ -0,0 +1,149 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'distance';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from + +'../../../../../util/conversion.js'; +import { quantizeToF16, quantizeToF32 } from '../../../../../util/math.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidArgumentTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); + +function quantizeFunctionForScalarType(type) { + switch (type) { + case Type.f32: + return quantizeToF32; + case Type.f16: + return quantizeToF16; + default: + return (v) => v; + } +} + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValidArgumentTypes)). +filter((u) => stageSupportsType(u.stage, kValidArgumentTypes[u.type])). +beginSubcases(). +expand('a', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)). +expand('b', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValidArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + let expectedResult = true; + + const scalarType = scalarTypeOf(kValidArgumentTypes[t.params.type]); + const quantizeFn = quantizeFunctionForScalarType(scalarType); + + // Distance equation: length(a - b) + // Should be invalid if the calculations result in intermediate values that + // exceed the maximum representable float value for the given type. + const a = Number(t.params.a); + const b = Number(t.params.b); + const ab = quantizeFn(a - b); + + if (!Number.isFinite(ab)) { + expectedResult = false; + } + + // Only calculates the full length if the type is a vector. Otherwise abs(a-b) is used. + if (kValidArgumentTypes[t.params.type].width > 1) { + const ab2 = quantizeFn(ab * ab); + const sqrLen = quantizeFn(ab2 * kValidArgumentTypes[t.params.type].width); + // Square root does not need to be calculated because it can never fail if + // the previous results are finite. + + if (!Number.isFinite(ab2) || !Number.isFinite(sqrLen)) { + expectedResult = false; + } + } + + const type = kValidArgumentTypes[t.params.type]; + + // Validates distance(vecN(a), vecN(b)) or distance(a, b); + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.a), type.create(t.params.b)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(vec3(0), vec3(1))', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_1arg: '(vec3(0))', + bad_3arg: '(vec3(0), vec3(1), vec3(2))', + // Bad value for arg 0 + bad_0bool: '(false, vec3(1))', + bad_0array: '(array(1.1,2.2), vec3(1))', + bad_0struct: '(modf(2.2), vec3(1))', + bad_0int: '(0i, vec3(1))', + bad_0vec2i: '(vec2i(), vec3(1))', + bad_0vec3i: '(vec3i(), vec3(1))', + bad_0vec4i: '(vec4i(), vec3(1))', + bad_0uint: '(0u, vec3(1))', + bad_0vec2u: '(vec2u(), vec3(1))', + bad_0vec3u: '(vec3u(), vec3(1))', + bad_0vec4u: '(vec4u(), vec3(1))', + // Bad value type for arg 1 + bad_1bool: '(vec3(0), true)', + bad_1array: '(vec3(0), array(1.1,2.2))', + bad_1struct: '(vec3(0), modf(2.2))', + bad_1int: '(vec3(0), 0i)', + bad_1vec2i: '(vec3(0), vec2i())', + bad_1vec3i: '(vec3(0), vec3i())', + bad_1vec4i: '(vec3(0), vec4i())', + bad_1uint: '(vec3(0), 0u)', + bad_1vec2u: '(vec3(0), vec2u())', + bad_1vec3u: '(vec3(0), vec3u())', + bad_1vec4u: '(vec3(0), vec4u())' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/dot4I8Packed.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/dot4I8Packed.spec.js new file mode 100644 index 0000000000..f72eb87f97 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/dot4I8Packed.spec.js @@ -0,0 +1,66 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validate dot4I8Packed`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kFeature = 'packed_4x8_integer_dot_product'; +const kFn = 'dot4I8Packed'; +const kArgCases = { + good: '(1u,2u)', + bad_0args: '()', + bad_1args: '(1u)', + bad_3args: '(1u,2u,3u)', + bad_0i32: '(1i,2u)', + bad_0f32: '(1f,2u)', + bad_0bool: '(false,2u)', + bad_0vec2u: '(vec2u(),2u)', + bad_1i32: '(1u,2i)', + bad_1f32: '(1u,2f)', + bad_1bool: '(1u,true)', + bad_1vec2u: '(1u,vec2u())', + bad_bool_bool: '(false,true)', + bad_bool2_bool2: '(vec2(),vec2(false,true))', + bad_0array: '(array(1))', + bad_0struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('unsupported'). +desc(`Test absence of ${kFn} when ${kFeature} is not supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(false, code); +}); + +g.test('supported'). +desc(`Test presence of ${kFn} when ${kFeature} is supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(true, code); +}); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + t.expectCompileResult(t.params.arg === 'good', `const c = ${kFn}${kArgCases[t.params.arg]};`); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/dot4U8Packed.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/dot4U8Packed.spec.js new file mode 100644 index 0000000000..315e69bfb9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/dot4U8Packed.spec.js @@ -0,0 +1,66 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validate dot4U8Packed`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kFeature = 'packed_4x8_integer_dot_product'; +const kFn = 'dot4U8Packed'; +const kArgCases = { + good: '(1u,2u)', + bad_0args: '()', + bad_1args: '(1u)', + bad_3args: '(1u,2u,3u)', + bad_0i32: '(1i,2u)', + bad_0f32: '(1f,2u)', + bad_0bool: '(false,2u)', + bad_0vec2u: '(vec2u(),2u)', + bad_1i32: '(1u,2i)', + bad_1f32: '(1u,2f)', + bad_1bool: '(1u,true)', + bad_1vec2u: '(1u,vec2u())', + bad_bool_bool: '(false,true)', + bad_bool2_bool2: '(vec2(),vec2(false,true))', + bad_0array: '(array(1))', + bad_0struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('unsupported'). +desc(`Test absence of ${kFn} when ${kFeature} is not supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(false, code); +}); + +g.test('supported'). +desc(`Test presence of ${kFn} when ${kFeature} is supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(true, code); +}); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + t.expectCompileResult(t.params.arg === 'good', `const c = ${kFn}${kArgCases[t.params.arg]};`); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/exp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/exp.spec.js index 74a8816114..e677442d4a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/exp.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/exp.spec.js @@ -7,24 +7,52 @@ import { makeTestGroup } from '../../../../../../common/framework/test_group.js' import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { kValue } from '../../../../../util/constants.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { kConstantAndOverrideStages, + rangeForType, stageSupportsType, validateConstOrOverrideBuiltinEval } from './const_override_validation.js'; export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); + +const valueForType = rangeForType( + [ + -1e2, + -1e3, + -4, + -3, + -2, + -1, + -1e-1, + -1e-2, + -1e-3, + 0, + 1e-3, + 1e-2, + 1e-1, + 1, + 2, + 3, + 4, + 1e2, + 1e3, + Math.log2(kValue.f16.positive.max) - 0.1, + Math.log2(kValue.f16.positive.max) + 0.1, + Math.log2(kValue.f32.positive.max) - 0.1, + Math.log2(kValue.f32.positive.max) + 0.1], + + [-100n, -1000n, -4n, -3n, -2n, -1n, 0n, 1n, 2n, 3n, 4n, 100n, 1000n] +); g.test('values'). desc( @@ -38,40 +66,20 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -combine('value', [ --1e2, --1e3, --4, --3, --2, --1, --1e-1, --1e-2, --1e-3, -0, -1e-3, -1e-2, -1e-1, -1, -2, -3, -4, -1e2, -1e3, -Math.log2(kValue.f16.positive.max) - 0.1, -Math.log2(kValue.f16.positive.max) + 0.1, -Math.log2(kValue.f32.positive.max) - 0.1, -Math.log2(kValue.f32.positive.max) + 0.1] -) +expand('value', (u) => valueForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; - const expectedResult = isRepresentable(Math.exp(t.params.value), elementType(type)); + const expectedResult = isRepresentable( + Math.exp(Number(t.params.value)), + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); validateConstOrOverrideBuiltinEval( t, builtin, @@ -81,22 +89,40 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kArgCases = { + good: '(1.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.2, 2.3)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())' +}; -g.test('integer_argument'). -desc( - ` -Validates that scalar and vector integer arguments are rejected by ${builtin}() -` -). -params((u) => u.combine('type', keysOf(kIntegerArgumentTypes))). +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). fn((t) => { - const type = kIntegerArgumentTypes[t.params.type]; - validateConstOrOverrideBuiltinEval( - t, - builtin, - /* expectedResult */type === TypeF32, - [type.create(0)], - 'constant' + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/exp2.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/exp2.spec.js index c38d5f90ef..5455216d75 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/exp2.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/exp2.spec.js @@ -7,24 +7,52 @@ import { makeTestGroup } from '../../../../../../common/framework/test_group.js' import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { kValue } from '../../../../../util/constants.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { kConstantAndOverrideStages, + rangeForType, stageSupportsType, validateConstOrOverrideBuiltinEval } from './const_override_validation.js'; export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); + +const valueForType = rangeForType( + [ + -1e2, + -1e3, + -4, + -3, + -2, + -1, + -1e-1, + -1e-2, + -1e-3, + 0, + 1e-3, + 1e-2, + 1e-1, + 1, + 2, + 3, + 4, + 1e2, + 1e3, + Math.log2(kValue.f16.positive.max) - 0.1, + Math.log2(kValue.f16.positive.max) + 0.1, + Math.log2(kValue.f32.positive.max) - 0.1, + Math.log2(kValue.f32.positive.max) + 0.1], + + [-100n, -1000n, -4n, -3n, -2n, -1n, 0n, 1n, 2n, 3n, 4n, 100n, 1000n] +); g.test('values'). desc( @@ -38,40 +66,20 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -combine('value', [ --1e2, --1e3, --4, --3, --2, --1, --1e-1, --1e-2, --1e-3, -0, -1e-3, -1e-2, -1e-1, -1, -2, -3, -4, -1e2, -1e3, -Math.log2(kValue.f16.positive.max) - 0.1, -Math.log2(kValue.f16.positive.max) + 0.1, -Math.log2(kValue.f32.positive.max) - 0.1, -Math.log2(kValue.f32.positive.max) + 0.1] -) +expand('value', (u) => valueForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; - const expectedResult = isRepresentable(Math.pow(2, t.params.value), elementType(type)); + const expectedResult = isRepresentable( + Math.pow(2, Number(t.params.value)), + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); validateConstOrOverrideBuiltinEval( t, builtin, @@ -81,22 +89,40 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kArgCases = { + good: '(1.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.2, 2.3)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())' +}; -g.test('integer_argument'). -desc( - ` -Validates that scalar and vector integer arguments are rejected by ${builtin}() -` -). -params((u) => u.combine('type', keysOf(kIntegerArgumentTypes))). +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). fn((t) => { - const type = kIntegerArgumentTypes[t.params.type]; - validateConstOrOverrideBuiltinEval( - t, - builtin, - /* expectedResult */type === TypeF32, - [type.create(0)], - 'constant' + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/extractBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/extractBits.spec.js new file mode 100644 index 0000000000..e38cb53905 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/extractBits.spec.js @@ -0,0 +1,218 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'extractBits';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kFloatScalarsAndVectors, + u32 } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConcreteIntegerScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors on valid inputs +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValuesTypes[u.type])). +combineWithParams([ +{ offset: 0, count: 0 }, +{ offset: 0, count: 31 }, +{ offset: 0, count: 32 }, +{ offset: 4, count: 0 }, +{ offset: 4, count: 27 }, +{ offset: 4, count: 28 }, +{ offset: 16, count: 0 }, +{ offset: 16, count: 15 }, +{ offset: 16, count: 16 }, +{ offset: 32, count: 0 }] +) +). +fn((t) => { + const expectedResult = true; // extractBits() should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [ + kValuesTypes[t.params.type].create(t.params.value), + u32(t.params.offset), + u32(t.params.count)], + + t.params.stage + ); +}); + +g.test('count_offset'). +desc( + ` +Validates that count and offset must be smaller than the size of the primitive. +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +beginSubcases(). +combineWithParams([ +// offset + count < 32 +{ offset: 0, count: 31 }, +{ offset: 1, count: 30 }, +{ offset: 31, count: 0 }, +{ offset: 30, count: 1 }, +// offset + count == 32 +{ offset: 0, count: 32 }, +{ offset: 1, count: 31 }, +{ offset: 16, count: 16 }, +{ offset: 31, count: 1 }, +{ offset: 32, count: 0 }, +// offset + count > 32 +{ offset: 2, count: 31 }, +{ offset: 31, count: 2 }, +// offset > 32 +{ offset: 33, count: 0 }, +{ offset: 33, count: 1 }, +// count > 32 +{ offset: 0, count: 33 }, +{ offset: 1, count: 33 }] +) +). +fn((t) => { + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */t.params.offset + t.params.count <= 32, + [u32(1), u32(t.params.offset), u32(t.params.count)], + t.params.stage + ); +}); + + + + + + + + + + +function typesToArguments(types, pass) { + return types.reduce( + (res, type) => ({ + ...res, + [type.toString()]: { arg: type.create(0).wgsl(), pass } + }), + {} + ); +} + +// u32 is included here to confirm that validation is failing due to a type issue and not something else. +const kInputArgTypes = { + ...typesToArguments([Type.u32], true), + ...typesToArguments([...kFloatScalarsAndVectors, Type.bool, Type.mat2x2f], false), + alias: { arg: 'u32_alias(1)', pass: true }, + vec_bool: { arg: 'vec2(false,true)', pass: false }, + atomic: { arg: 'a', pass: false }, + array: { + preamble: 'var arry: array;', + arg: 'arry', + pass: false + }, + array_runtime: { arg: 'k.arry', pass: false }, + struct: { + preamble: 'var x: A;', + arg: 'x', + pass: false + }, + enumerant: { arg: 'read_write', pass: false }, + ptr: { + preamble: `var f = 1u; + let p: ptr = &f;`, + arg: 'p', + pass: false + }, + ptr_deref: { + preamble: `var f = 1u; + let p: ptr = &f;`, + arg: '*p', + pass: true + }, + sampler: { arg: 's', pass: false }, + texture: { arg: 't', pass: false } +}; + +g.test('typed_arguments'). +desc( + ` +Test compilation validation of ${builtin} with variously typed arguments + - For failing input types, just use the same type for offset and count to reduce combinations. +` +). +params((u) => +u. +combine('input', keysOf(kInputArgTypes)). +beginSubcases(). +combine('offset', keysOf(kInputArgTypes)). +expand('count', (u) => kInputArgTypes[u.input].pass ? keysOf(kInputArgTypes) : [u.offset]) +). +fn((t) => { + const input = kInputArgTypes[t.params.input]; + const offset = kInputArgTypes[t.params.offset]; + const count = kInputArgTypes[t.params.count]; + t.expectCompileResult( + input.pass && offset.pass && count.pass, + `alias u32_alias = u32; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: u32, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + + @vertex + fn main() -> @builtin(position) vec4 { + ${input.preamble ? input.preamble : ''} + ${offset.preamble && offset !== input ? offset.preamble : ''} + ${count.preamble && count !== input && count !== offset ? count.preamble : ''} + _ = ${builtin}(${input.arg},${offset.arg},${count.arg}); + return vec4(.4, .2, .3, .1); + }` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(1u,0u,1u); }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/faceForward.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/faceForward.spec.js new file mode 100644 index 0000000000..77946e3e9e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/faceForward.spec.js @@ -0,0 +1,152 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'faceForward';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConvertableToFloatVectors, + scalarTypeOf } from + +'../../../../../util/conversion.js'; +import { quantizeToF16, quantizeToF32 } from '../../../../../util/math.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidArgumentTypes = objectsToRecord(kConvertableToFloatVectors); + +function quantizeFunctionForScalarType(type) { + switch (type) { + case Type.f32: + return quantizeToF32; + case Type.f16: + return quantizeToF16; + default: + return (v) => v; + } +} + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValidArgumentTypes)). +filter((u) => stageSupportsType(u.stage, kValidArgumentTypes[u.type])). +beginSubcases(). +expand('a', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)). +expand('b', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)). +expand('c', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValidArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + let expectedResult = true; + + const scalarType = scalarTypeOf(kValidArgumentTypes[t.params.type]); + const quantizeFn = quantizeFunctionForScalarType(scalarType); + + // Face Forward equation: dot(b, c) < 0 ? -a : a + // Should be invalid if the calculations result in intermediate values that + // exceed the maximum representable float value for the given type. + const b = Number(t.params.b); + const c = Number(t.params.c); + const bc = quantizeFn(b * c); + const dp = quantizeFn(bc * kValidArgumentTypes[t.params.type].width); + + if (!Number.isFinite(dp)) { + expectedResult = false; + } + + const type = kValidArgumentTypes[t.params.type]; + + // Validates faceForward(vecN(a), vecN(b), vecN(c)); + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.a), type.create(t.params.b), type.create(t.params.c)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(vec3(0), vec3(1), vec3(0.5))', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_1arg: '(vec3(0))', + bad_2arg: '(vec3(0), vec3(1))', + bad_4arg: '(vec3(0), vec3(1), vec3(0.5), vec3(3))', + // Bad value for arg 0 + bad_0bool: '(false, vec3(1), vec3(0.5))', + bad_0array: '(array(1.1,2.2), vec3(1), vec3(0.5))', + bad_0struct: '(modf(2.2), vec3(1), vec3(0.5))', + bad_0int: '(1i, vec3(1), vec3(0.5))', + bad_0uint: '(1u, vec3(1), vec3(0.5))', + bad_0vec2i: '(vec2i(0), vec2(1), vec2(0.5))', + bad_0vec3i: '(vec3i(0), vec3(1), vec3(0.5))', + bad_0vec4i: '(vec4i(0), vec4(1), vec4(0.5))', + bad_0vec2u: '(vec2u(0), vec2(1), vec2(0.5))', + bad_0vec3u: '(vec3u(0), vec3(1), vec3(0.5))', + bad_0vec4u: '(vec4u(0), vec4(1), vec4(0.5))', + // Bad value type for arg 1 + bad_1bool: '(vec3(0), true, vec3(0.5))', + bad_1array: '(vec3(0), array(1.1,2.2), vec3(0.5))', + bad_1struct: '(vec3(0), modf(2.2), vec3(0.5))', + bad_1int: '(vec3(0), 1i, vec3(0.5))', + bad_1uint: '(vec3(0), 1u, vec3(0.5))', + bad_1vec2i: '(vec2(1), vec2i(1), vec2(0.5))', + bad_1vec3i: '(vec3(1), vec3i(1), vec3(0.5))', + bad_1vec4i: '(vec4(1), vec4i(1), vec4(0.5))', + bad_1vec2u: '(vec2(1), vec2u(1), vec2(0.5))', + bad_1vec3u: '(vec3(1), vec3u(1), vec3(0.5))', + bad_1vec4u: '(vec4(1), vec4u(1), vec4(0.5))', + // Bad value type for arg 2 + bad_2bool: '(vec3(0), vec3(1), true)', + bad_2array: '(vec3(0), vec3(1), array(1.1,2.2))', + bad_2struct: '(vec3(0), vec3(1), modf(2.2))', + bad_2int: '(vec3(0), vec3(1), 1i)', + bad_2uint: '(vec3(0), vec3(1), 1u)', + bad_2vec2i: '(vec2(1), vec2(1), vec2i(1))', + bad_2vec3i: '(vec3(1), vec3(1), vec3i(1))', + bad_2vec4i: '(vec4(1), vec4(1), vec4i(1))', + bad_2vec2u: '(vec2(1), vec2(1), vec2u(1))', + bad_2vec3u: '(vec3(1), vec3(1), vec3u(1))', + bad_2vec4u: '(vec4(1), vec4(1), vec4u(1))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/firstLeadingBit.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/firstLeadingBit.spec.js new file mode 100644 index 0000000000..ab92243868 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/firstLeadingBit.spec.js @@ -0,0 +1,198 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'firstLeadingBit';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kFloatScalarsAndVectors } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConcreteIntegerScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) +). +fn((t) => { + const expectedResult = true; // firstLeadingBit() should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [kValuesTypes[t.params.type].create(t.params.value)], + t.params.stage + ); +}); + +// u32 is included here to confirm that validation is failing due to a type issue and not something else. +const kFloatTypes = objectsToRecord([Type.u32, ...kFloatScalarsAndVectors]); + +g.test('float_argument'). +desc( + ` +Validates that float arguments are rejected by ${builtin}() +` +). +params((u) => u.combine('type', keysOf(kFloatTypes))). +fn((t) => { + const type = kFloatTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */type === Type.u32, + [type.create(0)], + 'constant' + ); +}); + +const kTests = + + + + + + + + +{ + valid: { + args: '(1u)', + pass: true + }, + // Number of arguments. + no_parens: { + args: '', + pass: false + }, + too_few_args: { + args: '()', + pass: false + }, + too_many_args: { + args: '(1u,2u)', + pass: false + }, + // Arguments types (only 1 argument for this builtin). + alias: { + args: '(u32_alias(1))', + pass: true + }, + bool: { + args: '(false)', + pass: false + }, + vec_bool: { + args: '(vec2(false,true))', + pass: false + }, + matrix: { + args: '(mat2x2(1,1,1,1))', + pass: false + }, + atomic: { + args: '(a)', + pass: false + }, + array: { + preamble: 'var arry: array;', + args: '(arry)', + pass: false + }, + array_runtime: { + args: '(k.arry)', + pass: false + }, + struct: { + preamble: 'var x: A;', + args: '(x)', + pass: false + }, + enumerant: { + args: '(read_write)', + pass: false + }, + ptr: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(p)', + pass: false + }, + ptr_deref: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(*p)', + pass: true + }, + sampler: { + args: '(s)', + pass: false + }, + texture: { + args: '(t)', + pass: false + } +}; + +g.test('arguments'). +desc(`Test compilation validation of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const test = kTests[t.params.test]; + t.expectCompileResult( + test.pass, + `alias u32_alias = u32; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: u32, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + + @vertex + fn main() -> @builtin(position) vec4 { + ${test.preamble ? test.preamble : ''} + _ = ${builtin}${test.args}; + return vec4(.4, .2, .3, .1); + }` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(1u); }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/firstTrailingBit.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/firstTrailingBit.spec.js new file mode 100644 index 0000000000..9b0bc5f58f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/firstTrailingBit.spec.js @@ -0,0 +1,198 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'firstTrailingBit';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kFloatScalarsAndVectors } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConcreteIntegerScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) +). +fn((t) => { + const expectedResult = true; // firstTrailingBit() should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [kValuesTypes[t.params.type].create(t.params.value)], + t.params.stage + ); +}); + +// u32 is included here to confirm that validation is failing due to a type issue and not something else. +const kFloatTypes = objectsToRecord([Type.u32, ...kFloatScalarsAndVectors]); + +g.test('float_argument'). +desc( + ` +Validates that float arguments are rejected by ${builtin}() +` +). +params((u) => u.combine('type', keysOf(kFloatTypes))). +fn((t) => { + const type = kFloatTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */type === Type.u32, + [type.create(0)], + 'constant' + ); +}); + +const kTests = + + + + + + + + +{ + valid: { + args: '(1u)', + pass: true + }, + // Number of arguments. + no_parens: { + args: '', + pass: false + }, + too_few_args: { + args: '()', + pass: false + }, + too_many_args: { + args: '(1u,2u)', + pass: false + }, + // Arguments types (only 1 argument for this builtin). + alias: { + args: '(u32_alias(1))', + pass: true + }, + bool: { + args: '(false)', + pass: false + }, + vec_bool: { + args: '(vec2(false,true))', + pass: false + }, + matrix: { + args: '(mat2x2(1,1,1,1))', + pass: false + }, + atomic: { + args: '(a)', + pass: false + }, + array: { + preamble: 'var arry: array;', + args: '(arry)', + pass: false + }, + array_runtime: { + args: '(k.arry)', + pass: false + }, + struct: { + preamble: 'var x: A;', + args: '(x)', + pass: false + }, + enumerant: { + args: '(read_write)', + pass: false + }, + ptr: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(p)', + pass: false + }, + ptr_deref: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(*p)', + pass: true + }, + sampler: { + args: '(s)', + pass: false + }, + texture: { + args: '(t)', + pass: false + } +}; + +g.test('arguments'). +desc(`Test compilation validation of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const test = kTests[t.params.test]; + t.expectCompileResult( + test.pass, + `alias u32_alias = u32; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: u32, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + + @vertex + fn main() -> @builtin(position) vec4 { + ${test.preamble ? test.preamble : ''} + _ = ${builtin}${test.args}; + return vec4(.4, .2, .3, .1); + }` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(1u); }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/floor.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/floor.spec.js new file mode 100644 index 0000000000..6aa6f75310 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/floor.spec.js @@ -0,0 +1,108 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'floor';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const expectedResult = true; // floor() should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [kValuesTypes[t.params.type].create(t.params.value)], + t.params.stage + ); +}); + +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); + +g.test('integer_argument'). +desc( + ` +Validates that scalar and vector integer arguments are rejected by ${builtin}() +` +). +params((u) => u.combine('type', keysOf(kIntegerArgumentTypes))). +fn((t) => { + const type = kIntegerArgumentTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */type === Type.f32, + [type.create(0)], + 'constant' + ); +}); + +const kArgCases = { + good: '(1.1)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2args: '(1.0,2.0)', + // Bad value type for arg 0 + bad_0i32: '(1i)', + bad_0u32: '(1u)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/fract.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/fract.spec.js new file mode 100644 index 0000000000..2eb0f5a7a3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/fract.spec.js @@ -0,0 +1,94 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'fract';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidArgumentTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() error on invalid inputs. +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValidArgumentTypes)). +filter((u) => stageSupportsType(u.stage, kValidArgumentTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValidArgumentTypes[u.type])) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValidArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const expectedResult = true; + + const type = kValidArgumentTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.value)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(1.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.2, 2.3)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/frexp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/frexp.spec.js new file mode 100644 index 0000000000..e4a87551bb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/frexp.spec.js @@ -0,0 +1,94 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'frexp';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidArgumentTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() error on invalid inputs. +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValidArgumentTypes)). +filter((u) => stageSupportsType(u.stage, kValidArgumentTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValidArgumentTypes[u.type])) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValidArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const expectedResult = true; + + const type = kValidArgumentTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.value)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(1.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.2, 2.3)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/insertBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/insertBits.spec.js new file mode 100644 index 0000000000..e4645db0d9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/insertBits.spec.js @@ -0,0 +1,241 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'insertBits';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kFloatScalarsAndVectors, + u32 } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConcreteIntegerScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors on valid inputs +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValuesTypes[u.type], 5)). +expand('newbits', (u) => fullRangeForType(kValuesTypes[u.type], 5)). +combineWithParams([ +{ offset: 0, count: 0 }, +{ offset: 0, count: 31 }, +{ offset: 0, count: 32 }, +{ offset: 4, count: 0 }, +{ offset: 4, count: 27 }, +{ offset: 4, count: 28 }, +{ offset: 16, count: 0 }, +{ offset: 16, count: 15 }, +{ offset: 16, count: 16 }, +{ offset: 32, count: 0 }] +) +). +fn((t) => { + const expectedResult = true; // insertBits() should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [ + kValuesTypes[t.params.type].create(t.params.value), + kValuesTypes[t.params.type].create(t.params.newbits), + u32(t.params.offset), + u32(t.params.count)], + + t.params.stage + ); +}); + +g.test('mismatched'). +desc( + ` +Validates that even with valid types, if arg0 and arg1 do not match types ${builtin}() errors +` +). +params((u) => u.combine('arg0', keysOf(kValuesTypes)).combine('arg1', keysOf(kValuesTypes))). +fn((t) => { + const arg0 = kValuesTypes[t.params.arg0]; + const arg1 = kValuesTypes[t.params.arg1]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */t.params.arg0 === t.params.arg1, + [arg0.create(0), arg1.create(1), u32(0), u32(32)], + 'constant' + ); +}); + +g.test('count_offset'). +desc( + ` +Validates that count and offset must be smaller than the size of the primitive. +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +beginSubcases(). +combineWithParams([ +// offset + count < 32 +{ offset: 0, count: 31 }, +{ offset: 1, count: 30 }, +{ offset: 31, count: 0 }, +{ offset: 30, count: 1 }, +// offset + count == 32 +{ offset: 0, count: 32 }, +{ offset: 1, count: 31 }, +{ offset: 16, count: 16 }, +{ offset: 31, count: 1 }, +{ offset: 32, count: 0 }, +// offset + count > 32 +{ offset: 2, count: 31 }, +{ offset: 31, count: 2 }, +// offset > 32 +{ offset: 33, count: 0 }, +{ offset: 33, count: 1 }, +// count > 32 +{ offset: 0, count: 33 }, +{ offset: 1, count: 33 }] +) +). +fn((t) => { + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */t.params.offset + t.params.count <= 32, + [u32(0), u32(1), u32(t.params.offset), u32(t.params.count)], + t.params.stage + ); +}); + + + + + + + + + + +function typesToArguments(types, pass) { + return types.reduce( + (res, type) => ({ + ...res, + [type.toString()]: { arg: type.create(0).wgsl(), pass } + }), + {} + ); +} + +// u32 is included here to confirm that validation is failing due to a type issue and not something else. +const kInputArgTypes = { + ...typesToArguments([Type.u32], true), + ...typesToArguments([...kFloatScalarsAndVectors, Type.bool, Type.mat2x2f], false), + alias: { arg: 'u32_alias(1)', pass: true }, + vec_bool: { arg: 'vec2(false,true)', pass: false }, + atomic: { arg: 'a', pass: false }, + array: { + preamble: 'var arry: array;', + arg: 'arry', + pass: false + }, + array_runtime: { arg: 'k.arry', pass: false }, + struct: { + preamble: 'var x: A;', + arg: 'x', + pass: false + }, + enumerant: { arg: 'read_write', pass: false }, + ptr: { + preamble: `var f = 1u; + let p: ptr = &f;`, + arg: 'p', + pass: false + }, + ptr_deref: { + preamble: `var f = 1u; + let p: ptr = &f;`, + arg: '*p', + pass: true + }, + sampler: { arg: 's', pass: false }, + texture: { arg: 't', pass: false } +}; + +g.test('typed_arguments'). +desc( + ` +Test compilation validation of ${builtin} with variously typed arguments + - The input types are matching to reduce testing permutations. Mismatching input types are + validated in 'mismatched' test above. + - For failing input types, just use the same type for offset and count to reduce combinations. +` +). +params((u) => +u. +combine('input', keysOf(kInputArgTypes)). +beginSubcases(). +combine('offset', keysOf(kInputArgTypes)). +expand('count', (u) => kInputArgTypes[u.input].pass ? keysOf(kInputArgTypes) : [u.offset]) +). +fn((t) => { + const input = kInputArgTypes[t.params.input]; + const offset = kInputArgTypes[t.params.offset]; + const count = kInputArgTypes[t.params.count]; + t.expectCompileResult( + input.pass && offset.pass && count.pass, + `alias u32_alias = u32; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: u32, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + + @vertex + fn main() -> @builtin(position) vec4 { + ${input.preamble ? input.preamble : ''} + ${offset.preamble && offset !== input ? offset.preamble : ''} + ${count.preamble && count !== input && count !== offset ? count.preamble : ''} + _ = ${builtin}(${input.arg},${input.arg},${offset.arg},${count.arg}); + return vec4(.4, .2, .3, .1); + }` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(0u,1u,0u,1u); }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/inverseSqrt.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/inverseSqrt.spec.js index bb6c089450..128a9d390c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/inverseSqrt.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/inverseSqrt.spec.js @@ -6,11 +6,9 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -18,7 +16,7 @@ import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kMinusTwoToTwo, + minusTwoToTwoRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -26,7 +24,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -40,17 +38,27 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('value', (u) => unique(kMinusTwoToTwo, fullRangeForType(kValuesTypes[u.type]))) +expand('value', (u) => +unique( + minusTwoToTwoRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type]) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; const expectedResult = - t.params.value > 0 && isRepresentable(1 / Math.sqrt(t.params.value), elementType(type)); + t.params.value > 0 && + isRepresentable( + 1 / Math.sqrt(Number(t.params.value)), + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); validateConstOrOverrideBuiltinEval( t, builtin, @@ -60,22 +68,40 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kArgCases = { + good: '(1.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.2, 2.3)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())' +}; -g.test('integer_argument'). -desc( - ` -Validates that scalar and vector integer arguments are rejected by ${builtin}() -` -). -params((u) => u.combine('type', keysOf(kIntegerArgumentTypes))). +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). fn((t) => { - const type = kIntegerArgumentTypes[t.params.type]; - validateConstOrOverrideBuiltinEval( - t, - builtin, - /* expectedResult */type === TypeF32, - [type.create(1)], - 'constant' + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/length.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/length.spec.js index 12a28233e5..20ae5621a8 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/length.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/length.spec.js @@ -7,14 +7,13 @@ import { makeTestGroup } from '../../../../../../common/framework/test_group.js' import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalars, - kAllFloatVector2, - kAllFloatVector3, - kAllFloatVector4, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalar, + kConvertableToFloatVec2, + kConvertableToFloatVec3, + kConvertableToFloatVec4, + scalarTypeOf } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -49,16 +48,25 @@ type) { - const squareSum = vec.reduce((prev, curr) => prev + curr * curr, 0); + const vec_number = vec.map((e) => Number(e)); + const squareSum = vec_number.reduce((prev, curr) => prev + Number(curr) * Number(curr), 0); const result = Math.sqrt(squareSum); return { - isIntermediateRepresentable: isRepresentable(squareSum, type), - isResultRepresentable: isRepresentable(result, type), + isIntermediateRepresentable: isRepresentable( + squareSum, + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ), + isResultRepresentable: isRepresentable( + result, + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ), result }; } -const kScalarTypes = objectsToRecord(kAllFloatScalars); +const kScalarTypes = objectsToRecord(kConvertableToFloatScalar); g.test('scalar'). desc( @@ -76,7 +84,7 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kScalarTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kScalarTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kScalarTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -92,7 +100,7 @@ fn((t) => { ); }); -const kVec2Types = objectsToRecord(kAllFloatVector2); +const kVec2Types = objectsToRecord(kConvertableToFloatVec2); g.test('vec2'). desc( @@ -108,11 +116,11 @@ filter((u) => stageSupportsType(u.stage, kVec2Types[u.type])). beginSubcases(). expand('x', (u) => fullRangeForType(kVec2Types[u.type], 5)). expand('y', (u) => fullRangeForType(kVec2Types[u.type], 5)). -expand('_result', (u) => [calculate([u.x, u.y], elementType(kVec2Types[u.type]))]). +expand('_result', (u) => [calculate([u.x, u.y], scalarTypeOf(kVec2Types[u.type]))]). filter((u) => u._result.isResultRepresentable === u._result.isIntermediateRepresentable) ). beforeAllSubcases((t) => { - if (elementType(kVec2Types[t.params.type]) === TypeF16) { + if (scalarTypeOf(kVec2Types[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -127,7 +135,7 @@ fn((t) => { ); }); -const kVec3Types = objectsToRecord(kAllFloatVector3); +const kVec3Types = objectsToRecord(kConvertableToFloatVec3); g.test('vec3'). desc( @@ -144,11 +152,11 @@ beginSubcases(). expand('x', (u) => fullRangeForType(kVec3Types[u.type], 4)). expand('y', (u) => fullRangeForType(kVec3Types[u.type], 4)). expand('z', (u) => fullRangeForType(kVec3Types[u.type], 4)). -expand('_result', (u) => [calculate([u.x, u.y, u.z], elementType(kVec3Types[u.type]))]). +expand('_result', (u) => [calculate([u.x, u.y, u.z], scalarTypeOf(kVec3Types[u.type]))]). filter((u) => u._result.isResultRepresentable === u._result.isIntermediateRepresentable) ). beforeAllSubcases((t) => { - if (elementType(kVec3Types[t.params.type]) === TypeF16) { + if (scalarTypeOf(kVec3Types[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -163,7 +171,7 @@ fn((t) => { ); }); -const kVec4Types = objectsToRecord(kAllFloatVector4); +const kVec4Types = objectsToRecord(kConvertableToFloatVec4); g.test('vec4'). desc( @@ -181,11 +189,11 @@ expand('x', (u) => fullRangeForType(kVec4Types[u.type], 3)). expand('y', (u) => fullRangeForType(kVec4Types[u.type], 3)). expand('z', (u) => fullRangeForType(kVec4Types[u.type], 3)). expand('w', (u) => fullRangeForType(kVec4Types[u.type], 3)). -expand('_result', (u) => [calculate([u.x, u.y, u.z, u.w], elementType(kVec4Types[u.type]))]). +expand('_result', (u) => [calculate([u.x, u.y, u.z, u.w], scalarTypeOf(kVec4Types[u.type]))]). filter((u) => u._result.isResultRepresentable === u._result.isIntermediateRepresentable) ). beforeAllSubcases((t) => { - if (elementType(kVec4Types[t.params.type]) === TypeF16) { + if (scalarTypeOf(kVec4Types[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -200,7 +208,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -214,7 +222,7 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(1)], 'constant' ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/log.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/log.spec.js index fb911b4188..5b73577235 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/log.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/log.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -23,7 +22,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -40,7 +39,7 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -55,7 +54,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -69,8 +68,41 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(1)], 'constant' ); +}); + +const kArgCases = { + good: '(1.1)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2args: '(1.0,2.0)', + // Bad value type for arg 0 + bad_0i32: '(1i)', + bad_0u32: '(1u)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/log2.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/log2.spec.js index 4e538fbb77..60403807a6 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/log2.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/log2.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -23,7 +22,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -40,7 +39,7 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -55,7 +54,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -69,8 +68,41 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(1)], 'constant' ); +}); + +const kArgCases = { + good: '(1.1)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2args: '(1.0,2.0)', + // Bad value type for arg 0 + bad_0i32: '(1i)', + bad_0u32: '(1u)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/max.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/max.spec.js new file mode 100644 index 0000000000..6a550cfbc4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/max.spec.js @@ -0,0 +1,91 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'max';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllNumericScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kAllNumericScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('a', (u) => fullRangeForType(kValuesTypes[u.type], 5)). +expand('b', (u) => fullRangeForType(kValuesTypes[u.type], 5)) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kValuesTypes[t.params.type]; + const expectedResult = true; // should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.a), type.create(t.params.b)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(1.1, 2.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_1arg: '(1.0)', + bad_3arg: '(1.0, 2.0, 3.0)', + // Bad value for arg 0 + bad_0bool: '(false, 1.0)', + bad_0array: '(array(1.1,2.2), 1.0)', + bad_0struct: '(modf(2.2), 1.0)', + // Bad value type for arg 1 + bad_1bool: '(1.0, true)', + bad_1array: '(1.0, array(1.1,2.2))', + bad_1struct: '(1.0, modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/min.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/min.spec.js new file mode 100644 index 0000000000..377480a029 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/min.spec.js @@ -0,0 +1,91 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'min';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllNumericScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kAllNumericScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('a', (u) => fullRangeForType(kValuesTypes[u.type], 5)). +expand('b', (u) => fullRangeForType(kValuesTypes[u.type], 5)) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kValuesTypes[t.params.type]; + const expectedResult = true; // should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.a), type.create(t.params.b)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(1.1, 2.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_1arg: '(1.0)', + bad_3arg: '(1.0, 2.0, 3.0)', + // Bad value for arg 0 + bad_0bool: '(false, 1.0)', + bad_0array: '(array(1.1,2.2), 1.0)', + bad_0struct: '(modf(2.2), 1.0)', + // Bad value type for arg 1 + bad_1bool: '(1.0, true)', + bad_1array: '(1.0, array(1.1,2.2))', + bad_1struct: '(1.0, modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/modf.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/modf.spec.js index d3937bc4f3..a2edc6dd4d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/modf.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/modf.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -23,7 +22,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -40,7 +39,7 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -55,7 +54,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -69,7 +68,7 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(0)], 'constant' ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/normalize.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/normalize.spec.js new file mode 100644 index 0000000000..b696401dba --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/normalize.spec.js @@ -0,0 +1,146 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'normalize';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatVectors, + scalarTypeOf } from + +'../../../../../util/conversion.js'; +import { quantizeToF16, quantizeToF32 } from '../../../../../util/math.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidArgumentTypes = objectsToRecord(kConvertableToFloatVectors); + +function quantizeFunctionForScalarType(type) { + switch (type) { + case Type.f32: + return quantizeToF32; + case Type.f16: + return quantizeToF16; + default: + return (v) => v; + } +} + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() rejects invalid values +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValidArgumentTypes)). +filter((u) => stageSupportsType(u.stage, kValidArgumentTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValidArgumentTypes[u.type])) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValidArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + let expectedResult = true; + + const scalarType = scalarTypeOf(kValidArgumentTypes[t.params.type]); + const quantizeFn = quantizeFunctionForScalarType(scalarType); + + // Should be invalid if the normalization calculations result in intermediate + // values that exceed the maximum representable float value for the given type, + // or if the length is smaller than the smallest representable float value. + const v = Number(t.params.value); + const vv = quantizeFn(v * v); + const dp = quantizeFn(vv * kValidArgumentTypes[t.params.type].width); + const len = quantizeFn(Math.sqrt(dp)); + if (vv === Infinity || dp === Infinity || len === 0) { + expectedResult = false; + } + + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [kValidArgumentTypes[t.params.type].create(t.params.value)], + t.params.stage + ); +}); + +const kInvalidArgumentTypes = objectsToRecord([ +Type.f32, +Type.f16, +Type.abstractInt, +Type.bool, +Type.vec(2, Type.bool), +Type.vec(3, Type.bool), +Type.vec(4, Type.bool), +...kConcreteIntegerScalarsAndVectors] +); + +g.test('invalid_argument'). +desc( + ` +Validates that all scalar arguments and vector integer or boolean arguments are rejected by ${builtin}() +` +). +params((u) => u.combine('type', keysOf(kInvalidArgumentTypes))). +beforeAllSubcases((t) => { + if (kInvalidArgumentTypes[t.params.type] === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const expectedResult = false; // should always error with invalid argument types + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [kInvalidArgumentTypes[t.params.type].create(0)], + 'constant' + ); +}); + +const kArgCases = { + good: '(vec3f(1, 0, 0))', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2args: '(vec3f(),vec3f())', + // Bad value for arg 0 + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack2x16snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack2x16snorm.spec.js new file mode 100644 index 0000000000..1059208d45 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack2x16snorm.spec.js @@ -0,0 +1,58 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const kFn = 'pack2x16snorm';export const description = `Validate ${kFn}`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kArgCases = { + good: '(vec2f())', + good_vec2_abstract_float: '(vec2(0.1))', + bad_0args: '()', + bad_2args: '(vec2f(),vec2f())', + bad_abstract_int: '(1)', + bad_i32: '(1i)', + bad_f32: '(1f)', + bad_u32: '(1u)', + bad_abstract_float: '(0.1)', + bad_bool: '(false)', + bad_vec4f: '(vec4f())', + bad_vec4u: '(vec4u())', + bad_vec4i: '(vec4i())', + bad_vec4b: '(vec4())', + bad_vec3f: '(vec3f())', + bad_array: '(array(1.0, 2.0, 3.0, 4.0))', + bad_struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; +const kReturnType = 'u32'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good' || t.params.arg === 'good_vec2_abstract_float', + `const c = ${kFn}${kArgCases[t.params.arg]};` + ); +}); + +g.test('return'). +desc(`Test ${kFn} return value type`). +params((u) => u.combine('type', ['u32', 'i32', 'f32', 'bool', 'vec2u'])). +fn((t) => { + t.expectCompileResult( + t.params.type === kReturnType, + `const c: ${t.params.type} = ${kFn}${kGoodArgs};` + ); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack2x16unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack2x16unorm.spec.js new file mode 100644 index 0000000000..eb29dd5b41 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack2x16unorm.spec.js @@ -0,0 +1,58 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const kFn = 'pack2x16unorm';export const description = `Validate ${kFn}`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kArgCases = { + good: '(vec2f())', + good_vec2_abstract_float: '(vec2(0.1))', + bad_0args: '()', + bad_2args: '(vec2f(),vec2f())', + bad_abstract_int: '(1)', + bad_i32: '(1i)', + bad_f32: '(1f)', + bad_u32: '(1u)', + bad_abstract_float: '(0.1)', + bad_bool: '(false)', + bad_vec4f: '(vec4f())', + bad_vec4u: '(vec4u())', + bad_vec4i: '(vec4i())', + bad_vec4b: '(vec4())', + bad_vec3f: '(vec3f())', + bad_array: '(array(1.0, 2.0, 3.0, 4.0))', + bad_struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; +const kReturnType = 'u32'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good' || t.params.arg === 'good_vec2_abstract_float', + `const c = ${kFn}${kArgCases[t.params.arg]};` + ); +}); + +g.test('return'). +desc(`Test ${kFn} return value type`). +params((u) => u.combine('type', ['u32', 'i32', 'f32', 'bool', 'vec2u'])). +fn((t) => { + t.expectCompileResult( + t.params.type === kReturnType, + `const c: ${t.params.type} = ${kFn}${kGoodArgs};` + ); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4x8snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4x8snorm.spec.js new file mode 100644 index 0000000000..09c9008d61 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4x8snorm.spec.js @@ -0,0 +1,58 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const kFn = 'pack4x8snorm';export const description = `Validate ${kFn}`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kArgCases = { + good: '(vec4f())', + good_vec4_abstract_float: '(vec4(0.1))', + bad_0args: '()', + bad_2args: '(vec4f(),vec4f())', + bad_abstract_int: '(1)', + bad_i32: '(1i)', + bad_f32: '(1f)', + bad_u32: '(1u)', + bad_abstract_float: '(0.1)', + bad_bool: '(false)', + bad_vec4u: '(vec4u())', + bad_vec4i: '(vec4i())', + bad_vec4b: '(vec4())', + bad_vec2f: '(vec2f())', + bad_vec3f: '(vec3f())', + bad_array: '(array(1.0, 2.0, 3.0, 4.0))', + bad_struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; +const kReturnType = 'u32'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good' || t.params.arg === 'good_vec4_abstract_float', + `const c = ${kFn}${kArgCases[t.params.arg]};` + ); +}); + +g.test('return'). +desc(`Test ${kFn} return value type`). +params((u) => u.combine('type', ['u32', 'i32', 'f32', 'bool', 'vec2u'])). +fn((t) => { + t.expectCompileResult( + t.params.type === kReturnType, + `const c: ${t.params.type} = ${kFn}${kGoodArgs};` + ); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4x8unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4x8unorm.spec.js new file mode 100644 index 0000000000..a0ff836f44 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4x8unorm.spec.js @@ -0,0 +1,58 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const kFn = 'pack4x8unorm';export const description = `Validate ${kFn}`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kArgCases = { + good: '(vec4f())', + good_vec4_abstract_float: '(vec4(0.1))', + bad_0args: '()', + bad_2args: '(vec4f(),vec4f())', + bad_abstract_int: '(1)', + bad_i32: '(1i)', + bad_f32: '(1f)', + bad_u32: '(1u)', + bad_abstract_float: '(0.1)', + bad_bool: '(false)', + bad_vec4u: '(vec4u())', + bad_vec4i: '(vec4i())', + bad_vec4b: '(vec4())', + bad_vec2f: '(vec2f())', + bad_vec3f: '(vec3f())', + bad_array: '(array(1.0, 2.0, 3.0, 4.0))', + bad_struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; +const kReturnType = 'u32'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good' || t.params.arg === 'good_vec4_abstract_float', + `const c = ${kFn}${kArgCases[t.params.arg]};` + ); +}); + +g.test('return'). +desc(`Test ${kFn} return value type`). +params((u) => u.combine('type', ['u32', 'i32', 'f32', 'bool', 'vec2u'])). +fn((t) => { + t.expectCompileResult( + t.params.type === kReturnType, + `const c: ${t.params.type} = ${kFn}${kGoodArgs};` + ); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xI8.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xI8.spec.js new file mode 100644 index 0000000000..4d9caa575c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xI8.spec.js @@ -0,0 +1,62 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validate pack4xI8`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kFeature = 'packed_4x8_integer_dot_product'; +const kFn = 'pack4xI8'; +const kArgCases = { + good: '(vec4i())', + bad_0args: '()', + bad_2args: '(vec4i(),vec4i())', + bad_0i32: '(1i)', + bad_0f32: '(1f)', + bad_0bool: '(false)', + bad_0vec4u: '(vec4u())', + bad_0vec4f: '(vec4f())', + bad_0vec4b: '(vec4())', + bad_0vec2i: '(vec2i())', + bad_0vec3i: '(vec3i())', + bad_0array: '(array(1))', + bad_0struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('unsupported'). +desc(`Test absence of ${kFn} when ${kFeature} is not supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(false, code); +}); + +g.test('supported'). +desc(`Test presence of ${kFn} when ${kFeature} is supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(true, code); +}); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + t.expectCompileResult(t.params.arg === 'good', `const c = ${kFn}${kArgCases[t.params.arg]};`); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xI8Clamp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xI8Clamp.spec.js new file mode 100644 index 0000000000..dcd3af2633 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xI8Clamp.spec.js @@ -0,0 +1,62 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validate pack4xI8Clamp`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kFeature = 'packed_4x8_integer_dot_product'; +const kFn = 'pack4xI8Clamp'; +const kArgCases = { + good: '(vec4i())', + bad_0args: '()', + bad_2args: '(vec4i(),vec4i())', + bad_0i32: '(1i)', + bad_0f32: '(1f)', + bad_0bool: '(false)', + bad_0vec4u: '(vec4u())', + bad_0vec4f: '(vec4f())', + bad_0vec4b: '(vec4())', + bad_0vec2i: '(vec2i())', + bad_0vec3i: '(vec3i())', + bad_0array: '(array(1))', + bad_0struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('unsupported'). +desc(`Test absence of ${kFn} when ${kFeature} is not supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(false, code); +}); + +g.test('supported'). +desc(`Test presence of ${kFn} when ${kFeature} is supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(true, code); +}); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + t.expectCompileResult(t.params.arg === 'good', `const c = ${kFn}${kArgCases[t.params.arg]};`); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xU8.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xU8.spec.js new file mode 100644 index 0000000000..ef5483c2ae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xU8.spec.js @@ -0,0 +1,62 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validate pack4xU8`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kFeature = 'packed_4x8_integer_dot_product'; +const kFn = 'pack4xU8'; +const kArgCases = { + good: '(vec4u())', + bad_0args: '()', + bad_2args: '(vec4u(),vec4u())', + bad_0i32: '(1i)', + bad_0f32: '(1f)', + bad_0bool: '(false)', + bad_0vec4i: '(vec4i())', + bad_0vec4f: '(vec4f())', + bad_0vec4b: '(vec4())', + bad_0vec2u: '(vec2u())', + bad_0vec3u: '(vec3u())', + bad_0array: '(array(1))', + bad_0struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('unsupported'). +desc(`Test absence of ${kFn} when ${kFeature} is not supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(false, code); +}); + +g.test('supported'). +desc(`Test presence of ${kFn} when ${kFeature} is supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(true, code); +}); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + t.expectCompileResult(t.params.arg === 'good', `const c = ${kFn}${kArgCases[t.params.arg]};`); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xU8Clamp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xU8Clamp.spec.js new file mode 100644 index 0000000000..46505239aa --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/pack4xU8Clamp.spec.js @@ -0,0 +1,62 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validate pack4xU8Clamp`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kFeature = 'packed_4x8_integer_dot_product'; +const kFn = 'pack4xU8Clamp'; +const kArgCases = { + good: '(vec4u())', + bad_0args: '()', + bad_2args: '(vec4u(),vec4u())', + bad_0i32: '(1i)', + bad_0f32: '(1f)', + bad_0bool: '(false)', + bad_0vec4i: '(vec4i())', + bad_0vec4f: '(vec4f())', + bad_0vec4b: '(vec4())', + bad_0vec2u: '(vec2u())', + bad_0vec3u: '(vec3u())', + bad_0array: '(array(1))', + bad_0struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('unsupported'). +desc(`Test absence of ${kFn} when ${kFeature} is not supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(false, code); +}); + +g.test('supported'). +desc(`Test presence of ${kFn} when ${kFeature} is supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(true, code); +}); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + t.expectCompileResult(t.params.arg === 'good', `const c = ${kFn}${kArgCases[t.params.arg]};`); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/quantizeToF16.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/quantizeToF16.spec.js new file mode 100644 index 0000000000..cbea6ffa40 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/quantizeToF16.spec.js @@ -0,0 +1,113 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'quantizeToF16';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { Type, kConcreteF32ScalarsAndVectors } from '../../../../../util/conversion.js'; +import { quantizeToF16 } from '../../../../../util/math.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidArgumentTypes = objectsToRecord([ +Type.abstractFloat, +Type.vec(2, Type.abstractFloat), +Type.vec(3, Type.abstractFloat), +Type.vec(4, Type.abstractFloat), +...kConcreteF32ScalarsAndVectors] +); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() error on invalid inputs. +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValidArgumentTypes)). +filter((u) => stageSupportsType(u.stage, kValidArgumentTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValidArgumentTypes[u.type])) +). +fn((t) => { + let expectedResult = true; + + // Should be invalid if the quantized value exceeds the maximum representable + // 16-bit float value. + const f16Value = quantizeToF16(Number(t.params.value)); + if (f16Value === Infinity || f16Value === -Infinity) { + expectedResult = false; + } + + const type = kValidArgumentTypes[t.params.type]; + + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.value)], + t.params.stage + ); +}); + +const kArgCasesF16 = { + bad_0f16: '(1h)', + bad_0vec2h: '(vec2h())', + bad_0vec3h: '(vec3h())', + bad_0vec4h: '(vec4h())' +}; + +const kArgCases = { + good: '(vec3f())', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.0, 2.0)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())', + ...kArgCasesF16 +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +beforeAllSubcases((t) => { + if (t.params.arg in kArgCasesF16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/radians.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/radians.spec.js index 51e1c451a3..6d8a5511de 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/radians.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/radians.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -23,7 +22,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -40,7 +39,7 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -55,7 +54,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -69,8 +68,41 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(1)], 'constant' ); +}); + +const kArgCases = { + good: '(1.1)', + bad_no_parens: '', + // Bad number of args + bad_too_few: '()', + bad_too_many: '(1.0,2.0)', + // Bad value type for arg 0 + bad_0i32: '(1i)', + bad_0u32: '(1u)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/reflect.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/reflect.spec.js new file mode 100644 index 0000000000..f90cfc116a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/reflect.spec.js @@ -0,0 +1,131 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'reflect';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConvertableToFloatVectors, + scalarTypeOf } from + +'../../../../../util/conversion.js'; +import { quantizeToF16, quantizeToF32 } from '../../../../../util/math.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidArgumentTypes = objectsToRecord(kConvertableToFloatVectors); + +function quantizeFunctionForScalarType(type) { + switch (type) { + case Type.f32: + return quantizeToF32; + case Type.f16: + return quantizeToF16; + default: + return (v) => v; + } +} + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValidArgumentTypes)). +filter((u) => stageSupportsType(u.stage, kValidArgumentTypes[u.type])). +beginSubcases(). +expand('a', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)). +expand('b', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValidArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + let expectedResult = true; + + const scalarType = scalarTypeOf(kValidArgumentTypes[t.params.type]); + const quantizeFn = quantizeFunctionForScalarType(scalarType); + + // Reflect equation: a - 2 * dot(b, a) * b + // Should be invalid if the reflect calculations result in intermediate + // values that exceed the maximum representable float value for the given type. + const a = Number(t.params.a); + const b = Number(t.params.b); + const ab = quantizeFn(a * b); + const dp = quantizeFn(ab * kValidArgumentTypes[t.params.type].width); + const dp2 = quantizeFn(dp * 2); + const dp2b = quantizeFn(dp2 * b); + const a_dp2b = quantizeFn(a - dp2b); + + if ( + !Number.isFinite(ab) || + !Number.isFinite(dp) || + !Number.isFinite(dp2) || + !Number.isFinite(dp2b) || + !Number.isFinite(a_dp2b)) + { + expectedResult = false; + } + + const type = kValidArgumentTypes[t.params.type]; + + // Validates reflect(vecN(a, a, a), vecN(b, b, b)); + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.a), type.create(t.params.b)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(vec3(0), vec3(1))', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_1arg: '(vec3(0))', + bad_3arg: '(vec3(0), vec3(1), vec3(2))', + // Bad value for arg 0 + bad_0bool: '(false, vec3(1))', + bad_0array: '(array(1.1,2.2), vec3(1))', + bad_0struct: '(modf(2.2), vec3(1))', + // Bad value type for arg 1 + bad_1bool: '(vec3(0), true)', + bad_1array: '(vec3(0), array(1.1,2.2))', + bad_1struct: '(vec3(0), modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/reverseBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/reverseBits.spec.js new file mode 100644 index 0000000000..f1560d6d06 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/reverseBits.spec.js @@ -0,0 +1,198 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'reverseBits';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConcreteIntegerScalarsAndVectors, + kFloatScalarsAndVectors } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConcreteIntegerScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() never errors +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) +). +fn((t) => { + const expectedResult = true; // reverseBits() should never error + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [kValuesTypes[t.params.type].create(t.params.value)], + t.params.stage + ); +}); + +// u32 is included here to confirm that validation is failing due to a type issue and not something else. +const kFloatTypes = objectsToRecord([Type.u32, ...kFloatScalarsAndVectors]); + +g.test('float_argument'). +desc( + ` +Validates that float arguments are rejected by ${builtin}() +` +). +params((u) => u.combine('type', keysOf(kFloatTypes))). +fn((t) => { + const type = kFloatTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */type === Type.u32, + [type.create(0)], + 'constant' + ); +}); + +const kTests = + + + + + + + + +{ + valid: { + args: '(1u)', + pass: true + }, + // Number of arguments. + no_parens: { + args: '', + pass: false + }, + too_few_args: { + args: '()', + pass: false + }, + too_many_args: { + args: '(1u,2u)', + pass: false + }, + // Arguments types (only 1 argument for this builtin). + alias: { + args: '(u32_alias(1))', + pass: true + }, + bool: { + args: '(false)', + pass: false + }, + vec_bool: { + args: '(vec2(false,true))', + pass: false + }, + matrix: { + args: '(mat2x2(1,1,1,1))', + pass: false + }, + atomic: { + args: '(a)', + pass: false + }, + array: { + preamble: 'var arry: array;', + args: '(arry)', + pass: false + }, + array_runtime: { + args: '(k.arry)', + pass: false + }, + struct: { + preamble: 'var x: A;', + args: '(x)', + pass: false + }, + enumerant: { + args: '(read_write)', + pass: false + }, + ptr: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(p)', + pass: false + }, + ptr_deref: { + preamble: `var f = 1u; + let p: ptr = &f;`, + args: '(*p)', + pass: true + }, + sampler: { + args: '(s)', + pass: false + }, + texture: { + args: '(t)', + pass: false + } +}; + +g.test('arguments'). +desc(`Test compilation validation of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('test', keysOf(kTests))). +fn((t) => { + const test = kTests[t.params.test]; + t.expectCompileResult( + test.pass, + `alias u32_alias = u32; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: u32, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + + @vertex + fn main() -> @builtin(position) vec4 { + ${test.preamble ? test.preamble : ''} + _ = ${builtin}${test.args}; + return vec4(.4, .2, .3, .1); + }` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(1u); }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/round.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/round.spec.js index a90c17e10c..63ca9abc08 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/round.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/round.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { fpTraitsFor } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -25,7 +24,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -40,15 +39,19 @@ combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). expand('value', (u) => { - const constants = fpTraitsFor(elementType(kValuesTypes[u.type])).constants(); - return unique(fullRangeForType(kValuesTypes[u.type]), [ - constants.negative.min + 0.1, - constants.positive.max - 0.1] - ); + if (scalarTypeOf(kValuesTypes[u.type]).kind === 'abstract-int') { + return fullRangeForType(kValuesTypes[u.type]); + } else { + const constants = fpTraitsFor(scalarTypeOf(kValuesTypes[u.type])).constants(); + return unique(fullRangeForType(kValuesTypes[u.type]), [ + constants.negative.min + 0.1, + constants.positive.max - 0.1] + ); + } }) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -63,7 +66,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -77,7 +80,7 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(1)], 'constant' ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/saturate.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/saturate.spec.js index acf8bb059f..b6154f4a89 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/saturate.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/saturate.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -23,7 +22,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -40,7 +39,7 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -55,7 +54,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -69,7 +68,7 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(1)], 'constant' ); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/select.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/select.spec.js new file mode 100644 index 0000000000..7d3d56c2d5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/select.spec.js @@ -0,0 +1,250 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'select';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + concreteTypeOf, + isConvertible, + kAllScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { validateConstOrOverrideBuiltinEval } from './const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kArgumentTypes = objectsToRecord(kAllScalarsAndVectors); + +g.test('argument_types_1_and_2'). +desc( + ` +Validates that scalar and vector arguments are not rejected by ${builtin}() for args 1 and 2 +` +). +params((u) => u.combine('type1', keysOf(kArgumentTypes)).combine('type2', keysOf(kArgumentTypes))). +beforeAllSubcases((t) => { + if ( + scalarTypeOf(kArgumentTypes[t.params.type1]) === Type.f16 || + scalarTypeOf(kArgumentTypes[t.params.type2]) === Type.f16) + { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type1 = kArgumentTypes[t.params.type1]; + const type2 = kArgumentTypes[t.params.type2]; + // First and second arg must be the same or one convertible to the other. + // Note that we specify a concrete return type even if both args are abstract. + const returnType = isConvertible(type1, type2) ? + concreteTypeOf(type2) : + isConvertible(type2, type1) ? + concreteTypeOf(type1) : + undefined; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */returnType !== undefined, + [type1.create(0), type2.create(0), Type.bool.create(0)], + 'constant', + returnType + ); +}); + +g.test('argument_types_3'). +desc( + ` +Validates that third argument must be bool for ${builtin}() +` +). +params((u) => u.combine('type', keysOf(kArgumentTypes))). +beforeAllSubcases((t) => { + if (scalarTypeOf(kArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kArgumentTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */type === Type.bool, + [Type.i32.create(0), Type.i32.create(0), type.create(0)], + 'constant', + /*return_type*/Type.i32 + ); +}); + +const kTests = { + valid: { + src: `_ = ${builtin}(1, 2, true);`, + pass: true + }, + alias: { + src: `_ = ${builtin}(i32_alias(1), i32_alias(2), bool_alias(true));`, + pass: true + }, + bool: { + src: `_ = ${builtin}(false, false, true);`, + pass: true + }, + i32: { + src: `_ = ${builtin}(1i, 1i, true);`, + pass: true + }, + u32: { + src: `_ = ${builtin}(1u, 1u, true);`, + pass: true + }, + f32: { + src: `_ = ${builtin}(1.0f, 1.0f, true);`, + pass: true + }, + f16: { + src: `_ = ${builtin}(1.0h, 1.0h, true);`, + pass: true + }, + mixed_aint_afloat: { + src: `_ = ${builtin}(1, 1.0, true);`, + pass: true + }, + mixed_i32_u32: { + src: `_ = ${builtin}(1i, 1u, true);`, + pass: false + }, + vec_bool: { + src: `_ = ${builtin}(vec2(false, true), vec2(false, true), true);`, + pass: true + }, + vec2_bool_implicit: { + src: `_ = ${builtin}(vec2(false, true), vec2(false, true), true);`, + pass: true + }, + vec3_bool_implicit: { + src: `_ = ${builtin}(vec3(false), vec3(true), true);`, + pass: true + }, + vec_i32: { + src: `_ = ${builtin}(vec2(1, 1), vec2(1, 1), true);`, + pass: true + }, + vec_u32: { + src: `_ = ${builtin}(vec2(1, 1), vec2(1, 1), true);`, + pass: true + }, + vec_f32: { + src: `_ = ${builtin}(vec2(1, 1), vec2(1, 1), true);`, + pass: true + }, + vec_f16: { + src: `_ = ${builtin}(vec2(1, 1), vec2(1, 1), true);`, + pass: true + }, + matrix: { + src: `_ = ${builtin}(mat2x2(1, 1, 1, 1), mat2x2(1, 1, 1, 1), true);`, + pass: false + }, + atomic: { + src: ` _ = ${builtin}(a, a, true);`, + pass: false + }, + array: { + src: `var a: array; + _ = ${builtin}(a, a, true);`, + pass: false + }, + array_runtime: { + src: `_ = ${builtin}(k.arry, k.arry, true);`, + pass: false + }, + struct: { + src: `var a: A; + _ = ${builtin}(a, a, true);`, + pass: false + }, + enumerant: { + src: `_ = ${builtin}(read_write, read_write, true);`, + pass: false + }, + ptr: { + src: `var a = true; + let p: ptr = &a; + _ = ${builtin}(p, p, true);`, + pass: false + }, + ptr_deref: { + src: `var a = true; + let p: ptr = &a; + _ = ${builtin}(*p, *p, true);`, + pass: true + }, + sampler: { + src: `_ = ${builtin}(s, s, true);`, + pass: false + }, + texture: { + src: `_ = ${builtin}(t, t, true);`, + pass: false + }, + no_args: { + src: `_ = ${builtin}();`, + pass: false + }, + too_few_args: { + src: `_ = ${builtin}(1, true);`, + pass: false + }, + too_many_args: { + src: `_ = ${builtin}(1, 1, 1, true);`, + pass: false + } +}; + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}(1, 2, true); }`); +}); + +g.test('arguments'). +desc(`Test that ${builtin} is validated correctly.`). +params((u) => u.combine('test', keysOf(kTests))). +beforeAllSubcases((t) => { + if (t.params.test.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const src = kTests[t.params.test].src; + const enables = t.params.test.includes('f16') ? 'enable f16;' : ''; + const code = ` + ${enables} + alias bool_alias = bool; + alias i32_alias = i32; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: bool, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + @vertex + fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); + }`; + t.expectCompileResult(kTests[t.params.test].pass, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/shader_stage_utils.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/shader_stage_utils.js new file mode 100644 index 0000000000..8a563e7c78 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/shader_stage_utils.js @@ -0,0 +1,64 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ /** + * Use to test that certain WGSL builtins are only available in the fragment stage. + * Create WGSL that defines a function "foo" and its required variables that uses + * the builtin being tested. Append it to these code strings then compile. It should + * succeed or fail based on the value `expectSuccess`. + * + * See ./textureSample.spec.ts was one example + */export const kEntryPointsToValidateFragmentOnlyBuiltins = { none: { + expectSuccess: true, + code: `` + }, + fragment: { + expectSuccess: true, + code: ` + @fragment + fn main() { + foo(); + } + ` + }, + vertex: { + expectSuccess: false, + code: ` + @vertex + fn main() -> @builtin(position) vec4f { + foo(); + return vec4f(); + } + ` + }, + compute: { + expectSuccess: false, + code: ` + @compute @workgroup_size(1) + fn main() { + foo(); + } + ` + }, + fragment_and_compute: { + expectSuccess: false, + code: ` + @fragment + fn main1() { + foo(); + } + + @compute @workgroup_size(1) + fn main2() { + foo(); + } + ` + }, + compute_without_call: { + expectSuccess: true, + code: ` + @compute @workgroup_size(1) + fn main() { + } + ` + } +}; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sign.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sign.spec.js index 7a08bac5f9..1e458aa9d0 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sign.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sign.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatAndSignedIntegerScalarsAndVectors, - kAllUnsignedIntegerScalarsAndVectors } from + Type, + kFloatScalarsAndVectors, + kConcreteSignedIntegerScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -23,7 +22,10 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatAndSignedIntegerScalarsAndVectors); +const kValuesTypes = objectsToRecord([ +...kFloatScalarsAndVectors, +...kConcreteSignedIntegerScalarsAndVectors] +); g.test('values'). desc( @@ -40,7 +42,7 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -55,25 +57,36 @@ fn((t) => { ); }); -const kUnsignedIntegerArgumentTypes = objectsToRecord([ -TypeF32, -...kAllUnsignedIntegerScalarsAndVectors] -); +const kArgCases = { + good: '(1.0)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.0, 1.0)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0vec2u: '(vec2u(1))', + bad_0vec3u: '(vec3u(1))', + bad_0vec4u: '(vec4u(1))' +}; -g.test('unsigned_integer_argument'). -desc( - ` -Validates that scalar and vector integer arguments are rejected by ${builtin}() -` -). -params((u) => u.combine('type', keysOf(kUnsignedIntegerArgumentTypes))). +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). fn((t) => { - const type = kUnsignedIntegerArgumentTypes[t.params.type]; - validateConstOrOverrideBuiltinEval( - t, - builtin, - /* expectedResult */type === TypeF32, - [type.create(1)], - 'constant' + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sin.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sin.spec.js index 716311f20c..fd629bf7ed 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sin.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sin.spec.js @@ -6,18 +6,17 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kMinus3PiTo3Pi, + minusThreePiToThreePiRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -25,7 +24,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -39,10 +38,15 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('value', (u) => unique(kMinus3PiTo3Pi, fullRangeForType(kValuesTypes[u.type]))) +expand('value', (u) => +unique( + minusThreePiToThreePiRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type]) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). @@ -56,7 +60,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -70,8 +74,42 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, + [type.create(0)], 'constant' ); +}); + +const kArgCases = { + good: '(1.1)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2args: '(1.0,2.0)', + // Bad value type for arg 0 + bad_0i32: '(1i)', + bad_0u32: '(1u)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sinh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sinh.spec.js index c654132960..e35fb84e72 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sinh.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sinh.spec.js @@ -6,11 +6,9 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -24,7 +22,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -41,13 +39,17 @@ beginSubcases(). expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; - const expectedResult = isRepresentable(Math.sinh(t.params.value), elementType(type)); + const expectedResult = isRepresentable( + Math.sinh(Number(t.params.value)), + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); validateConstOrOverrideBuiltinEval( t, builtin, @@ -57,22 +59,40 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kArgCases = { + good: '(1.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.2, 2.3)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())' +}; -g.test('integer_argument'). -desc( - ` -Validates that scalar and vector integer arguments are rejected by ${builtin}() -` -). -params((u) => u.combine('type', keysOf(kIntegerArgumentTypes))). +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). fn((t) => { - const type = kIntegerArgumentTypes[t.params.type]; - validateConstOrOverrideBuiltinEval( - t, - builtin, - /* expectedResult */type === TypeF32, - [type.create(0)], - 'constant' + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/smoothstep.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/smoothstep.spec.js new file mode 100644 index 0000000000..1e1855a828 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/smoothstep.spec.js @@ -0,0 +1,241 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'smoothstep';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + concreteTypeOf, + elementTypeOf, + isConvertibleToFloatType, + kAllScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); +const kArgumentTypes = objectsToRecord(kAllScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() rejects invalid values +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value1', (u) => [-1000, -10, 0, 10, 1000]). +expand('value2', (u) => [-1000, -10, 0, 10, 1000]) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kValuesTypes[t.params.type]; + + // We expect to fail if low == high as it results in a DBZ + const expectedResult = t.params.value1 !== t.params.value2; + + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.value1), type.create(t.params.value2), type.create(0)], + t.params.stage, + /* returnType */concreteTypeOf(type, [Type.f32]) + ); +}); + +g.test('argument_types'). +desc( + ` +Validates that scalar and vector arguments are rejected by ${builtin}() if not float type or vecN +` +). +params((u) => u.combine('type', keysOf(kArgumentTypes))). +beforeAllSubcases((t) => { + if (scalarTypeOf(kArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kArgumentTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + /* expectedResult */isConvertibleToFloatType(elementTypeOf(type)), + [type.create(0), type.create(1), type.create(2)], + 'constant', + /* returnType */concreteTypeOf(type, [Type.f32]) + ); +}); + +const kTests = { + valid: { + src: `_ = ${builtin}(0.0, 42.0, 0.5);`, + pass: true + }, + alias: { + src: `_ = ${builtin}(f32_alias(0), f32_alias(42), f32_alias(0.5));`, + pass: true + }, + bool: { + src: `_ = ${builtin}(false, false, false);`, + pass: false + }, + i32: { + src: `_ = ${builtin}(1i, 2i, 1i);`, + pass: false + }, + u32: { + src: `_ = ${builtin}(1u, 2u, 1u);`, + pass: false + }, + f32: { + src: `_ = ${builtin}(1.0f, 2.0f, 1.0f);`, + pass: true + }, + f16: { + src: `_ = ${builtin}(1h, 2h, 1h);`, + pass: true + }, + mixed_aint_afloat: { + src: `_ = ${builtin}(1.0, 2, 1);`, + pass: true + }, + mixed_f32_afloat: { + src: `_ = ${builtin}(1.0f, 2.0, 1.0);`, + pass: true + }, + mixed_f16_afloat: { + src: `_ = ${builtin}(1.0h, 2.0, 1.0);`, + pass: true + }, + vec_bool: { + src: `_ = ${builtin}(vec2(false, true), vec2(false, true), vec2(false, true));`, + pass: false + }, + vec_i32: { + src: `_ = ${builtin}(vec2(1, 1), vec2(1, 1), vec2(1, 1));`, + pass: false + }, + vec_u32: { + src: `_ = ${builtin}(vec2(1, 1), vec2(1, 1), vec2(1, 1));`, + pass: false + }, + vec_f32: { + src: `_ = ${builtin}(vec2(0, 0), vec2(1, 1), vec2(1, 1));`, + pass: true + }, + matrix: { + src: `_ = ${builtin}(mat2x2(1, 1, 1, 1), mat2x2(1, 1, 1, 1), mat2x2(1, 1, 1, 1));`, + pass: false + }, + atomic: { + src: ` _ = ${builtin}(a, a, a);`, + pass: false + }, + array: { + src: `var a: array; + _ = ${builtin}(a, a, a);`, + pass: false + }, + array_runtime: { + src: `_ = ${builtin}(k.arry, k.arry, k.arry);`, + pass: false + }, + struct: { + src: `var a: A; + _ = ${builtin}(a, a, a);`, + pass: false + }, + enumerant: { + src: `_ = ${builtin}(read_write, read_write, read_write);`, + pass: false + }, + ptr: { + src: `var a = 1.0; + let p: ptr = &a; + _ = ${builtin}(p, p, p);`, + pass: false + }, + ptr_deref: { + src: `var a = 1.0; + let p: ptr = &a; + _ = ${builtin}(*p, *p, *p);`, + pass: true + }, + sampler: { + src: `_ = ${builtin}(s, s, s);`, + pass: false + }, + texture: { + src: `_ = ${builtin}(t, t, t);`, + pass: false + }, + no_args: { + src: `_ = ${builtin}();`, + pass: false + }, + too_few_args: { + src: `_ = ${builtin}(1.0, 2.0);`, + pass: false + }, + too_many_args: { + src: `_ = ${builtin}(1.0, 2.0, 3.0, 4.0);`, + pass: false + } +}; + +g.test('arguments'). +desc(`Test that ${builtin} is validated correctly when called with different arguments.`). +params((u) => u.combine('test', keysOf(kTests))). +beforeAllSubcases((t) => { + if (t.params.test.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const src = kTests[t.params.test].src; + const enables = t.params.test.includes('f16') ? 'enable f16;' : ''; + const code = ` + ${enables} + alias f32_alias = f32; + + @group(0) @binding(0) var s: sampler; + @group(0) @binding(1) var t: texture_2d; + + var a: atomic; + + struct A { + i: bool, + } + struct B { + arry: array, + } + @group(0) @binding(3) var k: B; + + @vertex + fn main() -> @builtin(position) vec4 { + ${src} + return vec4(.4, .2, .3, .1); + }`; + t.expectCompileResult(kTests[t.params.test].pass, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sqrt.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sqrt.spec.js index 4a2f254fef..acb432a539 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sqrt.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/sqrt.spec.js @@ -6,11 +6,10 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConcreteIntegerScalarsAndVectors, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { isRepresentable } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -18,7 +17,7 @@ import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kMinusTwoToTwo, + minusTwoToTwoRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -26,7 +25,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -40,17 +39,27 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('value', (u) => unique(kMinusTwoToTwo, fullRangeForType(kValuesTypes[u.type]))) +expand('value', (u) => +unique( + minusTwoToTwoRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type]) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; const expectedResult = - t.params.value >= 0 && isRepresentable(Math.sqrt(t.params.value), elementType(type)); + t.params.value >= 0 && + isRepresentable( + Math.sqrt(Number(t.params.value)), + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); validateConstOrOverrideBuiltinEval( t, builtin, @@ -60,7 +69,7 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kIntegerArgumentTypes = objectsToRecord([Type.f32, ...kConcreteIntegerScalarsAndVectors]); g.test('integer_argument'). desc( @@ -74,8 +83,41 @@ fn((t) => { validateConstOrOverrideBuiltinEval( t, builtin, - /* expectedResult */type === TypeF32, + /* expectedResult */type === Type.f32, [type.create(1)], 'constant' ); +}); + +const kArgCases = { + good: '(1.1)', + bad_no_parens: '', + // Bad number of args + bad_too_few: '()', + bad_too_many: '(1.0,2.0)', + // Bad value type for arg 0 + bad_0i32: '(1i)', + bad_0u32: '(1u)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/step.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/step.spec.js new file mode 100644 index 0000000000..6266a3628b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/step.spec.js @@ -0,0 +1,108 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'step';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidArgumentTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() error on invalid inputs. +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValidArgumentTypes)). +filter((u) => stageSupportsType(u.stage, kValidArgumentTypes[u.type])). +beginSubcases(). +expand('a', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)). +expand('b', (u) => fullRangeForType(kValidArgumentTypes[u.type], 5)) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValidArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const expectedResult = true; + + const type = kValidArgumentTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.a), type.create(t.params.b)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(1.2, 2.3)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_1arg: '(1.2)', + bad_3arg: '(1.2, 2.3, 4.5)', + // Bad value for arg 0 + bad_0bool: '(false, 2.3)', + bad_0array: '(array(1.1,2.2), 2.3)', + bad_0struct: '(modf(2.2), 2.3)', + bad_0uint: '(1u, 2.3)', + bad_0int: '(1i, 2.3)', + bad_0vec2i: '(vec2i(), 2.3)', + bad_0vec2u: '(vec2u(), 2.3)', + bad_0vec3i: '(vec3i(), 2.3)', + bad_0vec3u: '(vec3u(), 2.3)', + bad_0vec4i: '(vec4i(), 2.3)', + bad_0vec4u: '(vec4u(), 2.3)', + // Bad value for arg 1 + bad_1bool: '(1.2, false)', + bad_1array: '(1.2, array(1.1,2.2))', + bad_1struct: '(1.2, modf(2.2))', + bad_1uint: '(1.2, 1u)', + bad_1int: '(1.2, 1i)', + bad_1vec2i: '(1.2, vec2i())', + bad_1vec2u: '(1.2, vec2u())', + bad_1vec3i: '(1.2, vec3i())', + bad_1vec3u: '(1.2, vec3u())', + bad_1vec4i: '(1.2, vec4i())', + bad_1vec4u: '(1.2, vec4u())' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/tan.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/tan.spec.js index 91cee003ed..a7504ccb18 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/tan.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/tan.spec.js @@ -6,11 +6,9 @@ Validation tests for the ${builtin}() builtin. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; import { - TypeF16, - TypeF32, - elementType, - kAllFloatScalarsAndVectors, - kAllIntegerScalarsAndVectors } from + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from '../../../../../util/conversion.js'; import { fpTraitsFor } from '../../../../../util/floating_point.js'; import { ShaderValidationTest } from '../../../shader_validation_test.js'; @@ -18,7 +16,7 @@ import { ShaderValidationTest } from '../../../shader_validation_test.js'; import { fullRangeForType, kConstantAndOverrideStages, - kMinus3PiTo3Pi, + minusThreePiToThreePiRangeForType, stageSupportsType, unique, validateConstOrOverrideBuiltinEval } from @@ -26,7 +24,7 @@ import { export const g = makeTestGroup(ShaderValidationTest); -const kValuesTypes = objectsToRecord(kAllFloatScalarsAndVectors); +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); g.test('values'). desc( @@ -40,18 +38,26 @@ combine('stage', kConstantAndOverrideStages). combine('type', keysOf(kValuesTypes)). filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). beginSubcases(). -expand('value', (u) => unique(kMinus3PiTo3Pi, fullRangeForType(kValuesTypes[u.type]))) +expand('value', (u) => +unique( + minusThreePiToThreePiRangeForType(kValuesTypes[u.type]), + fullRangeForType(kValuesTypes[u.type]) +) +) ). beforeAllSubcases((t) => { - if (elementType(kValuesTypes[t.params.type]) === TypeF16) { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { t.selectDeviceOrSkipTestCase('shader-f16'); } }). fn((t) => { const type = kValuesTypes[t.params.type]; - const fp = fpTraitsFor(elementType(type)); + const fp = fpTraitsFor( + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); const smallestPositive = fp.constants().positive.min; - const v = fp.quantize(t.params.value); + const v = fp.quantize(Number(t.params.value)); const expectedResult = Math.abs(Math.cos(v)) > smallestPositive; validateConstOrOverrideBuiltinEval( t, @@ -62,22 +68,40 @@ fn((t) => { ); }); -const kIntegerArgumentTypes = objectsToRecord([TypeF32, ...kAllIntegerScalarsAndVectors]); +const kArgCases = { + good: '(1.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.2, 2.3)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())' +}; -g.test('integer_argument'). -desc( - ` -Validates that scalar and vector integer arguments are rejected by ${builtin}() -` -). -params((u) => u.combine('type', keysOf(kIntegerArgumentTypes))). +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). fn((t) => { - const type = kIntegerArgumentTypes[t.params.type]; - validateConstOrOverrideBuiltinEval( - t, - builtin, - /* expectedResult */type === TypeF32, - [type.create(0)], - 'constant' + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/tanh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/tanh.spec.js new file mode 100644 index 0000000000..653f92663e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/tanh.spec.js @@ -0,0 +1,98 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'tanh';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { isRepresentable } from '../../../../../util/floating_point.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValuesTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() rejects invalid values +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValuesTypes)). +filter((u) => stageSupportsType(u.stage, kValuesTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValuesTypes[u.type])) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValuesTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kValuesTypes[t.params.type]; + const expectedResult = isRepresentable( + Math.tanh(Number(t.params.value)), + // AbstractInt is converted to AbstractFloat before calling into the builtin + scalarTypeOf(type).kind === 'abstract-int' ? Type.abstractFloat : scalarTypeOf(type) + ); + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.value)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(1.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.2, 2.3)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureGather.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureGather.spec.js new file mode 100644 index 0000000000..6cd7061016 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureGather.spec.js @@ -0,0 +1,335 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureGather';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureGather component parameter must be correct type +* test textureGather component parameter must be between 0 and 3 inclusive +* test textureGather component parameter must be a const expression +* test textureGather coords parameter must be correct type +* test textureGather array_index parameter must be correct type +* test textureGather offset parameter must be correct type +* test textureGather offset parameter must be a const-expression +* test textureGather offset parameter must be between -8 and +7 inclusive +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + + + isUnsignedType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + + + + + + + + +const kValidTextureGatherParameterTypes = { + 'texture_2d': { + hasComponentArg: true, + coordsArgType: Type.vec2f, + offsetArgType: Type.vec2i + }, + 'texture_2d_array': { + hasComponentArg: true, + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + offsetArgType: Type.vec2i + }, + 'texture_cube': { hasComponentArg: true, coordsArgType: Type.vec3f }, + 'texture_cube_array': { + hasComponentArg: true, + coordsArgType: Type.vec3f, + hasArrayIndexArg: true + }, + texture_depth_2d: { coordsArgType: Type.vec2f, offsetArgType: Type.vec2i }, + texture_depth_2d_array: { + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + offsetArgType: Type.vec2i + }, + texture_depth_cube: { coordsArgType: Type.vec3f }, + texture_depth_cube_array: { coordsArgType: Type.vec3f, hasArrayIndexArg: true } +}; + +const kTextureTypes = keysOf(kValidTextureGatherParameterTypes); +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('component_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegather'). +desc( + ` +Validates that only incorrect components arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureGatherParameterTypes)) +// filter out types with no component argument +.filter((t) => !!kValidTextureGatherParameterTypes[t.textureType].hasComponentArg). +combine('componentType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1, 2, 3, 4]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.componentType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureGatherParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, componentType, offset, value } = t.params; + const componentArgType = kValuesTypes[componentType]; + const { offsetArgType, coordsArgType, hasArrayIndexArg } = + kValidTextureGatherParameterTypes[textureType]; + + const componentWGSL = componentArgType.create(value).wgsl(); + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureGather(${componentWGSL}, t, s, ${coordWGSL}${arrayWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + (isConvertible(componentArgType, Type.i32) || isConvertible(componentArgType, Type.u32)) && + value >= 0 && + value <= 3; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('component_argument,non_const'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegather'). +desc( + ` +Validates that only non-const components arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureGatherParameterTypes)) +// filter out types with no component argument +.filter((t) => !!kValidTextureGatherParameterTypes[t.textureType].hasComponentArg). +combine('varType', ['c', 'u', 'l']). +beginSubcases(). +expand('offset', (t) => +kValidTextureGatherParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, varType, offset } = t.params; + const componentArgType = Type.u32; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureGatherParameterTypes[textureType]; + + const componentWGSL = `${componentArgType}(${varType})`; + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@group(0) @binding(2) var u: ${componentArgType}; + +@fragment fn fs() -> @location(0) vec4f { + const c = 1; + let l = 1; + let v = textureGather(${componentWGSL}, t, s, ${coordWGSL}${arrayWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = varType === 'c'; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('coords_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegather'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureGatherParameterTypes)). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureGatherParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, coordType, offset, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { + hasComponentArg, + offsetArgType, + coordsArgType: coordsRequiredType, + hasArrayIndexArg + } = kValidTextureGatherParameterTypes[textureType]; + + const componentWGSL = hasComponentArg ? '0, ' : ''; + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureGather(${componentWGSL}t, s, ${coordWGSL}${arrayWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(coordArgType, coordsRequiredType); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegather'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no array_index +.filter((t) => !!kValidTextureGatherParameterTypes[t.textureType].hasArrayIndexArg). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureGatherParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, arrayIndexType, value, offset } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { hasComponentArg, coordsArgType, offsetArgType } = + kValidTextureGatherParameterTypes[textureType]; + + const componentWGSL = hasComponentArg ? '0, ' : ''; + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureGather(${componentWGSL}t, s, ${coordWGSL}, ${arrayWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegather'). +desc( + ` +Validates that only incorrect offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no offset +.filter((t) => !!kValidTextureGatherParameterTypes[t.textureType].offsetArgType). +combine('offsetType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.offsetType]) || t.value >= 0) +). +fn((t) => { + const { textureType, offsetType, value } = t.params; + const offsetArgType = kValuesTypes[offsetType]; + const args = [offsetArgType.create(value)]; + const { + hasComponentArg, + coordsArgType, + hasArrayIndexArg, + offsetArgType: offsetRequiredType + } = kValidTextureGatherParameterTypes[textureType]; + + const componentWGSL = hasComponentArg ? '0, ' : ''; + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = args.map((arg) => arg.wgsl()).join(', '); + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureGather(${componentWGSL}t, s, ${coordWGSL}${arrayWGSL}, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(offsetArgType, offsetRequiredType) && value >= -8 && value <= 7; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument,non_const'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegather'). +desc( + ` +Validates that only non-const offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('varType', ['c', 'u', 'l']) +// filter out types with no offset +.filter((t) => !!kValidTextureGatherParameterTypes[t.textureType].offsetArgType) +). +fn((t) => { + const { textureType, varType } = t.params; + const { hasComponentArg, coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureGatherParameterTypes[textureType]; + + const componentWGSL = hasComponentArg ? '0, ' : ''; + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = `${offsetArgType}(${varType})`; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@group(0) @binding(2) var u: ${offsetArgType}; +@fragment fn fs() -> @location(0) vec4f { + const c = 1; + let l = ${offsetArgType.create(0).wgsl()}; + let v = textureGather(${componentWGSL}t, s, ${coordWGSL}${arrayWGSL}, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = varType === 'c'; + t.expectCompileResult(expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureGatherCompare.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureGatherCompare.spec.js new file mode 100644 index 0000000000..4b41350ac7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureGatherCompare.spec.js @@ -0,0 +1,264 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureGatherCompare';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureGatherCompare coords parameter must be correct type +* test textureGatherCompare array_index parameter must be correct type +* test textureGatherCompare depth_ref parameter must be correct type +* test textureGatherCompare offset parameter must be correct type +* test textureGatherCompare offset parameter must be a const-expression +* test textureGatherCompare offset parameter must be between -8 and +7 inclusive +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + + + isUnsignedType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + + + + + + + +const kValidTextureGatherCompareParameterTypes = { + texture_depth_2d: { coordsArgType: Type.vec2f, offsetArgType: Type.vec2i }, + texture_depth_2d_array: { + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + offsetArgType: Type.vec2i + }, + texture_depth_cube: { coordsArgType: Type.vec3f }, + texture_depth_cube_array: { coordsArgType: Type.vec3f, hasArrayIndexArg: true } +}; + +const kTextureTypes = keysOf(kValidTextureGatherCompareParameterTypes); +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('coords_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegathercompare'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureGatherCompareParameterTypes)). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureGatherCompareParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, coordType, offset, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { + offsetArgType, + coordsArgType: coordsRequiredType, + hasArrayIndexArg + } = kValidTextureGatherCompareParameterTypes[textureType]; + + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureGatherCompare(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(coordArgType, coordsRequiredType); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegathercompare'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no array_index +.filter((t) => !!kValidTextureGatherCompareParameterTypes[t.textureType].hasArrayIndexArg). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureGatherCompareParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, arrayIndexType, value, offset } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { coordsArgType, offsetArgType } = kValidTextureGatherCompareParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureGatherCompare(t, s, ${coordWGSL}, ${arrayWGSL}, 0${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('depth_ref_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegathercompare'). +desc( + ` +Validates that only incorrect depth_ref arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureGatherCompareParameterTypes)). +combine('depthRefType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.depthRefType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureGatherCompareParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, depthRefType, offset, value } = t.params; + const depthRefArgType = kValuesTypes[depthRefType]; + const { offsetArgType, coordsArgType, hasArrayIndexArg } = + kValidTextureGatherCompareParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const depthRefWGSL = depthRefArgType.create(value).wgsl(); + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureGatherCompare(t, s, ${coordWGSL}${arrayWGSL}, ${depthRefWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(depthRefArgType, Type.f32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegathercompare'). +desc( + ` +Validates that only incorrect offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no offset +.filter((t) => !!kValidTextureGatherCompareParameterTypes[t.textureType].offsetArgType). +combine('offsetType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.offsetType]) || t.value >= 0) +). +fn((t) => { + const { textureType, offsetType, value } = t.params; + const offsetArgType = kValuesTypes[offsetType]; + const args = [offsetArgType.create(value)]; + const { + coordsArgType, + hasArrayIndexArg, + offsetArgType: offsetRequiredType + } = kValidTextureGatherCompareParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = args.map((arg) => arg.wgsl()).join(', '); + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureGatherCompare(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(offsetArgType, offsetRequiredType) && value >= -8 && value <= 7; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument,non_const'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturegathercompare'). +desc( + ` +Validates that only non-const offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('varType', ['c', 'u', 'l']) +// filter out types with no offset +.filter((t) => !!kValidTextureGatherCompareParameterTypes[t.textureType].offsetArgType) +). +fn((t) => { + const { textureType, varType } = t.params; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureGatherCompareParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = `${offsetArgType}(${varType})`; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@group(0) @binding(2) var u: ${offsetArgType}; +@fragment fn fs() -> @location(0) vec4f { + const c = 1; + let l = ${offsetArgType.create(0).wgsl()}; + let v = textureGatherCompare(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = varType === 'c'; + t.expectCompileResult(expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureLoad.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureLoad.spec.js new file mode 100644 index 0000000000..62038bb2f9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureLoad.spec.js @@ -0,0 +1,370 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureLoad';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureLoad coords parameter must be correct type +* test textureLoad array_index parameter must be correct type +* test textureLoad level parameter must be correct type +* test textureLoad sample_index parameter must be correct type +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { assert } from '../../../../../../common/util/util.js'; +import { kAllTextureFormats, kTextureFormatInfo } from '../../../../../format_info.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + + + isUnsignedType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + + + + + + + + + +const kCoords1DTypes = [Type.i32, Type.u32]; +const kCoords2DTypes = [Type.vec2i, Type.vec2u]; +const kCoords3DTypes = [Type.vec3i, Type.vec3u]; + +const kValidTextureLoadParameterTypesForNonStorageTextures = +{ + texture_1d: { usesMultipleTypes: true, coordsArgTypes: kCoords1DTypes, hasLevelArg: true }, + texture_2d: { usesMultipleTypes: true, coordsArgTypes: kCoords2DTypes, hasLevelArg: true }, + texture_2d_array: { + usesMultipleTypes: true, + coordsArgTypes: kCoords2DTypes, + hasArrayIndexArg: true, + hasLevelArg: true + }, + texture_3d: { usesMultipleTypes: true, coordsArgTypes: kCoords3DTypes, hasLevelArg: true }, + texture_multisampled_2d: { + usesMultipleTypes: true, + coordsArgTypes: kCoords2DTypes, + hasSampleIndexArg: true + }, + texture_depth_2d: { coordsArgTypes: kCoords2DTypes, hasLevelArg: true }, + texture_depth_2d_array: { + coordsArgTypes: kCoords2DTypes, + hasArrayIndexArg: true, + hasLevelArg: true + }, + texture_depth_multisampled_2d: { coordsArgTypes: kCoords2DTypes, hasSampleIndexArg: true }, + texture_external: { coordsArgTypes: kCoords2DTypes } +}; + +const kValidTextureLoadParameterTypesForStorageTextures = { + texture_storage_1d: { coordsArgTypes: [Type.i32, Type.u32] }, + texture_storage_2d: { coordsArgTypes: [Type.vec2i, Type.vec2u] }, + texture_storage_2d_array: { + coordsArgTypes: [Type.vec2i, Type.vec2u], + hasArrayIndexArg: true + }, + texture_storage_3d: { coordsArgTypes: [Type.vec3i, Type.vec3u] } +}; + +const kNonStorageTextureTypes = keysOf(kValidTextureLoadParameterTypesForNonStorageTextures); +const kStorageTextureTypes = keysOf(kValidTextureLoadParameterTypesForStorageTextures); +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +const kTexelType = { + f32: Type.vec4f, + i32: Type.vec4i, + u32: Type.vec4u +}; + +const kTexelTypes = keysOf(kTexelType); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('coords_argument,non_storage'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#textureload'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kNonStorageTextureTypes). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +expand('texelType', (t) => +kValidTextureLoadParameterTypesForNonStorageTextures[t.textureType].usesMultipleTypes ? +kTexelTypes : +[''] +). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0) +). +fn((t) => { + const { textureType, coordType, texelType, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { coordsArgTypes, hasArrayIndexArg, hasLevelArg, hasSampleIndexArg } = + kValidTextureLoadParameterTypesForNonStorageTextures[textureType]; + + const texelTypeWGSL = texelType ? `<${texelType}>` : ''; + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const levelWGSL = hasLevelArg ? ', 0' : ''; + const sampleIndexWGSL = hasSampleIndexArg ? ', 0' : ''; + + const code = ` +@group(0) @binding(0) var t: ${textureType}${texelTypeWGSL}; +@fragment fn fs() -> @location(0) vec4f { + _ = textureLoad(t, ${coordWGSL}${arrayWGSL}${levelWGSL}${sampleIndexWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(coordArgType, coordsArgTypes[0]) || + isConvertible(coordArgType, coordsArgTypes[1]); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('coords_argument,storage'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#textureload'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kStorageTextureTypes). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('format', kAllTextureFormats) +// filter to only storage texture formats. +.filter((t) => !!kTextureFormatInfo[t.format].color?.storage). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0) +). +beforeAllSubcases((t) => +t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures') +). +fn((t) => { + const { textureType, coordType, format, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { coordsArgTypes, hasArrayIndexArg } = + kValidTextureLoadParameterTypesForStorageTextures[textureType]; + + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + + const code = ` +@group(0) @binding(0) var t: ${textureType}<${format}, read>; +@fragment fn fs() -> @location(0) vec4f { + _ = textureLoad(t, ${coordWGSL}${arrayWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(coordArgType, coordsArgTypes[0]) || + isConvertible(coordArgType, coordsArgTypes[1]); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument,non_storage'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#textureload'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kNonStorageTextureTypes) +// filter out types with no array_index +.filter( + (t) => !!kValidTextureLoadParameterTypesForNonStorageTextures[t.textureType].hasArrayIndexArg +). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +expand('texelType', (t) => +kValidTextureLoadParameterTypesForNonStorageTextures[t.textureType].usesMultipleTypes ? +kTexelTypes : +[''] +). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0) +). +fn((t) => { + const { textureType, arrayIndexType, texelType, value } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { coordsArgTypes, hasLevelArg } = + kValidTextureLoadParameterTypesForNonStorageTextures[textureType]; + + const texelTypeWGSL = texelType ? `<${texelType}>` : ''; + const coordWGSL = coordsArgTypes[0].create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const levelWGSL = hasLevelArg ? ', 0' : ''; + + const code = ` +@group(0) @binding(0) var t: ${textureType}${texelTypeWGSL}; +@fragment fn fs() -> @location(0) vec4f { + _ = textureLoad(t, ${coordWGSL}, ${arrayWGSL}${levelWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument,storage'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#textureload'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kStorageTextureTypes) +// filter out types with no array_index +.filter( + (t) => !!kValidTextureLoadParameterTypesForStorageTextures[t.textureType].hasArrayIndexArg +). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +combine('format', kAllTextureFormats) +// filter to only storage texture formats. +.filter((t) => !!kTextureFormatInfo[t.format].color?.storage). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0) +). +beforeAllSubcases((t) => +t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures') +). +fn((t) => { + const { textureType, arrayIndexType, format, value } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { coordsArgTypes, hasLevelArg } = + kValidTextureLoadParameterTypesForStorageTextures[textureType]; + + const coordWGSL = coordsArgTypes[0].create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const levelWGSL = hasLevelArg ? ', 0' : ''; + + const code = ` +@group(0) @binding(0) var t: ${textureType}<${format}, read>; +@fragment fn fs() -> @location(0) vec4f { + _ = textureLoad(t, ${coordWGSL}, ${arrayWGSL}${levelWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('level_argument,non_storage'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#textureload'). +desc( + ` +Validates that only incorrect level arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kNonStorageTextureTypes) +// filter out types with no level +.filter( + (t) => !!kValidTextureLoadParameterTypesForNonStorageTextures[t.textureType].hasLevelArg +). +combine('levelType', keysOf(kValuesTypes)). +beginSubcases(). +expand('texelType', (t) => +kValidTextureLoadParameterTypesForNonStorageTextures[t.textureType].usesMultipleTypes ? +kTexelTypes : +[''] +). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.levelType]) || t.value >= 0) +). +fn((t) => { + const { textureType, levelType, texelType, value } = t.params; + const levelArgType = kValuesTypes[levelType]; + const { coordsArgTypes, hasArrayIndexArg } = + kValidTextureLoadParameterTypesForNonStorageTextures[textureType]; + + const texelTypeWGSL = texelType ? `<${texelType}>` : ''; + const coordWGSL = coordsArgTypes[0].create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const levelWGSL = levelArgType.create(value).wgsl(); + + const code = ` +@group(0) @binding(0) var t: ${textureType}${texelTypeWGSL}; +@fragment fn fs() -> @location(0) vec4f { + _ = textureLoad(t, ${coordWGSL}${arrayWGSL}, ${levelWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(levelArgType, Type.i32) || isConvertible(levelArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('sample_index_argument,non_storage'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#textureload'). +desc( + ` +Validates that only incorrect sample_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kNonStorageTextureTypes) +// filter out types with no sample_index +.filter( + (t) => !!kValidTextureLoadParameterTypesForNonStorageTextures[t.textureType].hasSampleIndexArg +). +combine('sampleIndexType', keysOf(kValuesTypes)). +beginSubcases(). +expand('texelType', (t) => +kValidTextureLoadParameterTypesForNonStorageTextures[t.textureType].usesMultipleTypes ? +kTexelTypes : +[''] +). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.sampleIndexType]) || t.value >= 0) +). +fn((t) => { + const { textureType, sampleIndexType, texelType, value } = t.params; + const sampleIndexArgType = kValuesTypes[sampleIndexType]; + const { coordsArgTypes, hasArrayIndexArg, hasLevelArg } = + kValidTextureLoadParameterTypesForNonStorageTextures[textureType]; + assert(!hasLevelArg); + + const texelTypeWGSL = texelType ? `<${texelType}>` : ''; + const coordWGSL = coordsArgTypes[0].create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const sampleIndexWGSL = sampleIndexArgType.create(value).wgsl(); + + const code = ` +@group(0) @binding(0) var t: ${textureType}${texelTypeWGSL}; +@fragment fn fs() -> @location(0) vec4f { + _ = textureLoad(t, ${coordWGSL}${arrayWGSL}, ${sampleIndexWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(sampleIndexArgType, Type.i32) || isConvertible(sampleIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSample.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSample.spec.js new file mode 100644 index 0000000000..322e3a7a70 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSample.spec.js @@ -0,0 +1,267 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureSample';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureSample coords parameter must be correct type +* test textureSample array_index parameter must be correct type +* test textureSample coords parameter must be correct type +* test textureSample offset parameter must be correct type +* test textureSample offset parameter must be a const-expression +* test textureSample offset parameter must be between -8 and +7 inclusive +* test textureSample not usable in a compute or vertex shader + +note: uniformity validation is covered in src/webgpu/shader/validation/uniformity/uniformity.spec.ts +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + + + isUnsignedType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { kEntryPointsToValidateFragmentOnlyBuiltins } from './shader_stage_utils.js'; + + + + + + + +const kValidTextureSampleParameterTypes = { + 'texture_1d': { coordsArgType: Type.f32 }, + 'texture_2d': { coordsArgType: Type.vec2f, offsetArgType: Type.vec2i }, + 'texture_2d_array': { + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + offsetArgType: Type.vec2i + }, + 'texture_3d': { coordsArgType: Type.vec3f, offsetArgType: Type.vec3i }, + 'texture_cube': { coordsArgType: Type.vec3f }, + 'texture_cube_array': { coordsArgType: Type.vec3f, hasArrayIndexArg: true }, + texture_depth_2d: { coordsArgType: Type.vec2f, offsetArgType: Type.vec2i }, + texture_depth_2d_array: { + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + offsetArgType: Type.vec2i + }, + texture_depth_cube: { coordsArgType: Type.vec3f }, + texture_depth_cube_array: { coordsArgType: Type.vec3f, hasArrayIndexArg: true } +}; + +const kTextureTypes = keysOf(kValidTextureSampleParameterTypes); +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('coords_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureSampleParameterTypes)). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, coordType, offset, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { + offsetArgType, + coordsArgType: coordsRequiredType, + hasArrayIndexArg + } = kValidTextureSampleParameterTypes[textureType]; + + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSample(t, s, ${coordWGSL}${arrayWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(coordArgType, coordsRequiredType); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no array_index +.filter((t) => !!kValidTextureSampleParameterTypes[t.textureType].hasArrayIndexArg). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, arrayIndexType, value, offset } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { coordsArgType, offsetArgType } = kValidTextureSampleParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSample(t, s, ${coordWGSL}, ${arrayWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample'). +desc( + ` +Validates that only incorrect offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleParameterTypes[t.textureType].offsetArgType). +combine('offsetType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.offsetType]) || t.value >= 0) +). +fn((t) => { + const { textureType, offsetType, value } = t.params; + const offsetArgType = kValuesTypes[offsetType]; + const args = [offsetArgType.create(value)]; + const { + coordsArgType, + hasArrayIndexArg, + offsetArgType: offsetRequiredType + } = kValidTextureSampleParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = args.map((arg) => arg.wgsl()).join(', '); + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSample(t, s, ${coordWGSL}${arrayWGSL}, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(offsetArgType, offsetRequiredType) && value >= -8 && value <= 7; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument,non_const'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample'). +desc( + ` +Validates that only non-const offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('varType', ['c', 'u', 'l']) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleParameterTypes[t.textureType].offsetArgType) +). +fn((t) => { + const { textureType, varType } = t.params; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = `${offsetArgType}(${varType})`; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@group(0) @binding(2) var u: ${offsetArgType}; +@fragment fn fs() -> @location(0) vec4f { + const c = 1; + let l = ${offsetArgType.create(0).wgsl()}; + let v = textureSample(t, s, ${coordWGSL}${arrayWGSL}, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = varType === 'c'; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('only_in_fragment'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample'). +desc( + ` +Validates that ${builtin} must not be used in a compute or vertex shader. +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('entryPoint', keysOf(kEntryPointsToValidateFragmentOnlyBuiltins)). +expand('offset', (t) => +kValidTextureSampleParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, entryPoint, offset } = t.params; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const config = kEntryPointsToValidateFragmentOnlyBuiltins[entryPoint]; + const code = ` +${config.code} +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; + +fn foo() { + _ = textureSample(t, s, ${coordWGSL}${arrayWGSL}${offsetWGSL}); +}`; + t.expectCompileResult(config.expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge.spec.js new file mode 100644 index 0000000000..0e9df6aeb4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge.spec.js @@ -0,0 +1,54 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureSampleBaseClampToEdge';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureSampleBaseClampToEdge coords parameter must be correct type +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + isUnsignedType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kTextureSampleBaseClampToEdgeTextureTypes = ['texture_2d', 'texture_external']; +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('coords_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplebaseclamptoedge'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureSampleBaseClampToEdgeTextureTypes). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0) +). +fn((t) => { + const { textureType, coordType, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const coordWGSL = coordArgType.create(value).wgsl(); + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleBaseClampToEdge(t, s, ${coordWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(coordArgType, Type.vec2f); + t.expectCompileResult(expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleBias.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleBias.spec.js new file mode 100644 index 0000000000..712e405b93 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleBias.spec.js @@ -0,0 +1,309 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureSampleBias';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureSampleBias coords parameter must be correct type +* test textureSampleBias array_index parameter must be correct type +* test textureSampleBias bias parameter must be correct type +* test textureSampleBias bias parameter must be between -16.0 and 15.99 inclusive if it's a constant +* test textureSampleBias offset parameter must be correct type +* test textureSampleBias offset parameter must be a const-expression +* test textureSampleBias offset parameter must be between -8 and +7 inclusive + +note: uniformity validation is covered in src/webgpu/shader/validation/uniformity/uniformity.spec.ts +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + + + isUnsignedType, + scalarTypeOf, + isFloatType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { kEntryPointsToValidateFragmentOnlyBuiltins } from './shader_stage_utils.js'; + + + + + + + +const kValidTextureSampleBiasParameterTypes = { + 'texture_2d': { coordsArgType: Type.vec2f, offsetArgType: Type.vec2i }, + 'texture_2d_array': { + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + offsetArgType: Type.vec2i + }, + 'texture_3d': { coordsArgType: Type.vec3f, offsetArgType: Type.vec3i }, + 'texture_cube': { coordsArgType: Type.vec3f }, + 'texture_cube_array': { coordsArgType: Type.vec3f, hasArrayIndexArg: true } +}; + +const kTextureTypes = keysOf(kValidTextureSampleBiasParameterTypes); +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('coords_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplebias'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureSampleBiasParameterTypes)). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleBiasParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, coordType, offset, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { + offsetArgType, + coordsArgType: coordsRequiredType, + hasArrayIndexArg + } = kValidTextureSampleBiasParameterTypes[textureType]; + + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleBias(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(coordArgType, coordsRequiredType); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplebias'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no array_index +.filter((t) => !!kValidTextureSampleBiasParameterTypes[t.textureType].hasArrayIndexArg). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleBiasParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, arrayIndexType, value, offset } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { coordsArgType, offsetArgType } = kValidTextureSampleBiasParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleBias(t, s, ${coordWGSL}, ${arrayWGSL}, 0${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('bias_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplebias'). +desc( + ` +Validates that only incorrect bias arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleBiasParameterTypes[t.textureType].offsetArgType). +combine('biasType', keysOf(kValuesTypes)). +beginSubcases() +// The spec mentions limits of > -16 and < 15.99 so pass some values around there +// No error is mentioned for out of range values so make sure no error is generated. +.combine('value', [-17, -16, -8, 0, 7, 15.99, 16]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.biasType]) || t.value >= 0) +// filter out non-integer values passed to integer types. +.filter((t) => Number.isInteger(t.value) || isFloatType(scalarTypeOf(kValuesTypes[t.biasType]))). +expand('offset', (t) => +kValidTextureSampleBiasParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, biasType, value, offset } = t.params; + const biasArgType = kValuesTypes[biasType]; + const args = [biasArgType.create(value)]; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleBiasParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const biasWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleBias(t, s, ${coordWGSL}${arrayWGSL}, ${biasWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(biasArgType, Type.f32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplebias'). +desc( + ` +Validates that only incorrect offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleBiasParameterTypes[t.textureType].offsetArgType). +combine('offsetType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.offsetType]) || t.value >= 0) +). +fn((t) => { + const { textureType, offsetType, value } = t.params; + const offsetArgType = kValuesTypes[offsetType]; + const args = [offsetArgType.create(value)]; + const { + coordsArgType, + hasArrayIndexArg, + offsetArgType: offsetRequiredType + } = kValidTextureSampleBiasParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = args.map((arg) => arg.wgsl()).join(', '); + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleBias(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(offsetArgType, offsetRequiredType) && value >= -8 && value <= 7; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument,non_const'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplebias'). +desc( + ` +Validates that only non-const offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('varType', ['c', 'u', 'l']) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleBiasParameterTypes[t.textureType].offsetArgType) +). +fn((t) => { + const { textureType, varType } = t.params; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleBiasParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = `${offsetArgType}(${varType})`; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@group(0) @binding(2) var u: ${offsetArgType}; +@fragment fn fs() -> @location(0) vec4f { + const c = 1; + let l = ${offsetArgType.create(0).wgsl()}; + let v = textureSampleBias(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = varType === 'c'; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('only_in_fragment'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample'). +desc( + ` +Validates that ${builtin} must not be used in a compute or vertex shader. +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('entryPoint', keysOf(kEntryPointsToValidateFragmentOnlyBuiltins)). +expand('offset', (t) => +kValidTextureSampleBiasParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, entryPoint, offset } = t.params; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleBiasParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const config = kEntryPointsToValidateFragmentOnlyBuiltins[entryPoint]; + const code = ` +${config.code} +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; + +fn foo() { + _ = textureSampleBias(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL}); +}`; + t.expectCompileResult(config.expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleCompare.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleCompare.spec.js new file mode 100644 index 0000000000..a1d06bb341 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleCompare.spec.js @@ -0,0 +1,308 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureSampleCompare';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureSampleCompare coords parameter must be correct type +* test textureSampleCompare array_index parameter must be correct type +* test textureSampleCompare depth_ref parameter must be correct type +* test textureSampleCompare offset parameter must be correct type +* test textureSampleCompare offset parameter must be a const-expression +* test textureSampleCompare offset parameter must be between -8 and +7 inclusive +* test textureSample not usable in a compute or vertex shader + +note: uniformity validation is covered in src/webgpu/shader/validation/uniformity/uniformity.spec.ts +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + + + isUnsignedType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { kEntryPointsToValidateFragmentOnlyBuiltins } from './shader_stage_utils.js'; + + + + + + + +const kValidTextureSampleCompareParameterTypes = { + texture_depth_2d: { coordsArgType: Type.vec2f, offsetArgType: Type.vec2i }, + texture_depth_2d_array: { + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + offsetArgType: Type.vec2i + }, + texture_depth_cube: { coordsArgType: Type.vec3f }, + texture_depth_cube_array: { coordsArgType: Type.vec3f, hasArrayIndexArg: true } +}; + +const kTextureTypes = keysOf(kValidTextureSampleCompareParameterTypes); +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('coords_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecompare'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureSampleCompareParameterTypes)). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleCompareParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, coordType, offset, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { + offsetArgType, + coordsArgType: coordsRequiredType, + hasArrayIndexArg + } = kValidTextureSampleCompareParameterTypes[textureType]; + + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + _ = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(coordArgType, coordsRequiredType); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecompare'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no array_index +.filter((t) => !!kValidTextureSampleCompareParameterTypes[t.textureType].hasArrayIndexArg). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleCompareParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, arrayIndexType, value, offset } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { coordsArgType, offsetArgType } = kValidTextureSampleCompareParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + _ = textureSampleCompare(t, s, ${coordWGSL}, ${arrayWGSL}, 0${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('depth_ref_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecompare'). +desc( + ` +Validates that only incorrect depth_ref arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('depthRefType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.depthRefType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleCompareParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, depthRefType, value, offset } = t.params; + const depthRefArgType = kValuesTypes[depthRefType]; + const args = [depthRefArgType.create(value)]; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleCompareParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const depthRefWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + _ = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, ${depthRefWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(depthRefArgType, Type.f32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecompare'). +desc( + ` +Validates that only incorrect offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleCompareParameterTypes[t.textureType].offsetArgType). +combine('offsetType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.offsetType]) || t.value >= 0) +). +fn((t) => { + const { textureType, offsetType, value } = t.params; + const offsetArgType = kValuesTypes[offsetType]; + const args = [offsetArgType.create(value)]; + const { + coordsArgType, + hasArrayIndexArg, + offsetArgType: offsetRequiredType + } = kValidTextureSampleCompareParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = args.map((arg) => arg.wgsl()).join(', '); + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + _ = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(offsetArgType, offsetRequiredType) && value >= -8 && value <= 7; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument,non_const'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecompare'). +desc( + ` +Validates that only non-const offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('varType', ['c', 'u', 'l']) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleCompareParameterTypes[t.textureType].offsetArgType) +). +fn((t) => { + const { textureType, varType } = t.params; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleCompareParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = `${offsetArgType}(${varType})`; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@group(0) @binding(2) var u: ${offsetArgType}; +@fragment fn fs() -> @location(0) vec4f { + const c = 1; + let l = ${offsetArgType?.create(0).wgsl()}; + _ = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = varType === 'c'; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('only_in_fragment'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample'). +desc( + ` +Validates that ${builtin} must not be used in a compute or vertex shader. +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('entryPoint', keysOf(kEntryPointsToValidateFragmentOnlyBuiltins)). +expand('offset', (t) => +kValidTextureSampleCompareParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, entryPoint, offset } = t.params; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleCompareParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const config = kEntryPointsToValidateFragmentOnlyBuiltins[entryPoint]; + const code = ` +${config.code} +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; + +fn foo() { + _ = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL}); +}`; + t.expectCompileResult(config.expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleCompareLevel.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleCompareLevel.spec.js new file mode 100644 index 0000000000..baa741204b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleCompareLevel.spec.js @@ -0,0 +1,268 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureSampleCompareLevel';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureSampleCompareLevel coords parameter must be correct type +* test textureSampleCompareLevel array_index parameter must be correct type +* test textureSampleCompareLevel depth_ref parameter must be correct type +* test textureSampleCompareLevel offset parameter must be correct type +* test textureSampleCompareLevel offset parameter must be a const-expression +* test textureSampleCompareLevel offset parameter must be between -8 and +7 inclusive +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + + + isUnsignedType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + + + + + + + +const kValidTextureSampleCompareLevelParameterTypes = + +{ + texture_depth_2d: { coordsArgType: Type.vec2f, offsetArgType: Type.vec2i }, + texture_depth_2d_array: { + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + offsetArgType: Type.vec2i + }, + texture_depth_cube: { coordsArgType: Type.vec3f }, + texture_depth_cube_array: { coordsArgType: Type.vec3f, hasArrayIndexArg: true } +}; + +const kTextureTypes = keysOf(kValidTextureSampleCompareLevelParameterTypes); +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('coords_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecomparelevel'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureSampleCompareLevelParameterTypes)). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleCompareLevelParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, coordType, offset, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { + offsetArgType, + coordsArgType: coordsRequiredType, + hasArrayIndexArg + } = kValidTextureSampleCompareLevelParameterTypes[textureType]; + + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleCompareLevel(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(coordArgType, coordsRequiredType); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecomparelevel'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no array_index +.filter((t) => !!kValidTextureSampleCompareLevelParameterTypes[t.textureType].hasArrayIndexArg). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleCompareLevelParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, arrayIndexType, value, offset } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { coordsArgType, offsetArgType } = + kValidTextureSampleCompareLevelParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleCompareLevel(t, s, ${coordWGSL}, ${arrayWGSL}, 0${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('depth_ref_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecomparelevel'). +desc( + ` +Validates that only incorrect depth_ref arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('depthRefType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.depthRefType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleCompareLevelParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, depthRefType, value, offset } = t.params; + const depthRefArgType = kValuesTypes[depthRefType]; + const args = [depthRefArgType.create(value)]; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleCompareLevelParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const depthRefWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleCompareLevel(t, s, ${coordWGSL}${arrayWGSL}, ${depthRefWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(depthRefArgType, Type.f32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecomparelevel'). +desc( + ` +Validates that only incorrect offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleCompareLevelParameterTypes[t.textureType].offsetArgType). +combine('offsetType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.offsetType]) || t.value >= 0) +). +fn((t) => { + const { textureType, offsetType, value } = t.params; + const offsetArgType = kValuesTypes[offsetType]; + const args = [offsetArgType.create(value)]; + const { + coordsArgType, + hasArrayIndexArg, + offsetArgType: offsetRequiredType + } = kValidTextureSampleCompareLevelParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = args.map((arg) => arg.wgsl()).join(', '); + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleCompareLevel(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(offsetArgType, offsetRequiredType) && value >= -8 && value <= 7; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument,non_const'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecomparelevel'). +desc( + ` +Validates that only non-const offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('varType', ['c', 'u', 'l']) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleCompareLevelParameterTypes[t.textureType].offsetArgType) +). +fn((t) => { + const { textureType, varType } = t.params; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleCompareLevelParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = `${offsetArgType}(${varType})`; + + const code = ` +@group(0) @binding(0) var s: sampler_comparison; +@group(0) @binding(1) var t: ${textureType}; +@group(0) @binding(2) var u: ${offsetArgType}; +@fragment fn fs() -> @location(0) vec4f { + const c = 1; + let l = ${offsetArgType?.create(0).wgsl()}; + let v = textureSampleCompareLevel(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = varType === 'c'; + t.expectCompileResult(expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleGrad.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleGrad.spec.js new file mode 100644 index 0000000000..c7b3843f9b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleGrad.spec.js @@ -0,0 +1,317 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureSampleGrad';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureSampleGrad coords parameter must be correct type +* test textureSampleGrad array_index parameter must be correct type +* test textureSampleGrad ddX parameter must be correct type +* test textureSampleGrad ddY parameter must be correct type +* test textureSampleGrad coords parameter must be correct type +* test textureSampleGrad offset parameter must be correct type +* test textureSampleGrad offset parameter must be a const-expression +* test textureSampleGrad offset parameter must be between -8 and +7 inclusive +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + + + isUnsignedType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +// Note: ddX and ddy parameter types match coords so we'll use coordsArgType for ddX and ddY. + + + + + + +const kValidTextureSampleGradParameterTypes = { + 'texture_2d': { + coordsArgType: Type.vec2f, + offsetArgType: Type.vec2i + }, + 'texture_2d_array': { + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + offsetArgType: Type.vec2i + }, + 'texture_3d': { coordsArgType: Type.vec3f, offsetArgType: Type.vec3i }, + 'texture_cube': { coordsArgType: Type.vec3f }, + 'texture_cube_array': { coordsArgType: Type.vec3f, hasArrayIndexArg: true } +}; + +const kTextureTypes = keysOf(kValidTextureSampleGradParameterTypes); +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('coords_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplegrad'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureSampleGradParameterTypes)). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleGradParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, coordType, offset, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { + offsetArgType, + coordsArgType: coordsRequiredType, + hasArrayIndexArg + } = kValidTextureSampleGradParameterTypes[textureType]; + + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const ddWGSL = coordsRequiredType.create(0).wgsl(); + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleGrad(t, s, ${coordWGSL}${arrayWGSL}, ${ddWGSL}, ${ddWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(coordArgType, coordsRequiredType); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplegrad'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no array_index +.filter((t) => !!kValidTextureSampleGradParameterTypes[t.textureType].hasArrayIndexArg). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleGradParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, arrayIndexType, value, offset } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { coordsArgType, offsetArgType } = kValidTextureSampleGradParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const ddWGSL = coordsArgType.create(0).wgsl(); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleGrad(t, s, ${coordWGSL}, ${arrayWGSL}, ${ddWGSL}, ${ddWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('ddX_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplegrad'). +desc( + ` +Validates that only incorrect ddX arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('ddxType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.ddxType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleGradParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, ddxType, value, offset } = t.params; + const ddxArgType = kValuesTypes[ddxType]; + const args = [ddxArgType.create(value)]; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleGradParameterTypes[textureType]; + + const ddxRequiredType = coordsArgType; + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const ddXWGSL = args.map((arg) => arg.wgsl()).join(', '); + const ddYWGSL = coordsArgType.create(0).wgsl(); + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleGrad(t, s, ${coordWGSL}${arrayWGSL}, ${ddXWGSL}, ${ddYWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(ddxArgType, ddxRequiredType); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('ddY_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplegrad'). +desc( + ` +Validates that only incorrect ddY arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('ddyType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.ddyType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleGradParameterTypes[t.textureType].offsetArgType ? [false, true] : [false] +) +). +fn((t) => { + const { textureType, ddyType, value, offset } = t.params; + const ddyArgType = kValuesTypes[ddyType]; + const args = [ddyArgType.create(value)]; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleGradParameterTypes[textureType]; + + const ddyRequiredType = coordsArgType; + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const ddXWGSL = coordsArgType.create(0).wgsl(); + const ddYWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleGrad(t, s, ${coordWGSL}${arrayWGSL}, ${ddXWGSL}, ${ddYWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(ddyArgType, ddyRequiredType); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplegrad'). +desc( + ` +Validates that only incorrect offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleGradParameterTypes[t.textureType].offsetArgType). +combine('offsetType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.offsetType]) || t.value >= 0) +). +fn((t) => { + const { textureType, offsetType, value } = t.params; + const offsetArgType = kValuesTypes[offsetType]; + const args = [offsetArgType.create(value)]; + const { + coordsArgType, + hasArrayIndexArg, + offsetArgType: offsetRequiredType + } = kValidTextureSampleGradParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const ddWGSL = coordsArgType.create(0).wgsl(); + const offsetWGSL = args.map((arg) => arg.wgsl()).join(', '); + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleGrad(t, s, ${coordWGSL}${arrayWGSL}, ${ddWGSL}, ${ddWGSL}, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(offsetArgType, offsetRequiredType) && value >= -8 && value <= 7; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument,non_const'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplegrad'). +desc( + ` +Validates that only non-const offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('varType', ['c', 'u', 'l']) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleGradParameterTypes[t.textureType].offsetArgType) +). +fn((t) => { + const { textureType, varType } = t.params; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleGradParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const ddWGSL = coordsArgType.create(0).wgsl(); + const offsetWGSL = `${offsetArgType}(${varType})`; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@group(0) @binding(2) var u: ${offsetArgType}; +@fragment fn fs() -> @location(0) vec4f { + const c = 1; + let l = ${offsetArgType.create(0).wgsl()}; + let v = textureSampleGrad(t, s, ${coordWGSL}${arrayWGSL}, ${ddWGSL}, ${ddWGSL}, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = varType === 'c'; + t.expectCompileResult(expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleLevel.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleLevel.spec.js new file mode 100644 index 0000000000..cf18cf2f7b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureSampleLevel.spec.js @@ -0,0 +1,282 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureSampleLevel';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureSampleLevel coords parameter must be correct type +* test textureSampleLevel array_index parameter must be correct type +* test textureSampleLevel level parameter must be correct type +* test textureSampleLevel offset parameter must be correct type +* test textureSampleLevel offset parameter must be a const-expression +* test textureSampleLevel offset parameter must be between -8 and +7 inclusive +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + + + isUnsignedType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + + + + + + + + +const kValidTextureSampleLevelParameterTypes = { + 'texture_2d': { coordsArgType: Type.vec2f, levelIsF32: true, offsetArgType: Type.vec2i }, + 'texture_2d_array': { + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + levelIsF32: true, + offsetArgType: Type.vec2i + }, + 'texture_3d': { coordsArgType: Type.vec3f, levelIsF32: true, offsetArgType: Type.vec3i }, + 'texture_cube': { coordsArgType: Type.vec3f, levelIsF32: true }, + 'texture_cube_array': { + coordsArgType: Type.vec3f, + hasArrayIndexArg: true, + levelIsF32: true + }, + texture_depth_2d: { coordsArgType: Type.vec2f, offsetArgType: Type.vec2i }, + texture_depth_2d_array: { + coordsArgType: Type.vec2f, + hasArrayIndexArg: true, + offsetArgType: Type.vec2i + }, + texture_depth_cube: { coordsArgType: Type.vec3f }, + texture_depth_cube_array: { coordsArgType: Type.vec3f, hasArrayIndexArg: true } +}; + +const kTextureTypes = keysOf(kValidTextureSampleLevelParameterTypes); +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('coords_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplelevel'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureSampleLevelParameterTypes)). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleLevelParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, coordType, offset, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { + offsetArgType, + coordsArgType: coordsRequiredType, + hasArrayIndexArg + } = kValidTextureSampleLevelParameterTypes[textureType]; + + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleLevel(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = isConvertible(coordArgType, coordsRequiredType); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplelevel'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no array_index +.filter((t) => !!kValidTextureSampleLevelParameterTypes[t.textureType].hasArrayIndexArg). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleLevelParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, arrayIndexType, value, offset } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { coordsArgType, offsetArgType } = kValidTextureSampleLevelParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleLevel(t, s, ${coordWGSL}, ${arrayWGSL}, 0${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('level_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplelevel'). +desc( + ` +Validates that only incorrect level arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('levelType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.levelType]) || t.value >= 0). +expand('offset', (t) => +kValidTextureSampleLevelParameterTypes[t.textureType].offsetArgType ? +[false, true] : +[false] +) +). +fn((t) => { + const { textureType, levelType, value, offset } = t.params; + const levelArgType = kValuesTypes[levelType]; + const args = [levelArgType.create(value)]; + const { coordsArgType, hasArrayIndexArg, offsetArgType, levelIsF32 } = + kValidTextureSampleLevelParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const levelWGSL = args.map((arg) => arg.wgsl()).join(', '); + const offsetWGSL = offset ? `, ${offsetArgType.create(0).wgsl()}` : ''; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleLevel(t, s, ${coordWGSL}${arrayWGSL}, ${levelWGSL}${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = levelIsF32 ? + isConvertible(levelArgType, Type.f32) : + isConvertible(levelArgType, Type.i32) || isConvertible(levelArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplelevel'). +desc( + ` +Validates that only incorrect offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleLevelParameterTypes[t.textureType].offsetArgType). +combine('offsetType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.offsetType]) || t.value >= 0) +). +fn((t) => { + const { textureType, offsetType, value } = t.params; + const offsetArgType = kValuesTypes[offsetType]; + const args = [offsetArgType.create(value)]; + const { + coordsArgType, + hasArrayIndexArg, + offsetArgType: offsetRequiredType + } = kValidTextureSampleLevelParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = args.map((arg) => arg.wgsl()).join(', '); + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@fragment fn fs() -> @location(0) vec4f { + let v = textureSampleLevel(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(offsetArgType, offsetRequiredType) && value >= -8 && value <= 7; + t.expectCompileResult(expectSuccess, code); +}); + +g.test('offset_argument,non_const'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplelevel'). +desc( + ` +Validates that only non-const offset arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('varType', ['c', 'u', 'l']) +// filter out types with no offset +.filter((t) => !!kValidTextureSampleLevelParameterTypes[t.textureType].offsetArgType) +). +fn((t) => { + const { textureType, varType } = t.params; + const { coordsArgType, hasArrayIndexArg, offsetArgType } = + kValidTextureSampleLevelParameterTypes[textureType]; + + const coordWGSL = coordsArgType.create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const offsetWGSL = `${offsetArgType}(${varType})`; + + const code = ` +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var t: ${textureType}; +@group(0) @binding(2) var u: ${offsetArgType}; +@fragment fn fs() -> @location(0) vec4f { + const c = 1; + let l = ${offsetArgType.create(0).wgsl()}; + let v = textureSampleLevel(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL}); + return vec4f(0); +} +`; + const expectSuccess = varType === 'c'; + t.expectCompileResult(expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureStore.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureStore.spec.js new file mode 100644 index 0000000000..fdc18f5ee6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/textureStore.spec.js @@ -0,0 +1,168 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'textureStore';export const description = ` +Validation tests for the ${builtin}() builtin. + +* test textureStore coords parameter must be correct type +* test textureStore array_index parameter must be correct type +* test textureStore value parameter must be correct type +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { kAllTextureFormats, kTextureFormatInfo } from '../../../../../format_info.js'; +import { + Type, + kAllScalarsAndVectors, + isConvertible, + + + isUnsignedType } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kTextureColorTypeToType = { + sint: Type.vec4i, + uint: Type.vec4u, + float: Type.vec4f, + 'unfilterable-float': Type.vec4f +}; + + + + + + +const kValidTextureStoreParameterTypes = { + texture_storage_1d: { coordsArgTypes: [Type.i32, Type.u32] }, + texture_storage_2d: { coordsArgTypes: [Type.vec2i, Type.vec2u] }, + texture_storage_2d_array: { + coordsArgTypes: [Type.vec2i, Type.vec2u], + hasArrayIndexArg: true + }, + texture_storage_3d: { coordsArgTypes: [Type.vec3i, Type.vec3u] } +}; + +const kTextureTypes = keysOf(kValidTextureStoreParameterTypes); +const kValuesTypes = objectsToRecord(kAllScalarsAndVectors); + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('coords_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturestore'). +desc( + ` +Validates that only incorrect coords arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', keysOf(kValidTextureStoreParameterTypes)). +combine('coordType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-1, 0, 1]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0) +). +fn((t) => { + const { textureType, coordType, value } = t.params; + const coordArgType = kValuesTypes[coordType]; + const { coordsArgTypes, hasArrayIndexArg } = kValidTextureStoreParameterTypes[textureType]; + + const coordWGSL = coordArgType.create(value).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const format = 'rgba8unorm'; + const valueWGSL = 'vec4f(0)'; + + const code = ` +@group(0) @binding(0) var t: ${textureType}<${format},write>; +@fragment fn fs() -> @location(0) vec4f { + textureStore(t, ${coordWGSL}${arrayWGSL}, ${valueWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(coordArgType, coordsArgTypes[0]) || + isConvertible(coordArgType, coordsArgTypes[1]); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('array_index_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturestore'). +desc( + ` +Validates that only incorrect array_index arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes) +// filter out types with no array_index +.filter((t) => !!kValidTextureStoreParameterTypes[t.textureType].hasArrayIndexArg). +combine('arrayIndexType', keysOf(kValuesTypes)). +beginSubcases(). +combine('value', [-9, -8, 0, 7, 8]) +// filter out unsigned types with negative values +.filter((t) => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0) +). +fn((t) => { + const { textureType, arrayIndexType, value } = t.params; + const arrayIndexArgType = kValuesTypes[arrayIndexType]; + const args = [arrayIndexArgType.create(value)]; + const { coordsArgTypes } = kValidTextureStoreParameterTypes[textureType]; + + const coordWGSL = coordsArgTypes[0].create(0).wgsl(); + const arrayWGSL = args.map((arg) => arg.wgsl()).join(', '); + const format = 'rgba8unorm'; + const valueWGSL = 'vec4f(0)'; + + const code = ` +@group(0) @binding(0) var t: ${textureType}<${format}, write>; +@fragment fn fs() -> @location(0) vec4f { + textureStore(t, ${coordWGSL}, ${arrayWGSL}, ${valueWGSL}); + return vec4f(0); +} +`; + const expectSuccess = + isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32); + t.expectCompileResult(expectSuccess, code); +}); + +g.test('value_argument'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturestore'). +desc( + ` +Validates that only incorrect value arguments are rejected by ${builtin} +` +). +params((u) => +u. +combine('textureType', kTextureTypes). +combine('valueType', keysOf(kValuesTypes)). +beginSubcases(). +combine('format', kAllTextureFormats) +// filter to only storage texture formats. +.filter((t) => !!kTextureFormatInfo[t.format].color?.storage). +combine('value', [0, 1, 2]) +). +fn((t) => { + const { textureType, valueType, format, value } = t.params; + const valueArgType = kValuesTypes[valueType]; + const args = [valueArgType.create(value)]; + const { coordsArgTypes, hasArrayIndexArg } = kValidTextureStoreParameterTypes[textureType]; + + const coordWGSL = coordsArgTypes[0].create(0).wgsl(); + const arrayWGSL = hasArrayIndexArg ? ', 0' : ''; + const valueWGSL = args.map((arg) => arg.wgsl()).join(', '); + + const code = ` +@group(0) @binding(0) var t: ${textureType}<${format}, write>; +@fragment fn fs() -> @location(0) vec4f { + textureStore(t, ${coordWGSL}${arrayWGSL}, ${valueWGSL}); + return vec4f(0); +} +`; + const colorType = kTextureFormatInfo[format].color?.type; + const requiredValueType = kTextureColorTypeToType[colorType]; + const expectSuccess = isConvertible(valueArgType, requiredValueType); + t.expectCompileResult(expectSuccess, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/trunc.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/trunc.spec.js new file mode 100644 index 0000000000..a4ce758a7e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/trunc.spec.js @@ -0,0 +1,94 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const builtin = 'trunc';export const description = ` +Validation tests for the ${builtin}() builtin. +`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js'; +import { + Type, + kConvertableToFloatScalarsAndVectors, + scalarTypeOf } from +'../../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +import { + fullRangeForType, + kConstantAndOverrideStages, + stageSupportsType, + validateConstOrOverrideBuiltinEval } from +'./const_override_validation.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidArgumentTypes = objectsToRecord(kConvertableToFloatScalarsAndVectors); + +g.test('values'). +desc( + ` +Validates that constant evaluation and override evaluation of ${builtin}() error on invalid inputs. +` +). +params((u) => +u. +combine('stage', kConstantAndOverrideStages). +combine('type', keysOf(kValidArgumentTypes)). +filter((u) => stageSupportsType(u.stage, kValidArgumentTypes[u.type])). +beginSubcases(). +expand('value', (u) => fullRangeForType(kValidArgumentTypes[u.type])) +). +beforeAllSubcases((t) => { + if (scalarTypeOf(kValidArgumentTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const expectedResult = true; + + const type = kValidArgumentTypes[t.params.type]; + validateConstOrOverrideBuiltinEval( + t, + builtin, + expectedResult, + [type.create(t.params.value)], + t.params.stage + ); +}); + +const kArgCases = { + good: '(1.2)', + bad_no_parens: '', + // Bad number of args + bad_0args: '()', + bad_2arg: '(1.2, 2.3)', + // Bad value for arg 0 + bad_0bool: '(false)', + bad_0array: '(array(1.1,2.2))', + bad_0struct: '(modf(2.2))', + bad_0uint: '(1u)', + bad_0int: '(1i)', + bad_0vec2i: '(vec2i())', + bad_0vec2u: '(vec2u())', + bad_0vec3i: '(vec3i())', + bad_0vec3u: '(vec3u())', + bad_0vec4i: '(vec4i())', + bad_0vec4u: '(vec4u())' +}; + +g.test('args'). +desc(`Test compilation failure of ${builtin} with variously shaped and typed arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.expectCompileResult( + t.params.arg === 'good', + `const c = ${builtin}${kArgCases[t.params.arg]};` + ); +}); + +g.test('must_use'). +desc(`Result of ${builtin} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${builtin}${kArgCases['good']}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16float.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16float.spec.js new file mode 100644 index 0000000000..e72ce1d047 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16float.spec.js @@ -0,0 +1,62 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const kFn = 'unpack2x16float';export const description = `Validate ${kFn}`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kArgCases = { + good_u32: '(1u)', + good_aint: '(1)', + bad_0args: '()', + bad_2args: '(1u,2u)', + bad_i32: '(1i)', + bad_f32: '(1f)', + bad_f16: '(1h)', + bad_bool: '(false)', + bad_vec2u: '(vec2u())', + bad_vec3u: '(vec3u())', + bad_vec4u: '(vec4u())', + bad_array: '(array(1))', + bad_struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good_u32']; +const kReturnType = 'vec2f'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +beforeAllSubcases((t) => { + if (t.params.arg === 'bad_f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + let code = ''; + if (t.params.arg === 'bad_f16') { + code += 'enable f16;\n'; + } + code += `const c = ${kFn}${kArgCases[t.params.arg]};`; + + t.expectCompileResult(t.params.arg.startsWith('good'), code); +}); + +g.test('return'). +desc(`Test ${kFn} return value type ${kReturnType}`). +params((u) => u.combine('type', ['vec2u', 'vec2i', 'vec2f', 'vec2h', 'vec4f', 'vec3f', 'f32'])). +fn((t) => { + t.expectCompileResult( + t.params.type === kReturnType, + `const c: ${t.params.type} = ${kFn}${kGoodArgs};` + ); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16snorm.spec.js new file mode 100644 index 0000000000..270dde01e3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16snorm.spec.js @@ -0,0 +1,62 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const kFn = 'unpack2x16snorm';export const description = `Validate ${kFn}`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kArgCases = { + good_u32: '(1u)', + good_aint: '(1)', + bad_0args: '()', + bad_2args: '(1u,2u)', + bad_i32: '(1i)', + bad_f32: '(1f)', + bad_f16: '(1h)', + bad_bool: '(false)', + bad_vec2u: '(vec2u())', + bad_vec3u: '(vec3u())', + bad_vec4u: '(vec4u())', + bad_array: '(array(1))', + bad_struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good_u32']; +const kReturnType = 'vec2f'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +beforeAllSubcases((t) => { + if (t.params.arg === 'bad_f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + let code = ''; + if (t.params.arg === 'bad_f16') { + code += 'enable f16;\n'; + } + code += `const c = ${kFn}${kArgCases[t.params.arg]};`; + + t.expectCompileResult(t.params.arg.startsWith('good'), code); +}); + +g.test('return'). +desc(`Test ${kFn} return value type ${kReturnType}`). +params((u) => u.combine('type', ['vec2u', 'vec2i', 'vec2f', 'vec2h', 'vec4f', 'vec3f', 'f32'])). +fn((t) => { + t.expectCompileResult( + t.params.type === kReturnType, + `const c: ${t.params.type} = ${kFn}${kGoodArgs};` + ); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16unorm.spec.js new file mode 100644 index 0000000000..1f9d08f914 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack2x16unorm.spec.js @@ -0,0 +1,62 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const kFn = 'unpack2x16unorm';export const description = `Validate ${kFn}`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kArgCases = { + good_u32: '(1u)', + good_aint: '(1)', + bad_0args: '()', + bad_2args: '(1u,2u)', + bad_i32: '(1i)', + bad_f32: '(1f)', + bad_f16: '(1h)', + bad_bool: '(false)', + bad_vec2u: '(vec2u())', + bad_vec3u: '(vec3u())', + bad_vec4u: '(vec4u())', + bad_array: '(array(1))', + bad_struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good_u32']; +const kReturnType = 'vec2f'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +beforeAllSubcases((t) => { + if (t.params.arg === 'bad_f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + let code = ''; + if (t.params.arg === 'bad_f16') { + code += 'enable f16;\n'; + } + code += `const c = ${kFn}${kArgCases[t.params.arg]};`; + + t.expectCompileResult(t.params.arg.startsWith('good'), code); +}); + +g.test('return'). +desc(`Test ${kFn} return value type ${kReturnType}`). +params((u) => u.combine('type', ['vec2u', 'vec2i', 'vec2f', 'vec2h', 'vec4f', 'vec3f', 'f32'])). +fn((t) => { + t.expectCompileResult( + t.params.type === kReturnType, + `const c: ${t.params.type} = ${kFn}${kGoodArgs};` + ); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4x8snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4x8snorm.spec.js new file mode 100644 index 0000000000..c2e9ccb216 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4x8snorm.spec.js @@ -0,0 +1,62 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const kFn = 'unpack4x8snorm';export const description = `Validate ${kFn}`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kArgCases = { + good_u32: '(1u)', + good_aint: '(1)', + bad_0args: '()', + bad_2args: '(1u,2u)', + bad_i32: '(1i)', + bad_f32: '(1f)', + bad_f16: '(1h)', + bad_bool: '(false)', + bad_vec2u: '(vec2u())', + bad_vec3u: '(vec3u())', + bad_vec4u: '(vec4u())', + bad_array: '(array(1))', + bad_struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good_u32']; +const kReturnType = 'vec4f'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +beforeAllSubcases((t) => { + if (t.params.arg === 'bad_f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + let code = ''; + if (t.params.arg === 'bad_f16') { + code += 'enable f16;\n'; + } + code += `const c = ${kFn}${kArgCases[t.params.arg]};`; + + t.expectCompileResult(t.params.arg.startsWith('good'), code); +}); + +g.test('return'). +desc(`Test ${kFn} return value type ${kReturnType}`). +params((u) => u.combine('type', ['vec4u', 'vec4i', 'vec4f', 'vec4h', 'vec3f', 'vec2f', 'f32'])). +fn((t) => { + t.expectCompileResult( + t.params.type === kReturnType, + `const c: ${t.params.type} = ${kFn}${kGoodArgs};` + ); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4x8unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4x8unorm.spec.js new file mode 100644 index 0000000000..fa8773bfa7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4x8unorm.spec.js @@ -0,0 +1,62 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/const kFn = 'unpack4x8unorm';export const description = `Validate ${kFn}`; +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kArgCases = { + good_u32: '(1u)', + good_aint: '(1)', + bad_0args: '()', + bad_2args: '(1u,2u)', + bad_i32: '(1i)', + bad_f32: '(1f)', + bad_f16: '(1h)', + bad_bool: '(false)', + bad_vec2u: '(vec2u())', + bad_vec3u: '(vec3u())', + bad_vec4u: '(vec4u())', + bad_array: '(array(1))', + bad_struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good_u32']; +const kReturnType = 'vec4f'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +beforeAllSubcases((t) => { + if (t.params.arg === 'bad_f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + let code = ''; + if (t.params.arg === 'bad_f16') { + code += 'enable f16;\n'; + } + code += `const c = ${kFn}${kArgCases[t.params.arg]};`; + + t.expectCompileResult(t.params.arg.startsWith('good'), code); +}); + +g.test('return'). +desc(`Test ${kFn} return value type ${kReturnType}`). +params((u) => u.combine('type', ['vec4u', 'vec4i', 'vec4f', 'vec4h', 'vec3f', 'vec2f', 'f32'])). +fn((t) => { + t.expectCompileResult( + t.params.type === kReturnType, + `const c: ${t.params.type} = ${kFn}${kGoodArgs};` + ); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4xI8.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4xI8.spec.js new file mode 100644 index 0000000000..5d7b58cdea --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4xI8.spec.js @@ -0,0 +1,61 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validate unpack4xI8`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kFeature = 'packed_4x8_integer_dot_product'; +const kFn = 'unpack4xI8'; +const kArgCases = { + good: '(1u)', + bad_0args: '()', + bad_2args: '(1u,2u)', + bad_0i32: '(1i)', + bad_0f32: '(1f)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0vec3u: '(vec3u())', + bad_0vec4u: '(vec4u())', + bad_0array: '(array(1))', + bad_0struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('unsupported'). +desc(`Test absence of ${kFn} when ${kFeature} is not supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(false, code); +}); + +g.test('supported'). +desc(`Test presence of ${kFn} when ${kFeature} is supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(true, code); +}); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + t.expectCompileResult(t.params.arg === 'good', `const c = ${kFn}${kArgCases[t.params.arg]};`); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4xU8.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4xU8.spec.js new file mode 100644 index 0000000000..c7c50cc660 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/unpack4xU8.spec.js @@ -0,0 +1,61 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validate unpack4xU8`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +const kFeature = 'packed_4x8_integer_dot_product'; +const kFn = 'unpack4xU8'; +const kArgCases = { + good: '(1u)', + bad_0args: '()', + bad_2args: '(1u,2u)', + bad_0i32: '(1i)', + bad_0f32: '(1f)', + bad_0bool: '(false)', + bad_0vec2u: '(vec2u())', + bad_0vec3u: '(vec3u())', + bad_0vec4u: '(vec4u())', + bad_0array: '(array(1))', + bad_0struct: '(modf(1.1))' +}; +const kGoodArgs = kArgCases['good']; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('unsupported'). +desc(`Test absence of ${kFn} when ${kFeature} is not supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(false, code); +}); + +g.test('supported'). +desc(`Test presence of ${kFn} when ${kFeature} is supported.`). +params((u) => u.combine('requires', [false, true])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const preamble = t.params.requires ? `requires ${kFeature}; ` : ''; + const code = `${preamble}const c = ${kFn}${kGoodArgs};`; + t.expectCompileResult(true, code); +}); + +g.test('args'). +desc(`Test compilation failure of ${kFn} with various numbers of and types of arguments`). +params((u) => u.combine('arg', keysOf(kArgCases))). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + t.expectCompileResult(t.params.arg === 'good', `const c = ${kFn}${kArgCases[t.params.arg]};`); +}); + +g.test('must_use'). +desc(`Result of ${kFn} must be used`). +params((u) => u.combine('use', [true, false])). +fn((t) => { + t.skipIfLanguageFeatureNotSupported(kFeature); + const use_it = t.params.use ? '_ = ' : ''; + t.expectCompileResult(t.params.use, `fn f() { ${use_it}${kFn}${kGoodArgs}; }`); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/workgroupUniformLoad.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/workgroupUniformLoad.spec.js new file mode 100644 index 0000000000..a061fd1603 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/call/builtin/workgroupUniformLoad.spec.js @@ -0,0 +1,122 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for the workgroupUniformLoad() builtin. +`;import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kEntryPoints = { + none: { supportsBarrier: true, code: `` }, + compute: { + supportsBarrier: true, + code: `@compute @workgroup_size(1) +fn main() { + foo(); +}` + }, + vertex: { + supportsBarrier: false, + code: `@vertex +fn main() -> @builtin(position) vec4f { + foo(); + return vec4f(); +}` + }, + fragment: { + supportsBarrier: false, + code: `@fragment +fn main() { + foo(); +}` + }, + compute_and_fragment: { + supportsBarrier: false, + code: `@compute @workgroup_size(1) +fn main1() { + foo(); +} + +@fragment +fn main2() { + foo(); +} +` + }, + fragment_without_call: { + supportsBarrier: true, + code: `@fragment +fn main() { +} +` + } +}; + +g.test('only_in_compute'). +specURL('https://www.w3.org/TR/WGSL/#sync-builtin-functions'). +desc( + ` +Synchronization functions must only be used in the compute shader stage. +` +). +params((u) => +u. +combine('entry_point', keysOf(kEntryPoints)). +combine('call', ['bar()', 'workgroupUniformLoad(&wgvar)']) +). +fn((t) => { + const config = kEntryPoints[t.params.entry_point]; + const code = ` +${config.code} + +var wgvar : u32; + +fn bar() -> u32 { + return 0; +} + +fn foo() { + _ = ${t.params.call}; +}`; + t.expectCompileResult(t.params.call === 'bar()' || config.supportsBarrier, code); +}); + +// A list of types that contains atomics, with a single control case. +const kAtomicTypes = [ +'bool', // control case +'atomic', +'atomic', +'array, 4>', +'AtomicStruct']; + + +g.test('no_atomics'). +desc( + ` +The argument passed to workgroupUniformLoad cannot contain any atomic types. + +NOTE: Various other valid types are tested via execution tests, so we only check for invalid types here. +` +). +params((u) => +u.combine('type', kAtomicTypes).combine('call', ['bar()', 'workgroupUniformLoad(&wgvar)']) +). +fn((t) => { + const code = ` +struct AtomicStruct { + a : atomic +} + +var wgvar : ${t.params.type}; + +fn bar() -> bool { + return true; +} + +fn foo() { + _ = ${t.params.call}; +}`; + t.expectCompileResult(t.params.type === 'bool' || t.params.call === 'bar()', code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/overload_resolution.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/overload_resolution.spec.js new file mode 100644 index 0000000000..9520d2b251 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/overload_resolution.spec.js @@ -0,0 +1,268 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validation tests for implicit conversions and overload resolution`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../common/util/data_tables.js'; +import { + kAllNumericScalarsAndVectors, + isConvertible, + VectorType } from +'../../../util/conversion.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + + + + + + + +const kImplicitConversionCases = { + absint_to_bool: { + expr: `any(1)`, + valid: false + }, + absint_to_u32: { + expr: `1 == 1u`, + valid: true + }, + absint_to_i32: { + expr: `1 == 1i`, + valid: true + }, + absint_to_f32: { + expr: `1 == 1f`, + valid: true + }, + absint_to_f16: { + expr: `1 == 1h`, + valid: true, + f16: true + }, + absfloat_to_bool: { + expr: `any(1.0)`, + valid: false + }, + absfloat_to_u32: { + expr: `1.0 == 1u`, + valid: false + }, + absfloat_to_i32: { + expr: `1.0 == 1i`, + valid: false + }, + absfloat_to_f32: { + expr: `1.0 == 1f`, + valid: true + }, + absfloat_to_f16: { + expr: `1.0 == 1h`, + valid: true, + f16: true + }, + vector_absint_to_bool: { + expr: `any(vec2(1))`, + valid: false + }, + vector_absint_to_u32: { + expr: `all(vec2(1) == vec2u(1u))`, + valid: true + }, + vector_absint_to_i32: { + expr: `all(vec3(1) == vec3i(1i))`, + valid: true + }, + vector_absint_to_f32: { + expr: `all(vec4(1) == vec4f(1f))`, + valid: true + }, + vector_absint_to_f16: { + expr: `all(vec2(1) == vec2h(1h))`, + valid: true, + f16: true + }, + vector_absfloat_to_bool: { + expr: `any(vec2(1.0))`, + valid: false + }, + vector_absfloat_to_u32: { + expr: `all(vec2(1.0) == vec2u(1u))`, + valid: false + }, + vector_absfloat_to_i32: { + expr: `all(vec3(1.0) == vec2i(1i))`, + valid: false + }, + vector_absfloat_to_f32: { + expr: `all(vec4(1.0) == vec4f(1f))`, + valid: true + }, + vector_absfloat_to_f16: { + expr: `all(vec2(1.0) == vec2h(1h))`, + valid: true, + f16: true + }, + vector_swizzle_integer: { + expr: `vec2(1).x == 1i`, + valid: true + }, + vector_swizzle_float: { + expr: `vec2(1).y == 1f`, + valid: true + }, + vector_default_ctor_integer: { + expr: `all(vec3().xy == vec2i())`, + valid: true + }, + vector_default_ctor_abstract: { + expr: `all(vec3().xy == vec2())`, + valid: true + }, + vector_swizzle_abstract: { + expr: `vec4(1f).x == 1`, + valid: true + }, + vector_abstract_to_integer: { + expr: `all(vec4(1) == vec4i(1))`, + valid: true + }, + vector_wrong_result_i32: { + expr: `vec2(1,2f).x == 1i`, + valid: false + }, + vector_wrong_result_f32: { + expr: `vec2(1,2i).y == 2f`, + valid: false + }, + vector_wrong_result_splat: { + expr: `vec2(1.0).x == 1i`, + valid: false + }, + array_absint_to_bool: { + expr: `any(array(1)[0])`, + valid: false + }, + array_absint_to_u32: { + expr: `array(1)[0] == array(1u)[0]`, + valid: true + }, + array_absint_to_i32: { + expr: `array(1)[0] == array(1i)[0]`, + valid: true + }, + array_absint_to_f32: { + expr: `array(1)[0] == array(1f)[0]`, + valid: true + }, + array_absint_to_f16: { + expr: `array(1)[0] == array(1h)[0]`, + valid: true, + f16: true + }, + array_absfloat_to_bool: { + expr: `any(array(1.0)[0])`, + valid: false + }, + array_absfloat_to_u32: { + expr: `array(1.0)[0] == array(1u)[0]`, + valid: false + }, + array_absfloat_to_i32: { + expr: `array(1.0)[0] == array(1i)[0]`, + valid: false + }, + array_absfloat_to_f32: { + expr: `array(1.0)[0] == array(1f)[0]`, + valid: true + }, + array_absfloat_to_f16: { + expr: `array(1.0)[0] == array(1h)[0]`, + valid: true, + f16: true + }, + mat2x2_index_absint: { + expr: `all(mat2x2(1,2,3,4)[0] == vec2(1,2))`, + valid: true + }, + mat2x2_index_absfloat: { + expr: `all(mat2x2(1,2,3,4)[1] == vec2(3.0,4.0))`, + valid: true + }, + mat2x2_index_float: { + expr: `all(mat2x2(0,0,0,0)[1] == vec2f())`, + valid: true + }, + mat2x2_wrong_result: { + expr: `all(mat2x2(0f,0,0,0)[0] == vec2h())`, + valid: false, + f16: true + } +}; + +g.test('implicit_conversions'). +desc('Test implicit conversions'). +params((u) => u.combine('case', keysOf(kImplicitConversionCases))). +beforeAllSubcases((t) => { + if (kImplicitConversionCases[t.params.case].f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const testcase = kImplicitConversionCases[t.params.case]; + const code = `${testcase.f16 ? 'enable f16;' : ''} + const_assert ${testcase.expr};`; + t.expectCompileResult(testcase.valid, code); +}); + +const kTypes = objectsToRecord(kAllNumericScalarsAndVectors); +const kTypeKeys = keysOf(kTypes); + +g.test('overload_resolution'). +desc('Test overload resolution'). +params((u) => +u. +combine('arg1', kTypeKeys). +combine('arg2', kTypeKeys). +beginSubcases(). +combine('op', ['min', 'max']). +filter((t) => { + if (t.arg1 === t.arg2) { + return false; + } + const t1 = kTypes[t.arg1]; + const t2 = kTypes[t.arg2]; + const t1IsVector = t1 instanceof VectorType; + const t2IsVector = t2 instanceof VectorType; + if (t1IsVector !== t2IsVector) { + return false; + } + if (t1IsVector && t2IsVector && t1.size !== t2.size) { + return false; + } + return true; +}) +). +beforeAllSubcases((t) => { + const t1 = kTypes[t.params.arg1]; + const t2 = kTypes[t.params.arg2]; + if (t1.requiresF16() || t2.requiresF16()) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const t1 = kTypes[t.params.arg1]; + const t2 = kTypes[t.params.arg2]; + const resTy = isConvertible(t1, t2) ? t2 : t1; + const enable = `${t1.requiresF16() || t2.requiresF16() ? 'enable f16;' : ''}`; + const min = 50; + const max = 100; + const res = t.params.op === 'min' ? min : max; + const v1 = t1.create(min).wgsl(); + const v2 = t2.create(max).wgsl(); + const resV = resTy.create(res).wgsl(); + const expr = `${t.params.op}(${v1}, ${v2}) == ${resV}`; + const assertExpr = t1 instanceof VectorType ? `all(${expr})` : expr; + const code = `${enable} + const_assert ${assertExpr};`; + t.expectCompileResult(isConvertible(t1, t2) || isConvertible(t2, t1), code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/precedence.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/precedence.spec.js new file mode 100644 index 0000000000..36903dded4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/precedence.spec.js @@ -0,0 +1,188 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for operator precedence. +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// Bit set for the binary operator groups. +const kMultiplicative = 1 << 0; +const kAdditive = 1 << 1; +const kShift = 1 << 2; +const kRelational = 1 << 3; +const kBinaryAnd = 1 << 4; +const kBinaryXor = 1 << 5; +const kBinaryOr = 1 << 6; +const kLogical = 1 << 7; + +// Set of other operators that each operator can precede without any parentheses. +const kCanPrecedeWithoutParens = {}; +kCanPrecedeWithoutParens[kMultiplicative] = kMultiplicative | kAdditive | kRelational; +kCanPrecedeWithoutParens[kAdditive] = kMultiplicative | kAdditive | kRelational; +kCanPrecedeWithoutParens[kShift] = kRelational | kLogical; +kCanPrecedeWithoutParens[kRelational] = kMultiplicative | kAdditive | kShift | kLogical; +kCanPrecedeWithoutParens[kBinaryAnd] = kBinaryAnd; +kCanPrecedeWithoutParens[kBinaryXor] = kBinaryXor; +kCanPrecedeWithoutParens[kBinaryOr] = kBinaryOr; +kCanPrecedeWithoutParens[kLogical] = kRelational; + +// The list of binary operators. + + + + +const kBinaryOperators = { + mul: { op: '*', group: kMultiplicative }, + div: { op: '/', group: kMultiplicative }, + mod: { op: '%', group: kMultiplicative }, + + add: { op: '+', group: kAdditive }, + sub: { op: '-', group: kAdditive }, + + shl: { op: '<<', group: kShift }, + shr: { op: '>>', group: kShift }, + + lt: { op: '<', group: kRelational }, + gt: { op: '>', group: kRelational }, + le: { op: '<=', group: kRelational }, + ge: { op: '>=', group: kRelational }, + eq: { op: '==', group: kRelational }, + ne: { op: '!=', group: kRelational }, + + bin_and: { op: '&', group: kBinaryAnd }, + bin_xor: { op: '^', group: kBinaryXor }, + bin_or: { op: '|', group: kBinaryOr }, + + log_and: { op: '&&', group: kLogical }, + log_or: { op: '||', group: kLogical } +}; + +g.test('binary_requires_parentheses'). +desc( + ` + Validates that certain binary operators require parentheses to bind correctly. + ` +). +params((u) => +u. +combine('op1', keysOf(kBinaryOperators)). +combine('op2', keysOf(kBinaryOperators)). +filter((p) => { + // Skip expressions that would parse as template lists. + if (p.op1 === 'lt' && ['gt', 'ge', 'shr'].includes(p.op2)) { + return false; + } + // Only combine logical operators with relational operators. + if (kBinaryOperators[p.op1].group === kLogical) { + return kBinaryOperators[p.op2].group === kRelational; + } + if (kBinaryOperators[p.op2].group === kLogical) { + return kBinaryOperators[p.op1].group === kRelational; + } + return true; +}) +). +fn((t) => { + const op1 = kBinaryOperators[t.params.op1]; + const op2 = kBinaryOperators[t.params.op2]; + const code = ` +var a : ${op1.group === kLogical ? 'bool' : 'u32'}; +var b : u32; +var c : ${op2.group === kLogical ? 'bool' : 'u32'}; +fn foo() { + let foo = a ${op1.op} b ${op2.op} c; +} +`; + + const valid = (kCanPrecedeWithoutParens[op1.group] & op2.group) !== 0; + t.expectCompileResult(valid, code); +}); + +g.test('mixed_logical_requires_parentheses'). +desc( + ` + Validates that mixed logical operators require parentheses to bind correctly. + ` +). +params((u) => +u. +combine('op1', keysOf(kBinaryOperators)). +combine('op2', keysOf(kBinaryOperators)). +combine('parens', ['none', 'left', 'right']). +filter((p) => { + const group1 = kBinaryOperators[p.op1].group; + const group2 = kBinaryOperators[p.op2].group; + return group1 === kLogical && group2 === kLogical; +}) +). +fn((t) => { + const op1 = kBinaryOperators[t.params.op1]; + const op2 = kBinaryOperators[t.params.op2]; + let expr = `a ${op1.op} b ${op2.op} c;`; + if (t.params.parens === 'left') { + expr = `(a ${op1.op} b) ${op2.op} c;`; + } else if (t.params.parens === 'right') { + expr = `a ${op1.op} (b ${op2.op} c);`; + } + const code = ` +var a : bool; +var b : bool; +var c : bool; +fn foo() { + let bar = ${expr}; +} +`; + const valid = t.params.parens !== 'none' || t.params.op1 === t.params.op2; + t.expectCompileResult(valid, code); +}); + +// The list of miscellaneous other test cases. + + + + +const kExpressions = { + neg_member: { expr: '- str . a', result: true }, + comp_member: { expr: '~ str . a', result: true }, + addr_member: { expr: '& str . a', result: true }, + log_and_member: { expr: 'false && str . b', result: true }, + log_or_member: { expr: 'false || str . b', result: true }, + and_addr: { expr: ' v & &str .a', result: false }, + and_addr_paren: { expr: 'v & (&str).a', result: true }, + deref_member: { expr: ' * ptr_str . a', result: false }, + deref_member_paren: { expr: '(* ptr_str) . a', result: true }, + deref_idx: { expr: ' * ptr_vec [0]', result: false }, + deref_idx_paren: { expr: '(* ptr_vec) [1]', result: true } +}; + +g.test('other'). +desc( + ` + Test that other operator precedence rules are correctly implemented. + ` +). +params((u) => u.combine('expr', keysOf(kExpressions))). +fn((t) => { + const expr = kExpressions[t.params.expr]; + const wgsl = ` + struct S { + a: i32, + b: bool, + } + + fn main() { + var v = 42; + var vec = vec4(); + var str = S(42, false); + let ptr_vec = &vec; + let ptr_str = &str; + + let foo = ${expr.expr}; + } + `; + + t.expectCompileResult(expr.result, wgsl); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/address_of_and_indirection.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/address_of_and_indirection.spec.js new file mode 100644 index 0000000000..b783220b30 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/address_of_and_indirection.spec.js @@ -0,0 +1,243 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for unary address-of and indirection (dereference) +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kAddressSpaces = ['function', 'private', 'workgroup', 'uniform', 'storage']; +const kAccessModes = ['read', 'read_write']; +const kStorageTypes = ['bool', 'u32', 'i32', 'f32', 'f16']; +const kCompositeTypes = ['array', 'struct', 'vec', 'mat']; +const kDerefTypes = { + deref_address_of_identifier: { + wgsl: `(*(&a))`, + requires_pointer_composite_access: false + }, + deref_pointer: { + wgsl: `(*p)`, + requires_pointer_composite_access: false + }, + address_of_identifier: { + wgsl: `(&a)`, + requires_pointer_composite_access: true + }, + pointer: { + wgsl: `p`, + requires_pointer_composite_access: true + } +}; + +g.test('basic'). +desc( + `Validates address-of (&) every supported variable type, ensuring the type is correct by + assigning to an explicitly typed pointer. Also validates dereferencing the reference, + ensuring the type is correct by assigning to an explicitly typed variable.` +). +params((u) => +u. +combine('addressSpace', kAddressSpaces). +combine('accessMode', kAccessModes). +combine('storageType', kStorageTypes). +combine('derefType', keysOf(kDerefTypes)). +filter((t) => { + if (t.storageType === 'bool') { + return t.addressSpace === 'function' || t.addressSpace === 'private'; + } + return true; +}). +filter((t) => { + // This test does not test composite access + return !kDerefTypes[t.derefType].requires_pointer_composite_access; +}) +). +beforeAllSubcases((t) => { + if (t.params.storageType === 'f16') { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); + } +}). +fn((t) => { + const isLocal = t.params.addressSpace === 'function'; + const deref = kDerefTypes[t.params.derefType]; + // Only specify access mode for storage buffers + const commaAccessMode = t.params.addressSpace === 'storage' ? `, ${t.params.accessMode}` : ''; + + let varDecl = ''; + if (t.params.addressSpace === 'uniform' || t.params.addressSpace === 'storage') { + varDecl += '@group(0) @binding(0) '; + } + varDecl += `var<${t.params.addressSpace}${commaAccessMode}> a : VarType;`; + + const wgsl = ` + ${t.params.storageType === 'f16' ? 'enable f16;' : ''} + + alias VarType = ${t.params.storageType}; + alias PtrType = ptr<${t.params.addressSpace}, VarType ${commaAccessMode}>; + + ${isLocal ? '' : varDecl} + + fn foo() { + ${isLocal ? varDecl : ''} + let p : PtrType = &a; + var deref : VarType = ${deref.wgsl}; + } + `; + + t.expectCompileResult(true, wgsl); +}); + +g.test('composite'). +desc( + `Validates address-of (&) every supported variable type for composite types, ensuring the type + is correct by assigning to an explicitly typed pointer. Also validates dereferencing the + reference followed by member/index access, ensuring the type is correct by assigning to an + explicitly typed variable.` +). +params((u) => +u. +combine('addressSpace', kAddressSpaces). +combine('compositeType', kCompositeTypes). +combine('storageType', kStorageTypes). +beginSubcases(). +combine('derefType', keysOf(kDerefTypes)). +combine('accessMode', kAccessModes). +filter((t) => { + if (t.storageType === 'bool') { + return t.addressSpace === 'function' || t.addressSpace === 'private'; + } + return true; +}). +filter((t) => { + if (t.compositeType === 'mat') { + return t.storageType === 'f32' || t.storageType === 'f16'; + } + return true; +}) +). +beforeAllSubcases((t) => { + if (t.params.storageType === 'f16') { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); + } +}). +fn((t) => { + const isLocal = t.params.addressSpace === 'function'; + const deref = kDerefTypes[t.params.derefType]; + // Only specify access mode for storage buffers + const commaAccessMode = t.params.addressSpace === 'storage' ? `, ${t.params.accessMode}` : ''; + + let varDecl = ''; + if (t.params.addressSpace === 'uniform' || t.params.addressSpace === 'storage') { + varDecl += '@group(0) @binding(0) '; + } + varDecl += `var<${t.params.addressSpace}${commaAccessMode}> a : VarType;`; + + let wgsl = ` + ${t.params.storageType === 'f16' ? 'enable f16;' : ''}`; + + switch (t.params.compositeType) { + case 'array': + wgsl += ` + struct S { @align(16) member : ${t.params.storageType} } + alias VarType = array; + alias PtrType = ptr<${t.params.addressSpace}, VarType ${commaAccessMode}>; + ${isLocal ? '' : varDecl} + + fn foo() { + ${isLocal ? varDecl : ''} + let p : PtrType = &a; + var deref : ${t.params.storageType} = ${deref.wgsl}[0].member; + }`; + break; + case 'struct': + wgsl += ` + struct S { member : ${t.params.storageType} } + alias VarType = S; + alias PtrType = ptr<${t.params.addressSpace}, VarType ${commaAccessMode}>; + ${isLocal ? '' : varDecl} + + fn foo() { + ${isLocal ? varDecl : ''} + let p : PtrType = &a; + var deref : ${t.params.storageType} = ${deref.wgsl}.member; + }`; + break; + case 'vec': + wgsl += ` + alias VarType = vec3<${t.params.storageType}>; + alias PtrType = ptr<${t.params.addressSpace}, VarType ${commaAccessMode}>; + ${isLocal ? '' : varDecl} + + fn foo() { + ${isLocal ? varDecl : ''} + let p : PtrType = &a; + var deref_member : ${t.params.storageType} = ${deref.wgsl}.x; + var deref_index : ${t.params.storageType} = ${deref.wgsl}[0]; + }`; + break; + case 'mat': + wgsl += ` + alias VarType = mat2x3<${t.params.storageType}>; + alias PtrType = ptr<${t.params.addressSpace}, VarType ${commaAccessMode}>; + ${isLocal ? '' : varDecl} + + fn foo() { + ${isLocal ? varDecl : ''} + let p : PtrType = &a; + var deref_vec : vec3<${t.params.storageType}> = ${deref.wgsl}[0]; + var deref_elem : ${t.params.storageType} = ${deref.wgsl}[0][0]; + }`; + break; + } + + let shouldPass = true; + if ( + kDerefTypes[t.params.derefType].requires_pointer_composite_access && + !t.hasLanguageFeature('pointer_composite_access')) + { + shouldPass = false; + } + + t.expectCompileResult(shouldPass, wgsl); +}); + +const kInvalidCases = { + address_of_let: ` + let a = 1; + let p = &a;`, + address_of_texture: ` + let p = &t;`, + address_of_sampler: ` + let p = &s;`, + address_of_function: ` + let p = &func;`, + address_of_vector_elem_via_member: ` + var a : vec3(); + let p = &a.x;`, + address_of_vector_elem_via_index: ` + var a : vec3(); + let p = &a[0];`, + address_of_matrix_elem: ` + var a : mat2x3(); + let p = &a[0][0];`, + deref_non_pointer: ` + var a = 1; + let p = *a; + ` +}; +g.test('invalid'). +desc('Test invalid cases of unary address-of and dereference'). +params((u) => u.combine('case', keysOf(kInvalidCases))). +fn((t) => { + const wgsl = ` + @group(0) @binding(0) var s : sampler; + @group(0) @binding(1) var t : texture_2d; + fn func() {} + fn main() { + ${kInvalidCases[t.params.case]} + } + `; + t.expectCompileResult(false, wgsl); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/arithmetic_negation.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/arithmetic_negation.spec.js new file mode 100644 index 0000000000..7d323f7bae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/arithmetic_negation.spec.js @@ -0,0 +1,114 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for arithmetic negation expressions. +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../common/util/data_tables.js'; +import { kAllScalarsAndVectors, scalarTypeOf, Type } from '../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// A list of scalar and vector types. +const kScalarAndVectorTypes = objectsToRecord(kAllScalarsAndVectors); + +g.test('scalar_vector'). +desc( + ` + Validates that scalar and vector numeric negation expressions are accepted for numerical types that are signed. + ` +). +params((u) => u.combine('type', keysOf(kScalarAndVectorTypes)).beginSubcases()). +beforeAllSubcases((t) => { + if (scalarTypeOf(kScalarAndVectorTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kScalarAndVectorTypes[t.params.type]; + const elementTy = scalarTypeOf(type); + const hasF16 = elementTy === Type.f16; + const code = ` +${hasF16 ? 'enable f16;' : ''} +const rhs = ${type.create(0).wgsl()}; +const foo = -rhs; +`; + + t.expectCompileResult(elementTy.signed, code); +}); + + + + + + + +const kInvalidTypes = { + mat2x2f: { + expr: 'm', + control: (e) => `${e}[0][0]` + }, + + array: { + expr: 'arr', + control: (e) => `${e}[0]` + }, + + ptr: { + expr: '(&b)', + control: (e) => `*${e}` + }, + + atomic: { + expr: 'a', + control: (e) => `atomicLoad(&${e})` + }, + + texture: { + expr: 't', + control: (e) => `textureLoad(${e}, vec2(), 0).x` + }, + + sampler: { + expr: 's', + control: (e) => `textureSampleLevel(t, ${e}, vec2(), 0).x` + }, + + struct: { + expr: 'str', + control: (e) => `${e}.b` + } +}; + +g.test('invalid_types'). +desc( + ` + Validates that arithmetic negation expressions are never accepted for non-scalar and non-vector types. + ` +). +params((u) => +u.combine('type', keysOf(kInvalidTypes)).combine('control', [true, false]).beginSubcases() +). +fn((t) => { + const type = kInvalidTypes[t.params.type]; + const expr = t.params.control ? type.control(type.expr) : type.expr; + const code = ` +@group(0) @binding(0) var t : texture_2d; +@group(0) @binding(1) var s : sampler; +@group(0) @binding(2) var a : atomic; + +struct S { b : i32 } + +var b : i32; +var m : mat2x2f; +var arr : array; +var str : S; + +@compute @workgroup_size(1) +fn main() { + let foo = -${expr}; +} +`; + + t.expectCompileResult(t.params.control, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/bitwise_complement.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/bitwise_complement.spec.js new file mode 100644 index 0000000000..5dcc9a42f2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/bitwise_complement.spec.js @@ -0,0 +1,114 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for bitwise complement expressions. +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../common/util/data_tables.js'; +import { kAllScalarsAndVectors, scalarTypeOf, Type } from '../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// A list of scalar and vector types. +const kScalarAndVectorTypes = objectsToRecord(kAllScalarsAndVectors); + +g.test('scalar_vector'). +desc( + ` + Validates that scalar and vector bitwise complement expressions are only accepted for integers. + ` +). +params((u) => u.combine('type', keysOf(kScalarAndVectorTypes)).beginSubcases()). +beforeAllSubcases((t) => { + if (scalarTypeOf(kScalarAndVectorTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kScalarAndVectorTypes[t.params.type]; + const elementTy = scalarTypeOf(type); + const hasF16 = elementTy === Type.f16; + const code = ` +${hasF16 ? 'enable f16;' : ''} +const rhs = ${type.create(0).wgsl()}; +const foo = ~rhs; +`; + + t.expectCompileResult([Type.abstractInt, Type.i32, Type.u32].includes(elementTy), code); +}); + + + + + + + +const kInvalidTypes = { + mat2x2f: { + expr: 'm', + control: (e) => `i32(${e}[0][0])` + }, + + array: { + expr: 'arr', + control: (e) => `${e}[0]` + }, + + ptr: { + expr: '(&u)', + control: (e) => `*${e}` + }, + + atomic: { + expr: 'a', + control: (e) => `atomicLoad(&${e})` + }, + + texture: { + expr: 't', + control: (e) => `i32(textureLoad(${e}, vec2(), 0).x)` + }, + + sampler: { + expr: 's', + control: (e) => `i32(textureSampleLevel(t, ${e}, vec2(), 0).x)` + }, + + struct: { + expr: 'str', + control: (e) => `${e}.u` + } +}; + +g.test('invalid_types'). +desc( + ` + Validates that bitwise complement expressions are never accepted for non-scalar and non-vector types. + ` +). +params((u) => +u.combine('type', keysOf(kInvalidTypes)).combine('control', [true, false]).beginSubcases() +). +fn((t) => { + const type = kInvalidTypes[t.params.type]; + const expr = t.params.control ? type.control(type.expr) : type.expr; + const code = ` +@group(0) @binding(0) var t : texture_2d; +@group(0) @binding(1) var s : sampler; +@group(0) @binding(2) var a : atomic; + +struct S { u : u32 } + +var u : u32; +var m : mat2x2f; +var arr : array; +var str : S; + +@compute @workgroup_size(1) +fn main() { + let foo = ~${expr}; +} +`; + + t.expectCompileResult(t.params.control, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/logical_negation.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/logical_negation.spec.js new file mode 100644 index 0000000000..acfa6715e7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/expression/unary/logical_negation.spec.js @@ -0,0 +1,114 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for logical negation expressions. +`;import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../common/util/data_tables.js'; +import { kAllScalarsAndVectors, scalarTypeOf, Type } from '../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// A list of scalar and vector types. +const kScalarAndVectorTypes = objectsToRecord(kAllScalarsAndVectors); + +g.test('scalar_vector'). +desc( + ` + Validates that scalar and vector logical negation expressions are only accepted for bool types. + ` +). +params((u) => u.combine('type', keysOf(kScalarAndVectorTypes)).beginSubcases()). +beforeAllSubcases((t) => { + if (scalarTypeOf(kScalarAndVectorTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const type = kScalarAndVectorTypes[t.params.type]; + const elementTy = scalarTypeOf(type); + const hasF16 = elementTy === Type.f16; + const code = ` +${hasF16 ? 'enable f16;' : ''} +const rhs = ${type.create(0).wgsl()}; +const foo = !rhs; +`; + + t.expectCompileResult(elementTy === Type.bool, code); +}); + + + + + + + +const kInvalidTypes = { + mat2x2f: { + expr: 'm', + control: (e) => `bool(${e}[0][0])` + }, + + array: { + expr: 'arr', + control: (e) => `${e}[0]` + }, + + ptr: { + expr: '(&b)', + control: (e) => `*${e}` + }, + + atomic: { + expr: 'a', + control: (e) => `bool(atomicLoad(&${e}))` + }, + + texture: { + expr: 't', + control: (e) => `bool(textureLoad(${e}, vec2(), 0).x)` + }, + + sampler: { + expr: 's', + control: (e) => `bool(textureSampleLevel(t, ${e}, vec2(), 0).x)` + }, + + struct: { + expr: 'str', + control: (e) => `${e}.b` + } +}; + +g.test('invalid_types'). +desc( + ` + Validates that logical negation expressions are never accepted for non-scalar and non-vector types. + ` +). +params((u) => +u.combine('type', keysOf(kInvalidTypes)).combine('control', [true, false]).beginSubcases() +). +fn((t) => { + const type = kInvalidTypes[t.params.type]; + const expr = t.params.control ? type.control(type.expr) : type.expr; + const code = ` +@group(0) @binding(0) var t : texture_2d; +@group(0) @binding(1) var s : sampler; +@group(0) @binding(2) var a : atomic; + +struct S { b : bool } + +var b : bool; +var m : mat2x2f; +var arr : array; +var str : S; + +@compute @workgroup_size(1) +fn main() { + let foo = !${expr}; +} +`; + + t.expectCompileResult(t.params.control, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/extension/pointer_composite_access.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/extension/pointer_composite_access.spec.js new file mode 100644 index 0000000000..50b0696a3a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/extension/pointer_composite_access.spec.js @@ -0,0 +1,130 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for pointer_composite_access extension +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +function makeSource(module, init_expr, pointer_read_expr) { + return ` + ${module} + fn f() { + var a = ${init_expr}; + let p = &a; + let r = ${pointer_read_expr}; + }`; +} + +const kCases = { + // Via identifier 'a' + array_index_access_via_identifier: { + module: '', + init_expr: 'array()', + via_deref: '(*(&a))[0]', + via_pointer: '(&a)[0]' + }, + vector_index_access_via_identifier: { + module: '', + init_expr: 'vec3()', + via_deref: '(*(&a))[0]', + via_pointer: '(&a)[0]' + }, + vector_member_access_via_identifier: { + module: '', + init_expr: 'vec3()', + via_deref: '(*(&a)).x', + via_pointer: '(&a).x' + }, + matrix_index_access_via_identifier: { + module: '', + init_expr: 'mat2x3()', + via_deref: '(*(&a))[0]', + via_pointer: '(&a)[0]' + }, + struct_member_access_via_identifier: { + module: 'struct S { a : i32, }', + init_expr: 'S()', + via_deref: '(*(&a)).a', + via_pointer: '(&a).a' + }, + builtin_struct_modf_via_identifier: { + module: '', + init_expr: 'modf(1.5)', + via_deref: 'vec2((*(&a)).fract, (*(&a)).whole)', + via_pointer: 'vec2((&a).fract, (&a).whole)' + }, + builtin_struct_frexp_via_identifier: { + module: '', + init_expr: 'frexp(1.5)', + via_deref: 'vec2((*(&a)).fract, f32((*(&a)).exp))', + via_pointer: 'vec2((&a).fract, f32((&a).exp))' + }, + + // Via pointer 'p' + array_index_access_via_pointer: { + module: '', + init_expr: 'array()', + via_deref: '(*p)[0]', + via_pointer: 'p[0]' + }, + vector_index_access_via_pointer: { + module: '', + init_expr: 'vec3()', + via_deref: '(*p)[0]', + via_pointer: 'p[0]' + }, + vector_member_access_via_pointer: { + module: '', + init_expr: 'vec3()', + via_deref: '(*p).x', + via_pointer: 'p.x' + }, + matrix_index_access_via_pointer: { + module: '', + init_expr: 'mat2x3()', + via_deref: '(*p)[0]', + via_pointer: 'p[0]' + }, + struct_member_access_via_pointer: { + module: 'struct S { a : i32, }', + init_expr: 'S()', + via_deref: '(*p).a', + via_pointer: 'p.a' + }, + builtin_struct_modf_via_pointer: { + module: '', + init_expr: 'modf(1.5)', + via_deref: 'vec2((*p).fract, (*p).whole)', + via_pointer: 'vec2(p.fract, p.whole)' + }, + builtin_struct_frexp_via_pointer: { + module: '', + init_expr: 'frexp(1.5)', + via_deref: 'vec2((*p).fract, f32((*p).exp))', + via_pointer: 'vec2(p.fract, f32(p.exp))' + } +}; + +g.test('deref'). +desc('Baseline test: pointer deref is always valid'). +params((u) => u.combine('case', keysOf(kCases))). +fn((t) => { + const curr = kCases[t.params.case]; + const source = makeSource(curr.module, curr.init_expr, curr.via_deref); + t.expectCompileResult(true, source); +}); + +g.test('pointer'). +desc( + 'Tests that direct pointer access is valid if pointer_composite_access is supported, else it should fail' +). +params((u) => u.combine('case', keysOf(kCases))). +fn((t) => { + const curr = kCases[t.params.case]; + const source = makeSource(curr.module, curr.init_expr, curr.via_pointer); + const should_pass = t.hasLanguageFeature('pointer_composite_access'); + t.expectCompileResult(should_pass, source); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/extension/readonly_and_readwrite_storage_textures.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/extension/readonly_and_readwrite_storage_textures.spec.js new file mode 100644 index 0000000000..62b689c20e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/extension/readonly_and_readwrite_storage_textures.spec.js @@ -0,0 +1,48 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for the readonly_and_readwrite_storage_textures language feature +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { TexelFormats } from '../../types.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kFeatureName = 'readonly_and_readwrite_storage_textures'; + +g.test('var_decl'). +desc( + `Checks that the read and read_write access modes are only allowed with the language feature present` +). +paramsSubcasesOnly((u) => +u. +combine('type', [ +'texture_storage_1d', +'texture_storage_2d', +'texture_storage_2d_array', +'texture_storage_3d'] +). +combine('format', TexelFormats). +combine('access', ['read', 'write', 'read_write']) +). +fn((t) => { + const { type, format, access } = t.params; + const source = `@group(0) @binding(0) var t : ${type}<${format.format}, ${access}>;`; + const requiresFeature = access !== 'write'; + t.expectCompileResult(t.hasLanguageFeature(kFeatureName) || !requiresFeature, source); +}); + +g.test('textureBarrier'). +desc( + `Checks that the textureBarrier() builtin is only allowed with the language feature present` +). +fn((t) => { + t.expectCompileResult( + t.hasLanguageFeature(kFeatureName), + ` + @workgroup_size(1) @compute fn main() { + textureBarrier(); + } + ` + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/functions/alias_analysis.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/functions/alias_analysis.spec.js index ab5d7c3327..0549dc9c90 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/functions/alias_analysis.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/functions/alias_analysis.spec.js @@ -38,50 +38,284 @@ function shouldPass(aliased, ...uses) { return !aliased || !uses.some((u) => kUses[u].is_write) || uses.includes('no_access'); } + + +const kWritableAddressSpaces = ['private', 'function', 'storage', 'workgroup']; + +function ptr(addressSpace, type) { + switch (addressSpace) { + case 'function': + return `ptr`; + case 'private': + return `ptr`; + case 'storage': + return `ptr`; + case 'uniform': + return `ptr`; + case 'workgroup': + return `ptr`; + } +} + +function declareModuleScopeVar( +name, +addressSpace, +type) +{ + const binding = name === 'x' ? 0 : 1; + switch (addressSpace) { + case 'private': + return `var ${name} : ${type};`; + case 'storage': + return `@binding(${binding}) @group(0) var ${name} : ${type};`; + case 'uniform': + return `@binding(${binding}) @group(0) var ${name} : ${type};`; + case 'workgroup': + return `var ${name} : ${type};`; + } +} + +function maybeDeclareModuleScopeVar(name, addressSpace, type) { + if (addressSpace === 'function') { + return ''; + } + return declareModuleScopeVar(name, addressSpace, type); +} + +function maybeDeclareFunctionScopeVar(name, addressSpace, type) { + switch (addressSpace) { + case 'function': + return `var ${name} : ${type};`; + default: + return ``; + } +} + +/** + * @returns true if a pointer of the given address space requires the + * 'unrestricted_pointer_parameters' language feature. + */ +function requiresUnrestrictedPointerParameters(addressSpace) { + return addressSpace !== 'function' && addressSpace !== 'private'; +} + g.test('two_pointers'). desc(`Test aliasing of two pointers passed to a function.`). params((u) => u. -combine('address_space', ['private', 'function']). -combine('a_use', keysOf(kUses)). -combine('b_use', keysOf(kUses)). +combine('address_space', kWritableAddressSpaces). combine('aliased', [true, false]). -beginSubcases() +beginSubcases(). +combine('a_use', keysOf(kUses)). +combine('b_use', keysOf(kUses)) ). fn((t) => { + if (requiresUnrestrictedPointerParameters(t.params.address_space)) { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + } + const code = ` -${t.params.address_space === 'private' ? `var x : i32; var y : i32;` : ``} +${maybeDeclareModuleScopeVar('x', t.params.address_space, 'i32')} +${maybeDeclareModuleScopeVar('y', t.params.address_space, 'i32')} -fn callee(pa : ptr<${t.params.address_space}, i32>, - pb : ptr<${t.params.address_space}, i32>) -> i32 { +fn callee(pa : ${ptr(t.params.address_space, 'i32')}, + pb : ${ptr(t.params.address_space, 'i32')}) -> i32 { ${kUses[t.params.a_use].gen(`*pa`)} ${kUses[t.params.b_use].gen(`*pb`)} return 0; } fn caller() { - ${t.params.address_space === 'function' ? `var x : i32; var y : i32;` : ``} + ${maybeDeclareFunctionScopeVar('x', t.params.address_space, 'i32')} + ${maybeDeclareFunctionScopeVar('y', t.params.address_space, 'i32')} callee(&x, ${t.params.aliased ? `&x` : `&y`}); } `; t.expectCompileResult(shouldPass(t.params.aliased, t.params.a_use, t.params.b_use), code); }); +g.test('two_pointers_to_array_elements'). +desc(`Test aliasing of two array element pointers passed to a function.`). +params((u) => +u. +combine('address_space', kWritableAddressSpaces). +combine('index', [0, 1]). +combine('aliased', [true, false]). +beginSubcases(). +combine('a_use', keysOf(kUses)). +combine('b_use', keysOf(kUses)) +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const code = ` +${maybeDeclareModuleScopeVar('x', t.params.address_space, 'array')} +${maybeDeclareModuleScopeVar('y', t.params.address_space, 'array')} + +fn callee(pa : ${ptr(t.params.address_space, 'i32')}, + pb : ${ptr(t.params.address_space, 'i32')}) -> i32 { + ${kUses[t.params.a_use].gen(`*pa`)} + ${kUses[t.params.b_use].gen(`*pb`)} + return 0; +} + +fn caller() { + ${maybeDeclareFunctionScopeVar('x', t.params.address_space, 'array')} + ${maybeDeclareFunctionScopeVar('y', t.params.address_space, 'array')} + callee(&x[${t.params.index}], ${t.params.aliased ? `&x[0]` : `&y[0]`}); +} +`; + t.expectCompileResult(shouldPass(t.params.aliased, t.params.a_use, t.params.b_use), code); +}); + +g.test('two_pointers_to_array_elements_indirect'). +desc( + `Test aliasing of two array pointers passed to a function, which indexes those arrays and then +passes the element pointers to another function.` +). +params((u) => +u. +combine('address_space', kWritableAddressSpaces). +combine('index', [0, 1]). +combine('aliased', [true, false]). +beginSubcases(). +combine('a_use', keysOf(kUses)). +combine('b_use', keysOf(kUses)) +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const code = ` +${maybeDeclareModuleScopeVar('x', t.params.address_space, 'array')} +${maybeDeclareModuleScopeVar('y', t.params.address_space, 'array')} + +fn callee(pa : ${ptr(t.params.address_space, 'i32')}, + pb : ${ptr(t.params.address_space, 'i32')}) -> i32 { + ${kUses[t.params.a_use].gen(`*pa`)} + ${kUses[t.params.b_use].gen(`*pb`)} + return 0; +} + +fn index(pa : ${ptr(t.params.address_space, 'array')}, + pb : ${ptr(t.params.address_space, 'array')}) -> i32 { + return callee(&(*pa)[${t.params.index}], &(*pb)[0]); +} + +fn caller() { + ${maybeDeclareFunctionScopeVar('x', t.params.address_space, 'array')} + ${maybeDeclareFunctionScopeVar('y', t.params.address_space, 'array')} + index(&x, ${t.params.aliased ? `&x` : `&y`}); +} +`; + t.expectCompileResult(shouldPass(t.params.aliased, t.params.a_use, t.params.b_use), code); +}); + +g.test('two_pointers_to_struct_members'). +desc(`Test aliasing of two struct member pointers passed to a function.`). +params((u) => +u. +combine('address_space', kWritableAddressSpaces). +combine('member', ['a', 'b']). +combine('aliased', [true, false]). +beginSubcases(). +combine('a_use', keysOf(kUses)). +combine('b_use', keysOf(kUses)) +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const code = ` +struct S { + a : i32, + b : i32, +} + +${maybeDeclareModuleScopeVar('x', t.params.address_space, 'S')} +${maybeDeclareModuleScopeVar('y', t.params.address_space, 'S')} + +fn callee(pa : ${ptr(t.params.address_space, 'i32')}, + pb : ${ptr(t.params.address_space, 'i32')}) -> i32 { + ${kUses[t.params.a_use].gen(`*pa`)} + ${kUses[t.params.b_use].gen(`*pb`)} + return 0; +} + +fn caller() { + ${maybeDeclareFunctionScopeVar('x', t.params.address_space, 'S')} + ${maybeDeclareFunctionScopeVar('y', t.params.address_space, 'S')} + callee(&x.${t.params.member}, ${t.params.aliased ? `&x.a` : `&y.a`}); +} +`; + t.expectCompileResult(shouldPass(t.params.aliased, t.params.a_use, t.params.b_use), code); +}); + +g.test('two_pointers_to_struct_members_indirect'). +desc( + `Test aliasing of two structure pointers passed to a function, which accesses members of those +structures and then passes the member pointers to another function.` +). +params((u) => +u. +combine('address_space', kWritableAddressSpaces). +combine('member', ['a', 'b']). +combine('aliased', [true, false]). +beginSubcases(). +combine('a_use', keysOf(kUses)). +combine('b_use', keysOf(kUses)) +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const code = ` +struct S { + a : i32, + b : i32, +} + +${maybeDeclareModuleScopeVar('x', t.params.address_space, 'S')} +${maybeDeclareModuleScopeVar('y', t.params.address_space, 'S')} + +fn callee(pa : ${ptr(t.params.address_space, 'i32')}, + pb : ${ptr(t.params.address_space, 'i32')}) -> i32 { + ${kUses[t.params.a_use].gen(`*pa`)} + ${kUses[t.params.b_use].gen(`*pb`)} + return 0; +} + +fn access(pa : ${ptr(t.params.address_space, 'S')}, + pb : ${ptr(t.params.address_space, 'S')}) -> i32 { + return callee(&(*pa).${t.params.member}, &(*pb).a); +} + +fn caller() { + ${maybeDeclareFunctionScopeVar('x', t.params.address_space, 'S')} + ${maybeDeclareFunctionScopeVar('y', t.params.address_space, 'S')} + access(&x, ${t.params.aliased ? `&x` : `&y`}); +} +`; + t.expectCompileResult(shouldPass(t.params.aliased, t.params.a_use, t.params.b_use), code); +}); + g.test('one_pointer_one_module_scope'). desc(`Test aliasing of a pointer with a direct access to a module-scope variable.`). params((u) => u. -combine('a_use', keysOf(kUses)). -combine('b_use', keysOf(kUses)). +combine('address_space', ['private', 'storage', 'workgroup']). combine('aliased', [true, false]). -beginSubcases() +beginSubcases(). +combine('a_use', keysOf(kUses)). +combine('b_use', keysOf(kUses)) ). fn((t) => { + if (requiresUnrestrictedPointerParameters(t.params.address_space)) { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + } + const code = ` -var x : i32; -var y : i32; +${declareModuleScopeVar('x', t.params.address_space, 'i32')} +${declareModuleScopeVar('y', t.params.address_space, 'i32')} -fn callee(pb : ptr) -> i32 { +fn callee(pb : ${ptr(t.params.address_space, 'i32')}) -> i32 { ${kUses[t.params.a_use].gen(`x`)} ${kUses[t.params.b_use].gen(`*pb`)} return 0; @@ -98,29 +332,34 @@ g.test('subcalls'). desc(`Test aliasing of two pointers passed to a function, and then passed to other functions.`). params((u) => u. -combine('a_use', ['no_access', 'assign', 'binary_lhs']). -combine('b_use', ['no_access', 'assign', 'binary_lhs']). +combine('address_space', ['private', 'storage', 'workgroup']). combine('aliased', [true, false]). -beginSubcases() +beginSubcases(). +combine('a_use', ['no_access', 'assign', 'binary_lhs']). +combine('b_use', ['no_access', 'assign', 'binary_lhs']) ). fn((t) => { + if (requiresUnrestrictedPointerParameters(t.params.address_space)) { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + } + const ptr_i32 = ptr(t.params.address_space, 'i32'); const code = ` -var x : i32; -var y : i32; +${declareModuleScopeVar('x', t.params.address_space, 'i32')} +${declareModuleScopeVar('y', t.params.address_space, 'i32')} -fn subcall_no_access(p : ptr) { +fn subcall_no_access(p : ${ptr_i32}) { let pp = &*p; } -fn subcall_binary_lhs(p : ptr) -> i32 { +fn subcall_binary_lhs(p : ${ptr_i32}) -> i32 { return *p + 1; } -fn subcall_assign(p : ptr) { +fn subcall_assign(p : ${ptr_i32}) { *p = 42; } -fn callee(pa : ptr, pb : ptr) -> i32 { +fn callee(pa : ${ptr_i32}, pb : ${ptr_i32}) -> i32 { let new_pa = &*pa; let new_pb = &*pb; subcall_${t.params.a_use}(new_pa); @@ -139,20 +378,25 @@ g.test('member_accessors'). desc(`Test aliasing of two pointers passed to a function and used with member accessors.`). params((u) => u. -combine('a_use', ['no_access', 'assign', 'binary_lhs']). -combine('b_use', ['no_access', 'assign', 'binary_lhs']). +combine('address_space', ['private', 'storage', 'workgroup']). combine('aliased', [true, false]). -beginSubcases() +beginSubcases(). +combine('a_use', ['no_access', 'assign', 'binary_lhs']). +combine('b_use', ['no_access', 'assign', 'binary_lhs']) ). fn((t) => { + if (requiresUnrestrictedPointerParameters(t.params.address_space)) { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + } + + const ptr_S = ptr(t.params.address_space, 'S'); const code = ` struct S { a : i32 } -var x : S; -var y : S; +${declareModuleScopeVar('x', t.params.address_space, 'S')} +${declareModuleScopeVar('y', t.params.address_space, 'S')} -fn callee(pa : ptr, - pb : ptr) -> i32 { +fn callee(pa : ${ptr_S}, pb : ${ptr_S}) -> i32 { ${kUses[t.params.a_use].gen(`(*pa).a`)} ${kUses[t.params.b_use].gen(`(*pb).a`)} return 0; @@ -167,12 +411,18 @@ fn caller() { g.test('same_pointer_read_and_write'). desc(`Test that we can read from and write to the same pointer.`). -params((u) => u.beginSubcases()). +params((u) => +u.combine('address_space', ['private', 'storage', 'workgroup']).beginSubcases() +). fn((t) => { + if (requiresUnrestrictedPointerParameters(t.params.address_space)) { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + } + const code = ` -var v : i32; +${declareModuleScopeVar('v', t.params.address_space, 'i32')} -fn callee(p : ptr) { +fn callee(p : ${ptr(t.params.address_space, 'i32')}) { *p = *p + 1; } @@ -185,10 +435,12 @@ fn caller() { g.test('aliasing_inside_function'). desc(`Test that we can alias pointers inside a function.`). -params((u) => u.beginSubcases()). +params((u) => +u.combine('address_space', ['private', 'storage', 'workgroup']).beginSubcases() +). fn((t) => { const code = ` -var v : i32; +${declareModuleScopeVar('v', t.params.address_space, 'i32')} fn foo() { var v : i32; @@ -199,4 +451,237 @@ fn foo() { } `; t.expectCompileResult(true, code); +}); + +const kAtomicBuiltins = [ +'atomicLoad', +'atomicStore', +'atomicAdd', +'atomicSub', +'atomicMax', +'atomicMin', +'atomicAnd', +'atomicOr', +'atomicXor', +'atomicExchange', +'atomicCompareExchangeWeak']; + + + + +function isWrite(builtin) { + switch (builtin) { + case 'atomicLoad': + return false; + case 'atomicAdd': + case 'atomicSub': + case 'atomicMax': + case 'atomicMin': + case 'atomicAnd': + case 'atomicOr': + case 'atomicXor': + case 'atomicExchange': + case 'atomicCompareExchangeWeak': + case 'atomicStore': + return true; + } +} + +function callAtomicBuiltin(builtin, ptr) { + switch (builtin) { + case 'atomicLoad': + return `i += ${builtin}(${ptr})`; + case 'atomicStore': + return `${builtin}(${ptr}, 42)`; + case 'atomicAdd': + case 'atomicSub': + case 'atomicMax': + case 'atomicMin': + case 'atomicAnd': + case 'atomicOr': + case 'atomicXor': + case 'atomicExchange': + return `i += ${builtin}(${ptr}, 42)`; + case 'atomicCompareExchangeWeak': + return `${builtin}(${ptr}, 10, 42)`; + } +} + +g.test('two_atomic_pointers'). +desc(`Test aliasing of two atomic pointers passed to a function.`). +params((u) => +u. +combine('builtin_a', kAtomicBuiltins). +combine('builtin_b', ['atomicLoad', 'atomicStore']). +combine('address_space', ['storage', 'workgroup']). +combine('aliased', [true, false]). +beginSubcases() +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const ptr_atomic_i32 = ptr(t.params.address_space, 'atomic'); + const code = ` +${declareModuleScopeVar('x', t.params.address_space, 'atomic')} +${declareModuleScopeVar('y', t.params.address_space, 'atomic')} + +fn callee(pa : ${ptr_atomic_i32}, pb : ${ptr_atomic_i32}) { + var i : i32; + ${callAtomicBuiltin(t.params.builtin_a, 'pa')}; + ${callAtomicBuiltin(t.params.builtin_b, 'pb')}; +} + +fn caller() { + callee(&x, &${t.params.aliased ? 'x' : 'y'}); +} +`; + const shouldFail = + t.params.aliased && (isWrite(t.params.builtin_a) || isWrite(t.params.builtin_b)); + t.expectCompileResult(!shouldFail, code); +}); + +g.test('two_atomic_pointers_to_array_elements'). +desc(`Test aliasing of two atomic array element pointers passed to a function.`). +params((u) => +u. +combine('builtin_a', kAtomicBuiltins). +combine('builtin_b', ['atomicLoad', 'atomicStore']). +combine('address_space', ['storage', 'workgroup']). +combine('index', [0, 1]). +combine('aliased', [true, false]). +beginSubcases() +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const ptr_atomic_i32 = ptr(t.params.address_space, 'atomic'); + const code = ` +${declareModuleScopeVar('x', t.params.address_space, 'array, 32>')} +${declareModuleScopeVar('y', t.params.address_space, 'array, 32>')} + +fn callee(pa : ${ptr_atomic_i32}, pb : ${ptr_atomic_i32}) { + var i : i32; + ${callAtomicBuiltin(t.params.builtin_a, 'pa')}; + ${callAtomicBuiltin(t.params.builtin_b, 'pb')}; +} + +fn caller() { + callee(&x[${t.params.index}], &${t.params.aliased ? 'x' : 'y'}[0]); +} +`; + const shouldFail = + t.params.aliased && (isWrite(t.params.builtin_a) || isWrite(t.params.builtin_b)); + t.expectCompileResult(!shouldFail, code); +}); + +g.test('two_atomic_pointers_to_struct_members'). +desc(`Test aliasing of two struct member atomic pointers passed to a function.`). +params((u) => +u. +combine('builtin_a', kAtomicBuiltins). +combine('builtin_b', ['atomicLoad', 'atomicStore']). +combine('address_space', ['storage', 'workgroup']). +combine('member', ['a', 'b']). +combine('aliased', [true, false]). +beginSubcases() +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const ptr_atomic_i32 = ptr(t.params.address_space, 'atomic'); + const code = ` +struct S { + a : atomic, + b : atomic, +} + +${declareModuleScopeVar('x', t.params.address_space, 'S')} +${declareModuleScopeVar('y', t.params.address_space, 'S')} + +fn callee(pa : ${ptr_atomic_i32}, pb : ${ptr_atomic_i32}) { + var i : i32; + ${callAtomicBuiltin(t.params.builtin_a, 'pa')}; + ${callAtomicBuiltin(t.params.builtin_b, 'pb')}; +} + +fn caller() { + callee(&x.${t.params.member}, &${t.params.aliased ? 'x' : 'y'}.a); +} +`; + const shouldFail = + t.params.aliased && (isWrite(t.params.builtin_a) || isWrite(t.params.builtin_b)); + t.expectCompileResult(!shouldFail, code); +}); + +g.test('one_atomic_pointer_one_module_scope'). +desc(`Test aliasing of an atomic pointer with a direct access to a module-scope variable.`). +params((u) => +u. +combine('builtin_a', kAtomicBuiltins). +combine('builtin_b', ['atomicLoad', 'atomicStore']). +combine('address_space', ['storage', 'workgroup']). +combine('aliased', [true, false]). +beginSubcases() +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + const ptr_atomic_i32 = ptr(t.params.address_space, 'atomic'); + const code = ` +${declareModuleScopeVar('x', t.params.address_space, 'atomic')} +${declareModuleScopeVar('y', t.params.address_space, 'atomic')} + +fn callee(p : ${ptr_atomic_i32}) { + var i : i32; + ${callAtomicBuiltin(t.params.builtin_a, 'p')}; + ${callAtomicBuiltin(t.params.builtin_b, t.params.aliased ? '&x' : '&y')}; +} + +fn caller() { + callee(&x); +} +`; + const shouldFail = + t.params.aliased && (isWrite(t.params.builtin_a) || isWrite(t.params.builtin_b)); + t.expectCompileResult(!shouldFail, code); +}); + +g.test('workgroup_uniform_load'). +desc(`Test aliasing via workgroupUniformLoad.`). +params((u) => +u. +combine('use', ['load', 'store', 'workgroupUniformLoad']). +combine('aliased', [true, false]). +beginSubcases() +). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + + function emitUse() { + switch (t.params.use) { + case 'load': + return `v = *pa`; + case 'store': + return `*pa = 1`; + case 'workgroupUniformLoad': + return `v = workgroupUniformLoad(pa)`; + } + } + + const code = ` +var x : i32; +var y : i32; + +fn callee(pa : ptr, pb : ptr) -> i32 { + var v : i32; + ${emitUse()}; + return v + workgroupUniformLoad(pb); +} + +fn caller() { + callee(&x, &${t.params.aliased ? 'x' : 'y'}); +} +`; + const shouldFail = t.params.aliased && t.params.use === 'store'; + t.expectCompileResult(!shouldFail, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/functions/restrictions.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/functions/restrictions.spec.js index 94e38837d9..30bdeb54fe 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/functions/restrictions.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/functions/restrictions.spec.js @@ -12,6 +12,30 @@ export const g = makeTestGroup(ShaderValidationTest); +const kCCommonTypeDecls = ` +struct runtime_array_struct { + arr : array +} + +struct constructible { + a : i32, + b : u32, + c : f32, + d : bool, +} + +struct host_shareable { + a : i32, + b : u32, + c : f32, +} + +struct struct_with_array { + a : array +} + +`; + const kVertexPosCases = { bare_position: { name: `@builtin(position) vec4f`, value: `vec4f()`, valid: true }, nested_position: { name: `pos_struct`, value: `pos_struct()`, valid: true }, @@ -145,20 +169,7 @@ fn((t) => { const code = ` ${enable} -struct runtime_array_struct { - arr : array -} - -struct constructible { - a : i32, - b : u32, - c : f32, - d : bool, -} - -struct struct_with_array { - a : array -} +${kCCommonTypeDecls} struct atomic_struct { a : atomic @@ -246,21 +257,42 @@ const kFunctionParamTypeCases = { ptr3: { name: `ptr`, valid: true }, ptr4: { name: `ptr`, valid: true }, + // Pointers only valid with unrestricted_pointer_parameters + ptr5: { name: `ptr`, valid: 'with_unrestricted_pointer_parameters' }, + ptr6: { name: `ptr`, valid: 'with_unrestricted_pointer_parameters' }, + ptr7: { name: `ptr`, valid: 'with_unrestricted_pointer_parameters' }, + ptr8: { name: `ptr`, valid: 'with_unrestricted_pointer_parameters' }, + ptr9: { name: `ptr`, valid: 'with_unrestricted_pointer_parameters' }, + ptr10: { + name: `ptr`, + valid: 'with_unrestricted_pointer_parameters' + }, + ptr11: { + name: `ptr`, + valid: 'with_unrestricted_pointer_parameters' + }, + ptr12: { + name: `ptr`, + valid: 'with_unrestricted_pointer_parameters' + }, + ptrWorkgroupAtomic: { + name: `ptr>`, + valid: 'with_unrestricted_pointer_parameters' + }, + ptrWorkgroupNestedAtomic: { + name: `ptr,1>>`, + valid: 'with_unrestricted_pointer_parameters' + }, + // Invalid pointers. - ptr5: { name: `ptr`, valid: false }, - ptr6: { name: `ptr`, valid: false }, - ptr7: { name: `ptr`, valid: false }, - ptr8: { name: `ptr`, valid: false }, - ptr9: { name: `ptr`, valid: false }, - ptr10: { name: `ptr`, valid: false }, // Can't spell handle address space - ptr12: { name: `ptr`, valid: false }, - ptr13: { name: `ptr`, valid: false }, // No store type - ptr14: { name: `ptr`, valid: false }, // Invalid store type - ptr15: { name: `ptr`, valid: false }, // Can't specify access mode - ptr16: { name: `ptr`, valid: false }, // Can't specify access mode - ptr17: { name: `ptr`, valid: false }, // Can't specify access mode - ptrWorkgroupAtomic: { name: `ptr>`, valid: false }, - ptrWorkgroupNestedAtomic: { name: `ptr,1>>`, valid: false } + invalid_ptr1: { name: `ptr`, valid: false }, // Can't spell handle address space + invalid_ptr2: { name: `ptr`, valid: false }, + invalid_ptr3: { name: `ptr`, valid: false }, // No store type + invalid_ptr4: { name: `ptr`, valid: false }, // Can't specify access mode + invalid_ptr5: { name: `ptr`, valid: false }, // Can't specify access mode + invalid_ptr6: { name: `ptr`, valid: false }, // Can't specify access mode + invalid_ptr7: { name: `ptr`, valid: false }, // Invalid store type + invalid_ptr8: { name: `ptr`, valid: false } // non-constructable pointer type }; g.test('function_parameter_types'). @@ -278,25 +310,17 @@ fn((t) => { const code = ` ${enable} -struct runtime_array_struct { - arr : array -} - -struct constructible { - a : i32, - b : u32, - c : f32, - d : bool, -} - -struct struct_with_array { - a : array -} +${kCCommonTypeDecls} fn foo(param : ${testcase.name}) { }`; - t.expectCompileResult(testcase.valid, code); + let isValid = testcase.valid; + if (isValid === 'with_unrestricted_pointer_parameters') { + isValid = t.hasLanguageFeature('unrestricted_pointer_parameters'); + } + + t.expectCompileResult(isValid, code); }); @@ -304,6 +328,7 @@ fn foo(param : ${testcase.name}) { + const kFunctionParamValueCases = { // Values u32_literal: { value: `0u`, matches: ['u32'] }, @@ -426,15 +451,47 @@ const kFunctionParamValueCases = { ptr3: { value: `&g_u32`, matches: ['ptr3'] }, ptr4: { value: `&g_constructible`, matches: ['ptr4'] }, - // Invalid pointers - ptr5: { value: `&f_constructible.b`, matches: [] }, - ptr6: { value: `&g_constructible.b`, matches: [] }, - ptr7: { value: `&f_struct_with_array.a[1].b`, matches: [] }, - ptr8: { value: `&g_struct_with_array.a[2]`, matches: [] }, - ptr9: { value: `&ro_constructible.b`, matches: [] }, - ptr10: { value: `&rw_constructible`, matches: [] }, - ptr11: { value: `&uniform_constructible`, matches: [] }, - ptr12: { value: `&ro_constructible`, matches: [] } + // Requires 'unrestricted_pointer_parameters' WGSL feature + ptr5: { + value: `&f_constructible.b`, + matches: ['ptr1'], + needsUnrestrictedPointerParameters: true + }, + ptr6: { + value: `&g_constructible.b`, + matches: ['ptr3'], + needsUnrestrictedPointerParameters: true + }, + ptr7: { + value: `&f_struct_with_array.a[1].b`, + matches: ['ptr1'], + needsUnrestrictedPointerParameters: true + }, + ptr8: { + value: `&g_struct_with_array.a[2]`, + matches: ['ptr4'], + needsUnrestrictedPointerParameters: true + }, + ptr9: { + value: `&ro_host_shareable.b`, + matches: ['ptr5', 'ptr6'], + needsUnrestrictedPointerParameters: true + }, + ptr10: { + value: `&rw_host_shareable`, + matches: ['ptr10'], + needsUnrestrictedPointerParameters: true + }, + ptr11: { + value: `&ro_host_shareable`, + matches: ['ptr11'], + needsUnrestrictedPointerParameters: true + }, + ptr12: { + value: `&uniform_host_shareable`, + matches: ['ptr12'], + needsUnrestrictedPointerParameters: true + } }; function parameterMatches(decl, matches) { @@ -454,10 +511,11 @@ desc( params((u) => u. combine('decl', keysOf(kFunctionParamTypeCases)). -combine('arg', keysOf(kFunctionParamValueCases)). filter((u) => { - return kFunctionParamTypeCases[u.decl].valid; -}) + return kFunctionParamTypeCases[u.decl].valid !== false; +}). +beginSubcases(). +combine('arg', keysOf(kFunctionParamValueCases)) ). beforeAllSubcases((t) => { if (kFunctionParamTypeCases[t.params.decl].name === 'f16') { @@ -471,26 +529,7 @@ fn((t) => { const code = ` ${enable} -struct runtime_array_struct { - arr : array -} - -struct constructible { - a : i32, - b : u32, - c : f32, - d : bool, -} - -struct host_shareable { - a : i32, - b : u32, - c : f32, -} - -struct struct_with_array { - a : array -} +${kCCommonTypeDecls} @group(0) @binding(0) var t : texture_2d; @group(0) @binding(1) @@ -507,11 +546,11 @@ var t_multisampled : texture_multisampled_2d; var t_external : texture_external; @group(1) @binding(0) -var ro_constructible : host_shareable; +var ro_host_shareable : host_shareable; @group(1) @binding(1) -var rw_constructible : host_shareable; +var rw_host_shareable : host_shareable; @group(1) @binding(2) -var uniform_constructible : host_shareable; +var uniform_host_shareable : host_shareable; fn bar(param : ${param.name}) { } @@ -568,7 +607,17 @@ fn foo() { } `; - t.expectCompileResult(parameterMatches(t.params.decl, arg.matches), code); + const needsUnrestrictedPointerParameters = + (kFunctionParamTypeCases[t.params.decl].valid === 'with_unrestricted_pointer_parameters' || + arg.needsUnrestrictedPointerParameters) ?? + false; + + let isValid = parameterMatches(t.params.decl, arg.matches); + if (isValid && needsUnrestrictedPointerParameters) { + isValid = t.hasLanguageFeature('unrestricted_pointer_parameters'); + } + + t.expectCompileResult(isValid, code); }); g.test('no_direct_recursion'). @@ -691,67 +740,75 @@ function checkArgTypeMatch(param_type, arg_matches) { return false; } -g.test('call_arg_types_match_params'). +g.test('call_arg_types_match_1_param'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#function-calls'). +desc(`Test that the argument types match in order`). +params((u) => +u. +combine('p1_type', kParamsTypes) // +.beginSubcases(). +combine('arg1_value', keysOf(kArgValues)) +). +fn((t) => { + const code = ` +fn bar(p1 : ${t.params.p1_type}) { } +fn foo() { + bar(${kArgValues[t.params.arg1_value].value}); +}`; + + const res = checkArgTypeMatch(t.params.p1_type, kArgValues[t.params.arg1_value].matches); + t.expectCompileResult(res, code); +}); + +g.test('call_arg_types_match_2_params'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#function-calls'). +desc(`Test that the argument types match in order`). +params((u) => +u. +combine('p1_type', kParamsTypes). +combine('p2_type', kParamsTypes). +beginSubcases(). +combine('arg1_value', keysOf(kArgValues)). +combine('arg2_value', keysOf(kArgValues)) +). +fn((t) => { + const code = ` +fn bar(p1 : ${t.params.p1_type}, p2 : ${t.params.p2_type}) { } +fn foo() { + bar(${kArgValues[t.params.arg1_value].value}, ${kArgValues[t.params.arg2_value].value}); +}`; + + const res = + checkArgTypeMatch(t.params.p1_type, kArgValues[t.params.arg1_value].matches) && + checkArgTypeMatch(t.params.p2_type, kArgValues[t.params.arg2_value].matches); + t.expectCompileResult(res, code); +}); + +g.test('call_arg_types_match_3_params'). specURL('https://gpuweb.github.io/gpuweb/wgsl/#function-calls'). desc(`Test that the argument types match in order`). params((u) => u. -combine('num_args', [1, 2, 3]). combine('p1_type', kParamsTypes). combine('p2_type', kParamsTypes). combine('p3_type', kParamsTypes). +beginSubcases(). combine('arg1_value', keysOf(kArgValues)). combine('arg2_value', keysOf(kArgValues)). combine('arg3_value', keysOf(kArgValues)) ). fn((t) => { - let code = ` - fn bar(`; - for (let i = 0; i < t.params.num_args; i++) { - switch (i) { - case 0: - default:{ - code += `p${i} : ${t.params.p1_type},`; - break; - } - case 1:{ - code += `p${i} : ${t.params.p2_type},`; - break; - } - case 2:{ - code += `p${i} : ${t.params.p3_type},`; - break; - } - } - } - code += `) { } - fn foo() { - bar(`; - for (let i = 0; i < t.params.num_args; i++) { - switch (i) { - case 0: - default:{ - code += `${kArgValues[t.params.arg1_value].value},`; - break; - } - case 1:{ - code += `${kArgValues[t.params.arg2_value].value},`; - break; - } - case 2:{ - code += `${kArgValues[t.params.arg3_value].value},`; - break; - } - } - } - code += `);\n}`; + const code = ` +fn bar(p1 : ${t.params.p1_type}, p2 : ${t.params.p2_type}, p3 : ${t.params.p3_type}) { } +fn foo() { + bar(${kArgValues[t.params.arg1_value].value}, + ${kArgValues[t.params.arg2_value].value}, + ${kArgValues[t.params.arg3_value].value}); +}`; - let res = checkArgTypeMatch(t.params.p1_type, kArgValues[t.params.arg1_value].matches); - if (res && t.params.num_args > 1) { - res = checkArgTypeMatch(t.params.p2_type, kArgValues[t.params.arg2_value].matches); - } - if (res && t.params.num_args > 2) { - res = checkArgTypeMatch(t.params.p3_type, kArgValues[t.params.arg3_value].matches); - } + const res = + checkArgTypeMatch(t.params.p1_type, kArgValues[t.params.arg1_value].matches) && + checkArgTypeMatch(t.params.p2_type, kArgValues[t.params.arg2_value].matches) && + checkArgTypeMatch(t.params.p3_type, kArgValues[t.params.arg3_value].matches); t.expectCompileResult(res, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/break.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/break.spec.js index bfdb0fc279..2a694f3cdc 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/break.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/break.spec.js @@ -15,10 +15,6 @@ const kTests = { src: 'loop { if true { break; } }', pass: true }, - continuing_break_if: { - src: 'loop { continuing { break if (true); } }', - pass: true - }, while_break: { src: 'while true { break; }', pass: true diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/break_if.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/break_if.spec.js new file mode 100644 index 0000000000..a525d1514b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/break_if.spec.js @@ -0,0 +1,141 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validation tests for break if`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kTests = { + compound_break: { + src: '{ break if true; }', + pass: false + }, + loop_break: { + src: 'loop { break if true; }', + pass: false + }, + loop_if_break: { + src: 'loop { if true { break if false; } }', + pass: false + }, + continuing_break_if: { + src: 'loop { continuing { break if true; } }', + pass: true + }, + continuing_break_if_parens: { + src: 'loop { continuing { break if (true); } }', + pass: true + }, + continuing_break_if_not_last: { + src: 'loop { continuing { break if (true); let a = 4;} }', + pass: false + }, + while_break: { + src: 'while true { break if true; }', + pass: false + }, + while_if_break: { + src: 'while true { if true { break if true; } }', + pass: false + }, + for_break: { + src: 'for (;;) { break if true; }', + pass: false + }, + for_if_break: { + src: 'for (;;) { if true { break if true; } }', + pass: false + }, + switch_case_break: { + src: 'switch(1) { default: { break if true; } }', + pass: false + }, + switch_case_if_break: { + src: 'switch(1) { default: { if true { break if true; } } }', + pass: false + }, + break: { + src: 'break if true;', + pass: false + }, + return_break: { + src: 'return break if true;', + pass: false + }, + if_break: { + src: 'if true { break if true; }', + pass: false + }, + continuing_if_break: { + src: 'loop { continuing { if (true) { break if true; } } }', + pass: false + }, + switch_break: { + src: 'switch(1) { break if true; }', + pass: false + } +}; + +g.test('placement'). +desc('Test that break if placement is validated correctly'). +params((u) => u.combine('stmt', keysOf(kTests))). +fn((t) => { + const code = ` +@vertex +fn vtx() -> @builtin(position) vec4f { + ${kTests[t.params.stmt].src} + return vec4f(1); +} + `; + t.expectCompileResult(kTests[t.params.stmt].pass, code); +}); + +const vec_types = [2, 3, 4]. +map((i) => ['i32', 'u32', 'f32', 'f16'].map((j) => `vec${i}<${j}>`)). +reduce((a, c) => a.concat(c), []); +const f32_matrix_types = [2, 3, 4]. +map((i) => [2, 3, 4].map((j) => `mat${i}x${j}f`)). +reduce((a, c) => a.concat(c), []); +const f16_matrix_types = [2, 3, 4]. +map((i) => [2, 3, 4].map((j) => `mat${i}x${j}`)). +reduce((a, c) => a.concat(c), []); + +g.test('non_bool_param'). +desc('Test that break if fails with a non-bool parameter'). +params((u) => +u.combine('type', [ +'f32', +'f16', +'i32', +'u32', +'S', +...vec_types, +...f32_matrix_types, +...f16_matrix_types] +) +). +beforeAllSubcases((t) => { + if (t.params.type.includes('f16')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const code = ` +struct S { + a: i32, +} + +@vertex +fn vtx() -> @builtin(position) vec4f { + var v: ${t.params.type}; + + loop { + continuing { + break if v; + } + } + return vec4f(1); +}`; + t.expectCompileResult(t.params.type === 'bool', code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/compound.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/compound.spec.js new file mode 100644 index 0000000000..12fc0724d8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/compound.spec.js @@ -0,0 +1,52 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validation tests for compound statements`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kTests = { + missing_start: { + src: '}', + pass: false + }, + missing_end: { + src: '{', + pass: false + }, + empty: { + src: '{}', + pass: true + }, + semicolon: { + src: '{;}', + pass: true + }, + semicolons: { + src: '{;;}', + pass: true + }, + decl: { + src: '{const c = 1;}', + pass: true + }, + nested: { + src: '{ {} }', + pass: true + } +}; + +g.test('parse'). +desc('Test that compound statments parse'). +params((u) => u.combine('stmt', keysOf(kTests))). +fn((t) => { + const code = ` +@vertex +fn vtx() -> @builtin(position) vec4f { + ${kTests[t.params.stmt].src} + return vec4f(1); +} + `; + t.expectCompileResult(kTests[t.params.stmt].pass, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/continuing.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/continuing.spec.js new file mode 100644 index 0000000000..7f6825dcd3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/continuing.spec.js @@ -0,0 +1,185 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validation tests for continuing`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kTests = { + continuing_break_if: { + src: 'loop { continuing { break if true; } }', + pass: true + }, + continuing_empty: { + src: 'loop { if a == 4 { break; } continuing { } }', + pass: true + }, + continuing_break_if_parens: { + src: 'loop { continuing { break if (true); } }', + pass: true + }, + continuing_discard: { + src: 'loop { if a == 4 { break; } continuing { discard; } }', + pass: true + }, + continuing_continue_nested: { + src: 'loop { if a == 4 { break; } continuing { loop { if a == 4 { break; } continue; } } }', + pass: true + }, + continuing_continue: { + src: 'loop { if a == 4 { break; } continuing { continue; } }', + pass: false + }, + continuing_break: { + src: 'loop { continuing { break; } }', + pass: false + }, + continuing_for: { + src: 'loop { if a == 4 { break; } continuing { for(;a < 4;) { } } }', + pass: true + }, + continuing_for_break: { + src: 'loop { if a == 4 { break; } continuing { for(;;) { break; } } }', + pass: true + }, + continuing_while: { + src: 'loop { if a == 4 { break; } continuing { while a < 4 { } } }', + pass: true + }, + continuing_while_break: { + src: 'loop { if a == 4 { break; } continuing { while true { break; } } }', + pass: true + }, + continuing_semicolon: { + src: 'loop { if a == 4 { break; } continuing { ; } }', + pass: true + }, + continuing_functionn_call: { + src: 'loop { if a == 4 { break; } continuing { _ = b(); } }', + pass: true + }, + continuing_let: { + src: 'loop { if a == 4 { break; } continuing { let c = b(); } }', + pass: true + }, + continuing_var: { + src: 'loop { if a == 4 { break; } continuing { var a = b(); } }', + pass: true + }, + continuing_const: { + src: 'loop { if a == 4 { break; } continuing { const a = 1; } }', + pass: true + }, + continuing_block: { + src: 'loop { if a == 4 { break; } continuing { { } } }', + pass: true + }, + continuing_const_assert: { + src: 'loop { if a == 4 { break; } continuing { const_assert(1 != 2); } }', + pass: true + }, + continuing_loop: { + src: 'loop { if a == 4 { break; } continuing { loop { break; } } }', + pass: true + }, + continuing_if: { + src: 'loop { if a == 4 { break; } continuing { if true { } else if false { } else { } } }', + pass: true + }, + continuing_switch: { + src: 'loop { if a == 4 { break; } continuing { switch 2 { default: { } } } }', + pass: true + }, + continuing_switch_break: { + src: 'loop { if a == 4 { break; } continuing { switch 2 { default: { break; } } } }', + pass: true + }, + continuing_loop_nested_continuing: { + src: 'loop { if a == 4 { break; } continuing { loop { if a == 4 { break; } continuing { } } } }', + pass: true + }, + continuing_inc: { + src: 'loop { if a == 4 { break; } continuing { a += 1; } }', + pass: true + }, + continuing_dec: { + src: 'loop { if a == 4 { break; } continuing { a -= 1; } }', + pass: true + }, + while: { + src: 'while a < 4 { continuing { break if true; } }', + pass: false + }, + for: { + src: 'for (;a < 4;) { continuing { break if true; } }', + pass: false + }, + switch_case: { + src: 'switch(1) { default: { continuing { break if true; } } }', + pass: false + }, + switch: { + src: 'switch(1) { continuing { break if true; } }', + pass: false + }, + continuing: { + src: 'continuing { break if true; }', + pass: false + }, + return: { + src: 'return continuing { break if true; }', + pass: false + }, + if_body: { + src: 'if true { continuing { break if true; } }', + pass: false + }, + if: { + src: 'if true { } continuing { break if true; } }', + pass: false + }, + if_else: { + src: 'if true { } else { } continuing { break if true; } }', + pass: false + }, + continuing_continuing: { + src: 'loop { if a == 4 { break; } continuing { continuing { break if true; } } }', + pass: false + }, + no_body: { + src: 'loop { if a == 4 { break; } continuing }', + pass: false + }, + return_in_continue: { + src: 'loop { if a == 4 { break; } continuing { return vec4f(2); } }', + pass: false + }, + return_if_nested_in_continue: { + src: 'loop { if a == 4 { break; } continuing { if true { return vec4f(2); } } }', + pass: false + }, + return_for_nested_in_continue: { + src: 'loop { if a == 4 { break; } continuing { for(;a < 4;) { return vec4f(2); } } }', + pass: false + } +}; + +g.test('placement'). +desc('Test that continuing placement is validated correctly'). +params((u) => u.combine('stmt', keysOf(kTests))). +fn((t) => { + const code = ` +fn b() -> i32 { + return 1; +} + +@fragment +fn frag() -> @location(0) vec4f { + var a = 0; + ${kTests[t.params.stmt].src} + return vec4f(1); +} + `; + t.expectCompileResult(kTests[t.params.stmt].pass, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/diagnostic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/diagnostic.spec.js index 8c05c6607f..b7581c122c 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/diagnostic.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/diagnostic.spec.js @@ -198,4 +198,264 @@ fn((t) => { const d2 = generateDiagnostic('attribute', t.params.s2, 'derivative_uniformity'); const code = `${kNestedLocations[t.params.loc](d1, d2)}`; t.expectCompileResult(true, code); +}); + +g.test('after_other_directives'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#diagnostics'). +desc(`Tests other global directives before a diagnostic directive.`). +params((u) => +u.combine('directive', ['enable f16', 'requires readonly_and_readwrite_storage_textures']) +). +beforeAllSubcases((t) => { + if (t.params.directive.startsWith('enable')) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + if (t.params.directive.startsWith('requires')) { + t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); + } + + let code = `${t.params.directive};`; + code += generateDiagnostic('directive', 'info', 'derivative_uniformity') + ';'; + t.expectCompileResult(true, code); +}); + + + + + + +function scopeCode(body) { + return ` +@group(0) @binding(0) var t : texture_1d; +@group(0) @binding(1) var s : sampler; +var non_uniform_cond : bool; +var non_uniform_coord : f32; +var non_uniform_val : u32; +@fragment fn main() { + ${body} +} +`; +} + +const kScopeCases = { + override_global_off: { + code: ` + ${generateDiagnostic('directive', 'error', 'derivative_uniformity')}; + ${scopeCode(` + ${generateDiagnostic('', 'off', 'derivative_uniformity')} + if non_uniform_cond { + _ = textureSample(t,s,0.0); + }`)}; + `, + result: true + }, + override_global_on: { + code: ` + ${generateDiagnostic('directive', 'off', 'derivative_uniformity')}; + ${scopeCode(` + ${generateDiagnostic('', 'error', 'derivative_uniformity')} + if non_uniform_cond { + _ = textureSample(t,s,0.0); + }`)} + `, + result: false + }, + override_global_warn: { + code: ` + ${generateDiagnostic('directive', 'error', 'derivative_uniformity')}; + ${scopeCode(` + ${generateDiagnostic('', 'warning', 'derivative_uniformity')} + if non_uniform_cond { + _ = textureSample(t,s,0.0); + }`)} + `, + result: 'warn' + }, + global_if_nothing_else_warn: { + code: ` + ${generateDiagnostic('directive', 'warning', 'derivative_uniformity')}; + ${scopeCode(` + if non_uniform_cond { + _ = textureSample(t,s,0.0); + }`)} + `, + result: 'warn' + }, + deepest_nesting_warn: { + code: scopeCode(` + ${generateDiagnostic('', 'error', 'derivative_uniformity')} + if non_uniform_cond { + ${generateDiagnostic('', 'warning', 'derivative_uniformity')} + if non_uniform_cond { + _ = textureSample(t,s,0.0); + } + }`), + result: 'warn' + }, + deepest_nesting_off: { + code: scopeCode(` + ${generateDiagnostic('', 'error', 'derivative_uniformity')} + if non_uniform_cond { + ${generateDiagnostic('', 'off', 'derivative_uniformity')} + if non_uniform_cond { + _ = textureSample(t,s,0.0); + } + }`), + result: true + }, + deepest_nesting_error: { + code: scopeCode(` + ${generateDiagnostic('', 'off', 'derivative_uniformity')} + if non_uniform_cond { + ${generateDiagnostic('', 'error', 'derivative_uniformity')} + if non_uniform_cond { + _ = textureSample(t,s,0.0); + } + }`), + result: false + }, + other_nest_unaffected: { + code: ` + ${generateDiagnostic('directive', 'warning', 'derivative_uniformity')}; + ${scopeCode(` + ${generateDiagnostic('', 'off', 'derivative_uniformity')} + if non_uniform_cond { + _ = textureSample(t,s,0.0); + } + if non_uniform_cond { + _ = textureSample(t,s,0.0); + }`)} + `, + result: 'warn' + }, + deeper_nest_no_effect: { + code: ` + ${generateDiagnostic('directive', 'error', 'derivative_uniformity')}; + ${scopeCode(` + if non_uniform_cond { + ${generateDiagnostic('', 'off', 'derivative_uniformity')} + if non_uniform_cond { + } + _ = textureSample(t,s,0.0); + }`)} + `, + result: false + }, + call_unaffected_error: { + code: ` + ${generateDiagnostic('directive', 'error', 'derivative_uniformity')}; + fn foo() { _ = textureSample(t,s,0.0); } + ${scopeCode(` + ${generateDiagnostic('', 'off', 'derivative_uniformity')} + if non_uniform_cond { + foo(); + }`)} + `, + result: false + }, + call_unaffected_warn: { + code: ` + ${generateDiagnostic('directive', 'warning', 'derivative_uniformity')}; + fn foo() { _ = textureSample(t,s,0.0); } + ${scopeCode(` + ${generateDiagnostic('', 'off', 'derivative_uniformity')} + if non_uniform_cond { + foo(); + }`)} + `, + result: 'warn' + }, + call_unaffected_off: { + code: ` + ${generateDiagnostic('directive', 'off', 'derivative_uniformity')}; + fn foo() { _ = textureSample(t,s,0.0); } + ${scopeCode(` + ${generateDiagnostic('', 'error', 'derivative_uniformity')} + if non_uniform_cond { + foo(); + }`)} + `, + result: true + }, + if_condition_error: { + code: scopeCode(` + if (non_uniform_cond) { + ${generateDiagnostic('', 'error', 'derivative_uniformity')} + if textureSample(t,s,non_uniform_coord).x > 0.0 + ${generateDiagnostic('', 'off', 'derivative_uniformity')} { + } + }`), + result: false + }, + if_condition_warn: { + code: scopeCode(` + if non_uniform_cond { + ${generateDiagnostic('', 'warning', 'derivative_uniformity')} + if textureSample(t,s,non_uniform_coord).x > 0.0 + ${generateDiagnostic('', 'error', 'derivative_uniformity')} { + } + }`), + result: 'warn' + }, + if_condition_off: { + code: scopeCode(` + if non_uniform_cond { + ${generateDiagnostic('', 'off', 'derivative_uniformity')} + if textureSample(t,s,non_uniform_coord).x > 0.0 + ${generateDiagnostic('', 'error', 'derivative_uniformity')} { + } + }`), + result: true + }, + switch_error: { + code: scopeCode(` + ${generateDiagnostic('', 'error', 'derivative_uniformity')} + switch non_uniform_val { + case 0 ${generateDiagnostic('', 'off', 'derivative_uniformity')} { + } + default { + _ = textureSample(t,s,0.0); + } + }`), + result: false + }, + switch_warn: { + code: scopeCode(` + ${generateDiagnostic('', 'warning', 'derivative_uniformity')} + switch non_uniform_val { + case 0 ${generateDiagnostic('', 'off', 'derivative_uniformity')} { + } + default { + _ = textureSample(t,s,0.0); + } + }`), + result: 'warn' + }, + switch_off: { + code: scopeCode(` + ${generateDiagnostic('', 'off', 'derivative_uniformity')} + switch non_uniform_val { + case 0 ${generateDiagnostic('', 'error', 'derivative_uniformity')}{ + } + default { + _ = textureSample(t,s,0.0); + } + }`), + result: true + } +}; + +g.test('diagnostic_scoping'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#diagnostics'). +desc('Tests that innermost scope controls the diagnostic'). +params((u) => u.combine('case', keysOf(kScopeCases))). +fn((t) => { + const testcase = kScopeCases[t.params.case]; + if (testcase.result === 'warn') { + t.expectCompileWarning(true, testcase.code); + } else { + t.expectCompileResult(testcase.result, testcase.code); + } }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/enable.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/enable.spec.js index a95ea54acf..b0ce591dfa 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/enable.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/enable.spec.js @@ -13,11 +13,21 @@ const kCases = { enable f16;`, pass: false }, - after_decl: { + decl_after: { code: `enable f16; alias i = i32;`, pass: true }, + requires_before: { + code: `requires readonly_and_readwrite_storage_textures; +enable f16;`, + pass: true + }, + diagnostic_before: { + code: `diagnostic(info, derivative_uniformity); +enable f16;`, + pass: true + }, const_assert_before: { code: `const_assert 1 == 1; enable f16;`, @@ -48,7 +58,7 @@ f16;`, enable f16;`, pass: true }, - multipe_entries: { + multiple_entries: { code: `enable f16, f16, f16;`, pass: true }, @@ -65,6 +75,10 @@ beforeAllSubcases((t) => { }). params((u) => u.combine('case', keysOf(kCases))). fn((t) => { + if (t.params.case === 'requires_before') { + t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); + } + const c = kCases[t.params.case]; t.expectCompileResult(c.pass, c.code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/must_use.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/must_use.spec.js index 2bff48a4ab..5c96cba5b9 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/must_use.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/must_use.spec.js @@ -57,27 +57,74 @@ fn((t) => { }); const kMustUseCalls = { + no_call: ``, // Never calling a @must_use function should pass phony: `_ = bar();`, let: `let tmp = bar();`, - var: `var tmp = bar();`, + local_var: `var tmp = bar();`, + private_var: `private_var = bar();`, + storage_var: `storage_var = bar();`, + pointer: ` + var a : f32; + let p = &a; + (*p) = bar();`, + vector_elem: ` + var a : vec3; + a.x = bar();`, + matrix_elem: ` + var a : mat3x2; + a[0][0] = bar();`, condition: `if bar() == 0 { }`, param: `baz(bar());`, - statement: `bar();` + return: `return bar();`, + statement: `bar();` // should fail if bar is @must_use }; g.test('call'). desc(`Validate that a call to must_use function cannot be the whole function call statement`). -params((u) => u.combine('use', ['@must_use', '']).combine('call', keysOf(kMustUseCalls))). +params((u) => +u // +.combine('use', ['@must_use', '']). +combine('call', keysOf(kMustUseCalls)) +). fn((t) => { const test = kMustUseCalls[t.params.call]; const code = ` - fn baz(param : u32) { } - ${t.params.use} fn bar() -> u32 { return 0; } - fn foo() { + @group(0) @binding(0) var storage_var : f32; + var private_var : f32; + + fn baz(param : f32) { } + + ${t.params.use} fn bar() -> f32 { return 0; } + + fn foo() ${t.params.call === 'return' ? '-> f32' : ''} { ${test} }`; - const res = t.params.call !== 'statement' || t.params.use === ''; - t.expectCompileResult(res, code); + + const should_pass = t.params.call !== 'statement' || t.params.use === ''; + t.expectCompileResult(should_pass, code); +}); + +g.test('ignore_result_of_non_must_use_that_returns_call_of_must_use'). +desc( + `Test that ignoring the result of a non-@must_use function that returns the result of a @must_use function succeeds` +). +fn((t) => { + const wgsl = ` + @must_use + fn f() -> f32 { + return 0; + } + + fn g() -> f32 { + return f(); + } + + fn main() { + g(); // Ignore result + } + `; + + t.expectCompileResult(true, wgsl); }); const kMustUseBuiltinCalls = { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/pipeline_stage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/pipeline_stage.spec.js index 4a94012262..018a6022d7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/pipeline_stage.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/pipeline_stage.spec.js @@ -73,34 +73,46 @@ fn((t) => { t.expectCompileResult(true, code); }); -g.test('duplicate_compute_on_function'). -desc(`Test that duplcate @compute attributes are not allowed.`). -params((u) => u.combine('dupe', ['', '@compute'])). +g.test('extra_on_compute_function'). +desc(`Test that an extra stage attribute on @compute functions are not allowed.`). +params((u) => +u.combine('extra', ['', '@compute', '@fragment', '@vertex']).combine('before', [false, true]) +). fn((t) => { + const before = t.params.before ? t.params.extra : ''; + const after = t.params.before ? '' : t.params.extra; const code = ` -@compute ${t.params.dupe} @workgroup_size(1) fn compute_1() {} +${before} @compute ${after} @workgroup_size(1) fn main() {} `; - t.expectCompileResult(t.params.dupe === '', code); + t.expectCompileResult(t.params.extra === '', code); }); -g.test('duplicate_fragment_on_function'). -desc(`Test that duplcate @fragment attributes are not allowed.`). -params((u) => u.combine('dupe', ['', '@fragment'])). +g.test('extra_on_fragment_function'). +desc(`Test that an extra stage attribute on @fragment functions are not allowed.`). +params((u) => +u.combine('extra', ['', '@compute', '@fragment', '@vertex']).combine('before', [false, true]) +). fn((t) => { + const before = t.params.before ? t.params.extra : ''; + const after = t.params.before ? '' : t.params.extra; const code = ` -@fragment ${t.params.dupe} fn vtx() -> @location(0) vec4f { return vec4f(1); } +${before} @fragment ${after} fn main() -> @location(0) vec4f { return vec4f(1); } `; - t.expectCompileResult(t.params.dupe === '', code); + t.expectCompileResult(t.params.extra === '', code); }); -g.test('duplicate_vertex_on_function'). -desc(`Test that duplcate @vertex attributes are not allowed.`). -params((u) => u.combine('dupe', ['', '@vertex'])). +g.test('extra_on_vertex_function'). +desc(`Test that an extra stage attribute on @vertex functions are not allowed.`). +params((u) => +u.combine('extra', ['', '@compute', '@fragment', '@vertex']).combine('before', [false, true]) +). fn((t) => { + const before = t.params.before ? t.params.extra : ''; + const after = t.params.before ? '' : t.params.extra; const code = ` -@vertex ${t.params.dupe} fn vtx() -> @builtin(position) vec4f { return vec4f(1); } +${before} @vertex ${after} fn main() -> @builtin(position) vec4f { return vec4f(1); } `; - t.expectCompileResult(t.params.dupe === '', code); + t.expectCompileResult(t.params.extra === '', code); }); g.test('placement'). diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/requires.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/requires.spec.js new file mode 100644 index 0000000000..050feef2af --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/requires.spec.js @@ -0,0 +1,103 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Parser validation tests for requires`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { kKnownWGSLLanguageFeatures } from '../../../capability_info.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kCases = { + valid: { code: `requires readonly_and_readwrite_storage_textures;`, pass: true }, + decl_before: { + code: `alias i = i32; +requires readonly_and_readwrite_storage_textures;`, + pass: false + }, + decl_after: { + code: `requires readonly_and_readwrite_storage_textures; +alias i = i32;`, + pass: true + }, + enable_before: { + code: `enable f16; +requires readonly_and_readwrite_storage_textures;`, + pass: true + }, + diagnostic_before: { + code: `diagnostic(info, derivative_uniformity); +requires readonly_and_readwrite_storage_textures;`, + pass: true + }, + const_assert_before: { + code: `const_assert 1 == 1; +requires readonly_and_readwrite_storage_textures;`, + pass: false + }, + const_assert_after: { + code: `requires readonly_and_readwrite_storage_textures; +const_assert 1 == 1;`, + pass: true + }, + embedded_comment: { + code: `/* comment + +*/requires readonly_and_readwrite_storage_textures;`, + pass: true + }, + parens: { + code: `requires(readonly_and_readwrite_storage_textures);`, + pass: false + }, + multi_line: { + code: `requires +readonly_and_readwrite_storage_textures;`, + pass: true + }, + multiple_requires_duplicate: { + code: `requires readonly_and_readwrite_storage_textures; +requires readonly_and_readwrite_storage_textures;`, + pass: true + }, + multiple_requires_different: { + code: `requires readonly_and_readwrite_storage_textures; +requires packed_4x8_integer_dot_product;`, + pass: true + }, + multiple_entries_duplicate: { + code: `requires readonly_and_readwrite_storage_textures, readonly_and_readwrite_storage_textures, readonly_and_readwrite_storage_textures;`, + pass: true + }, + multiple_entries_different: { + code: `requires readonly_and_readwrite_storage_textures, packed_4x8_integer_dot_product;`, + pass: true + }, + unknown: { + code: `requires unknown;`, + pass: false + } +}; + +g.test('requires'). +desc(`Tests that requires are validated correctly.`). +params((u) => u.combine('case', keysOf(kCases))). +beforeAllSubcases((t) => { + if (t.params.case === 'enable_before') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); + t.skipIfLanguageFeatureNotSupported('packed_4x8_integer_dot_product'); + + const c = kCases[t.params.case]; + t.expectCompileResult(c.pass, c.code); +}); + +g.test('wgsl_matches_api'). +desc(`Tests that language features are accepted iff the API reports support for them.`). +params((u) => u.combine('feature', kKnownWGSLLanguageFeatures)). +fn((t) => { + const code = `requires ${t.params.feature};`; + t.expectCompileResult(t.hasLanguageFeature(t.params.feature), code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/semicolon.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/semicolon.spec.js index f7af6a0b3e..d2feb676b1 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/semicolon.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/semicolon.spec.js @@ -27,6 +27,21 @@ fn((t) => { t.expectCompileResult( /* pass */false, `enable f16`); }); +g.test('after_requires'). +desc(`Test that a semicolon must be placed after a requires directive.`). +fn((t) => { + t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); + t.expectCompileResult( /* pass */true, `requires readonly_and_readwrite_storage_textures;`); + t.expectCompileResult( /* pass */false, `requires readonly_and_readwrite_storage_textures`); +}); + +g.test('after_diagnostic'). +desc(`Test that a semicolon must be placed after a requires directive.`). +fn((t) => { + t.expectCompileResult( /* pass */true, `diagnostic(info, derivative_uniformity);`); + t.expectCompileResult( /* pass */false, `diagnostic(info, derivative_uniformity)`); +}); + g.test('after_struct_decl'). desc(`Test that a semicolon can be placed after an struct declaration.`). fn((t) => { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/shadow_builtins.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/shadow_builtins.spec.js new file mode 100644 index 0000000000..a80ba712a3 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/shadow_builtins.spec.js @@ -0,0 +1,995 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validation tests for identifiers`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('function_param'). +desc( + `Test that a function param can shadow a builtin, but the builtin is available for other params.` +). +fn((t) => { + const code = ` +fn f(f: i32, i32: i32, t: i32) -> i32 { return i32; } + `; + t.expectCompileResult(true, code); +}); + +const kTests = { + abs: { + keyword: `abs`, + src: `_ = abs(1);` + }, + acos: { + keyword: `acos`, + src: `_ = acos(.2);` + }, + acosh: { + keyword: `acosh`, + src: `_ = acosh(1.2);` + }, + all: { + keyword: `all`, + src: `_ = all(true);` + }, + any: { + keyword: `any`, + src: `_ = any(true);` + }, + array_templated: { + keyword: `array`, + src: `_ = array(1, 2);` + }, + array: { + keyword: `array`, + src: `_ = array(1, 2);` + }, + array_length: { + keyword: `arrayLength`, + src: `_ = arrayLength(&placeholder.rt_arr);` + }, + asin: { + keyword: `asin`, + src: `_ = asin(.2);` + }, + asinh: { + keyword: `asinh`, + src: `_ = asinh(1.2);` + }, + atan: { + keyword: `atan`, + src: `_ = atan(1.2);` + }, + atanh: { + keyword: `atanh`, + src: `_ = atanh(.2);` + }, + atan2: { + keyword: `atan2`, + src: `_ = atan2(1.2, 2.3);` + }, + bool: { + keyword: `bool`, + src: `_ = bool(1);` + }, + bitcast: { + keyword: `bitcast`, + src: `_ = bitcast(1i);` + }, + ceil: { + keyword: `ceil`, + src: `_ = ceil(1.23);` + }, + clamp: { + keyword: `clamp`, + src: `_ = clamp(1, 2, 3);` + }, + cos: { + keyword: `cos`, + src: `_ = cos(2);` + }, + cosh: { + keyword: `cosh`, + src: `_ = cosh(2.2);` + }, + countLeadingZeros: { + keyword: `countLeadingZeros`, + src: `_ = countLeadingZeros(1);` + }, + countOneBits: { + keyword: `countOneBits`, + src: `_ = countOneBits(1);` + }, + countTrailingZeros: { + keyword: `countTrailingZeros`, + src: `_ = countTrailingZeros(1);` + }, + cross: { + keyword: `cross`, + src: `_ = cross(vec3(1, 2, 3), vec3(4, 5, 6));` + }, + degrees: { + keyword: `degrees`, + src: `_ = degrees(1);` + }, + determinant: { + keyword: `determinant`, + src: `_ = determinant(mat2x2(1, 2, 3, 4));` + }, + distance: { + keyword: `distance`, + src: `_ = distance(1, 2);` + }, + dot: { + keyword: `dot`, + src: `_ = dot(vec2(1, 2,), vec2(2, 3));` + }, + dot4U8Packed: { + keyword: `dot4U8Packed`, + src: `_ = dot4U8Packed(1, 2);` + }, + dot4I8Packed: { + keyword: `dot4I8Packed`, + src: `_ = dot4I8Packed(1, 2);` + }, + dpdx: { + keyword: `dpdx`, + src: `_ = dpdx(2);` + }, + dpdxCoarse: { + keyword: `dpdxCoarse`, + src: `_ = dpdxCoarse(2);` + }, + dpdxFine: { + keyword: `dpdxFine`, + src: `_ = dpdxFine(2);` + }, + dpdy: { + keyword: `dpdy`, + src: `_ = dpdy(2);` + }, + dpdyCoarse: { + keyword: `dpdyCoarse`, + src: `_ = dpdyCoarse(2);` + }, + dpdyFine: { + keyword: `dpdyFine`, + src: `_ = dpdyFine(2);` + }, + exp: { + keyword: `exp`, + src: `_ = exp(1);` + }, + exp2: { + keyword: `exp2`, + src: `_ = exp2(2);` + }, + extractBits: { + keyword: `extractBits`, + src: `_ = extractBits(1, 2, 3);` + }, + f32: { + keyword: `f32`, + src: `_ = f32(1i);` + }, + faceForward: { + keyword: `faceForward`, + src: `_ = faceForward(vec2(1, 2), vec2(3, 4), vec2(5, 6));` + }, + firstLeadingBit: { + keyword: `firstLeadingBit`, + src: `_ = firstLeadingBit(1);` + }, + firstTrailingBit: { + keyword: `firstTrailingBit`, + src: `_ = firstTrailingBit(1);` + }, + floor: { + keyword: `floor`, + src: `_ = floor(1.2);` + }, + fma: { + keyword: `fma`, + src: `_ = fma(1, 2, 3);` + }, + fract: { + keyword: `fract`, + src: `_ = fract(1);` + }, + frexp: { + keyword: `frexp`, + src: `_ = frexp(1);` + }, + fwidth: { + keyword: `fwidth`, + src: `_ = fwidth(2);` + }, + fwidthCoarse: { + keyword: `fwidthCoarse`, + src: `_ = fwidthCoarse(2);` + }, + fwidthFine: { + keyword: `fwidthFine`, + src: `_ = fwidthFine(2);` + }, + i32: { + keyword: `i32`, + src: `_ = i32(2u);` + }, + insertBits: { + keyword: `insertBits`, + src: `_ = insertBits(1, 2, 3, 4);` + }, + inverseSqrt: { + keyword: `inverseSqrt`, + src: `_ = inverseSqrt(1);` + }, + ldexp: { + keyword: `ldexp`, + src: `_ = ldexp(1, 2);` + }, + length: { + keyword: `length`, + src: `_ = length(1);` + }, + log: { + keyword: `log`, + src: `_ = log(2);` + }, + log2: { + keyword: `log2`, + src: `_ = log2(2);` + }, + mat2x2_templated: { + keyword: `mat2x2`, + src: `_ = mat2x2(1, 2, 3, 4);` + }, + mat2x2: { + keyword: `mat2x2`, + src: `_ = mat2x2(1, 2, 3, 4);` + }, + mat2x3_templated: { + keyword: `mat2x3`, + src: `_ = mat2x3(1, 2, 3, 4, 5, 6);` + }, + mat2x3: { + keyword: `mat2x3`, + src: `_ = mat2x3(1, 2, 3, 4, 5, 6);` + }, + mat2x4_templated: { + keyword: `mat2x4`, + src: `_ = mat2x4(1, 2, 3, 4, 5, 6, 7, 8);` + }, + mat2x4: { + keyword: `mat2x4`, + src: `_ = mat2x4(1, 2, 3, 4, 5, 6, 7, 8);` + }, + mat3x2_templated: { + keyword: `mat3x2`, + src: `_ = mat3x2(1, 2, 3, 4, 5, 6);` + }, + mat3x2: { + keyword: `mat3x2`, + src: `_ = mat3x2(1, 2, 3, 4, 5, 6);` + }, + mat3x3_templated: { + keyword: `mat3x3`, + src: `_ = mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9);` + }, + mat3x3: { + keyword: `mat3x3`, + src: `_ = mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9);` + }, + mat3x4_templated: { + keyword: `mat3x4`, + src: `_ = mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);` + }, + mat3x4: { + keyword: `mat3x4`, + src: `_ = mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);` + }, + mat4x2_templated: { + keyword: `mat4x2`, + src: `_ = mat4x2(1, 2, 3, 4, 5, 6, 7, 8);` + }, + mat4x2: { + keyword: `mat4x2`, + src: `_ = mat4x2(1, 2, 3, 4, 5, 6, 7, 8);` + }, + mat4x3_templated: { + keyword: `mat4x3`, + src: `_ = mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);` + }, + mat4x3: { + keyword: `mat4x3`, + src: `_ = mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);` + }, + mat4x4_templated: { + keyword: `mat4x4`, + src: `_ = mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);` + }, + mat4x4: { + keyword: `mat4x4`, + src: `_ = mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);` + }, + max: { + keyword: `max`, + src: `_ = max(1, 2);` + }, + min: { + keyword: `min`, + src: `_ = min(1, 2);` + }, + mix: { + keyword: `mix`, + src: `_ = mix(1, 2, 3);` + }, + modf: { + keyword: `modf`, + src: `_ = modf(1.2);` + }, + normalize: { + keyword: `normalize`, + src: `_ = normalize(vec2(1, 2));` + }, + pack2x16snorm: { + keyword: `pack2x16snorm`, + src: `_ = pack2x16snorm(vec2(1, 2));` + }, + pack2x16unorm: { + keyword: `pack2x16unorm`, + src: `_ = pack2x16unorm(vec2(1, 2));` + }, + pack2x16float: { + keyword: `pack2x16float`, + src: `_ = pack2x16float(vec2(1, 2));` + }, + pack4x8snorm: { + keyword: `pack4x8snorm`, + src: `_ = pack4x8snorm(vec4(1, 2, 3, 4));` + }, + pack4x8unorm: { + keyword: `pack4x8unorm`, + src: `_ = pack4x8unorm(vec4(1, 2, 3, 4));` + }, + pack4xI8: { + keyword: `pack4xI8`, + src: `_ = pack4xI8(vec4(1, 2, 3, 4));` + }, + pack4xU8: { + keyword: `pack4xU8`, + src: `_ = pack4xU8(vec4(1, 2, 3, 4));` + }, + pack4xI8Clamp: { + keyword: `pack4xI8Clamp`, + src: `_ = pack4xI8Clamp(vec4(1, 2, 3, 4));` + }, + pack4xU8Clamp: { + keyword: `pack4xU8Clamp`, + src: `_ = pack4xU8Clamp(vec4(1, 2, 3, 4));` + }, + pow: { + keyword: `pow`, + src: `_ = pow(1, 2);` + }, + quantizeToF16: { + keyword: `quantizeToF16`, + src: `_ = quantizeToF16(1.2);` + }, + radians: { + keyword: `radians`, + src: `_ = radians(1.2);` + }, + reflect: { + keyword: `reflect`, + src: `_ = reflect(vec2(1, 2), vec2(3, 4));` + }, + refract: { + keyword: `refract`, + src: `_ = refract(vec2(1, 1), vec2(2, 2), 3);` + }, + reverseBits: { + keyword: `reverseBits`, + src: `_ = reverseBits(1);` + }, + round: { + keyword: `round`, + src: `_ = round(1.2);` + }, + saturate: { + keyword: `saturate`, + src: `_ = saturate(1);` + }, + select: { + keyword: `select`, + src: `_ = select(1, 2, false);` + }, + sign: { + keyword: `sign`, + src: `_ = sign(1);` + }, + sin: { + keyword: `sin`, + src: `_ = sin(2);` + }, + sinh: { + keyword: `sinh`, + src: `_ = sinh(3);` + }, + smoothstep: { + keyword: `smoothstep`, + src: `_ = smoothstep(1, 2, 3);` + }, + sqrt: { + keyword: `sqrt`, + src: `_ = sqrt(24);` + }, + step: { + keyword: `step`, + src: `_ = step(4, 5);` + }, + tan: { + keyword: `tan`, + src: `_ = tan(2);` + }, + tanh: { + keyword: `tanh`, + src: `_ = tanh(2);` + }, + transpose: { + keyword: `transpose`, + src: `_ = transpose(mat2x2(1, 2, 3, 4));` + }, + trunc: { + keyword: `trunc`, + src: `_ = trunc(2);` + }, + u32: { + keyword: `u32`, + src: `_ = u32(1i);` + }, + unpack2x16snorm: { + keyword: `unpack2x16snorm`, + src: `_ = unpack2x16snorm(2);` + }, + unpack2x16unorm: { + keyword: `unpack2x16unorm`, + src: `_ = unpack2x16unorm(2);` + }, + unpack2x16float: { + keyword: `unpack2x16float`, + src: `_ = unpack2x16float(2);` + }, + unpack4x8snorm: { + keyword: `unpack4x8snorm`, + src: `_ = unpack4x8snorm(4);` + }, + unpack4x8unorm: { + keyword: `unpack4x8unorm`, + src: `_ = unpack4x8unorm(4);` + }, + unpack4xI8: { + keyword: `unpack4xI8`, + src: `_ = unpack4xI8(4);` + }, + unpack4xU8: { + keyword: `unpack4xU8`, + src: `_ = unpack4xU8(4);` + }, + vec2_templated: { + keyword: `vec2`, + src: `_ = vec2(1, 2);` + }, + vec2: { + keyword: `vec2`, + src: `_ = vec2(1, 2);` + }, + vec3_templated: { + keyword: `vec3`, + src: `_ = vec3(1, 2, 3);` + }, + vec3: { + keyword: `vec3`, + src: `_ = vec3(1, 2, 3);` + }, + vec4_templated: { + keyword: `vec4`, + src: `_ = vec4(1, 2, 3, 4);` + }, + vec4: { + keyword: `vec4`, + src: `_ = vec4(1, 2, 3, 4);` + } +}; + +g.test('shadow_hides_builtin'). +desc(`Test that shadows hide builtins.`). +params((u) => +u. +combine('inject', ['none', 'function', 'sibling', 'module']). +beginSubcases(). +combine('builtin', keysOf(kTests)) +). +fn((t) => { + const data = kTests[t.params.builtin]; + const local = `let ${data.keyword} = 4;`; + + const module_shadow = t.params.inject === 'module' ? `var ${data.keyword} : i32;` : ``; + const sibling_func = t.params.inject === 'sibling' ? local : ``; + const func = t.params.inject === 'function' ? local : ``; + + const code = ` +struct Data { + rt_arr: array, +} +@group(0) @binding(0) var placeholder: Data; + +${module_shadow} + +fn sibling() { + ${sibling_func} +} + +@fragment +fn main() -> @location(0) vec4f { + ${func} + ${data.src} + return vec4f(1); +} + `; + + const pass = t.params.inject === 'none' || t.params.inject === 'sibling'; + t.expectCompileResult(pass, code); +}); + +const kFloat16Tests = { + f16: { + keyword: `f16`, + src: `_ = f16(2);` + } +}; + +g.test('shadow_hides_builtin_f16'). +desc(`Test that shadows hide builtins when shader-f16 is enabled.`). +params((u) => +u. +combine('inject', ['none', 'function', 'sibling', 'module']). +beginSubcases(). +combine('builtin', keysOf(kFloat16Tests)) +). +beforeAllSubcases((t) => { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); +}). +fn((t) => { + const data = kFloat16Tests[t.params.builtin]; + const local = `let ${data.keyword} = 4;`; + + const module_shadow = t.params.inject === 'module' ? `var ${data.keyword} : f16;` : ``; + const sibling_func = t.params.inject === 'sibling' ? local : ``; + const func = t.params.inject === 'function' ? local : ``; + + const code = ` +enable f16; + +${module_shadow} + +fn sibling() { + ${sibling_func} +} + +@vertex +fn vtx() -> @builtin(position) vec4f { + ${func} + ${data.src} + return vec4f(1); +} + `; + const pass = t.params.inject === 'none' || t.params.inject === 'sibling'; + t.expectCompileResult(pass, code); +}); + +const kTextureTypeTests = { + texture_1d: { + keyword: `texture_1d`, + src: `var t: texture_1d;` + }, + texture_2d: { + keyword: `texture_2d`, + src: `var t: texture_2d;` + }, + texture_2d_array: { + keyword: `texture_2d_array`, + src: `var t: texture_2d_array;` + }, + texture_3d: { + keyword: `texture_3d`, + src: `var t: texture_3d;` + }, + texture_cube: { + keyword: `texture_cube`, + src: `var t: texture_cube;` + }, + texture_cube_array: { + keyword: `texture_cube_array`, + src: `var t: texture_cube_array;` + }, + texture_multisampled_2d: { + keyword: `texture_multisampled_2d`, + src: `var t: texture_multisampled_2d;` + }, + texture_depth_multisampled_2d: { + keyword: `texture_depth_multisampled_2d`, + src: `var t: texture_depth_multisampled_2d;` + }, + texture_external: { + keyword: `texture_external`, + src: `var t: texture_external;` + }, + texture_storage_1d: { + keyword: `texture_storage_1d`, + src: `var t: texture_storage_1d;` + }, + texture_storage_2d: { + keyword: `texture_storage_2d`, + src: `var t: texture_storage_2d;` + }, + texture_storage_2d_array: { + keyword: `texture_storage_2d_array`, + src: `var t: texture_storage_2d_array;` + }, + texture_storage_3d: { + keyword: `texture_storage_3d`, + src: `var t: texture_storage_3d;` + }, + texture_depth_2d: { + keyword: `texture_depth_2d`, + src: `var t: texture_depth_2d;` + }, + texture_depth_2d_array: { + keyword: `texture_depth_2d_array`, + src: `var t: texture_depth_2d_array;` + }, + texture_depth_cube: { + keyword: `texture_depth_cube`, + src: `var t: texture_depth_cube;` + }, + texture_depth_cube_array: { + keyword: `texture_depth_cube_array`, + src: `var t: texture_depth_cube_array;` + }, + sampler: { + keyword: `sampler`, + src: `var s: sampler;` + }, + sampler_comparison: { + keyword: `sampler_comparison`, + src: `var s: sampler_comparison;` + } +}; + +g.test('shadow_hides_builtin_handle_type'). +desc(`Test that shadows hide builtins when handle address space types are used.`). +params((u) => +u. +combine('inject', ['none', 'function', 'module']). +beginSubcases(). +combine('builtin', keysOf(kTextureTypeTests)) +). +fn((t) => { + const data = kTextureTypeTests[t.params.builtin]; + const local = `let ${data.keyword} = 4;`; + + const module_shadow = t.params.inject === 'module' ? `var ${data.keyword} : f32;` : ``; + const func = t.params.inject === 'function' ? local : ``; + + const code = ` +${module_shadow} +@group(0) @binding(0) ${data.src} + +fn func() { + ${func} +} + `; + const pass = t.params.inject === 'none' || t.params.inject === 'function'; + t.expectCompileResult(pass, code); +}); + +const kTextureTests = { + textureDimensions: { + keyword: `textureDimensions`, + src: `_ = textureDimensions(t_2d);` + }, + textureGather: { + keyword: `textureGather`, + src: `_ = textureGather(1, t_2d, s, vec2(1, 2));` + }, + textureGatherCompare: { + keyword: `textureGatherCompare`, + src: `_ = textureGatherCompare(t_2d_depth, sc, vec2(1, 2), 3);` + }, + textureLoad: { + keyword: `textureLoad`, + src: `_ = textureLoad(t_2d, vec2(1, 2), 1);` + }, + textureNumLayers: { + keyword: `textureNumLayers`, + src: `_ = textureNumLayers(t_2d_array);` + }, + textureNumLevels: { + keyword: `textureNumLevels`, + src: `_ = textureNumLevels(t_2d);` + }, + textureNumSamples: { + keyword: `textureNumSamples`, + src: `_ = textureNumSamples(t_2d_ms);` + }, + textureSample: { + keyword: `textureSample`, + src: `_ = textureSample(t_2d, s, vec2(1, 2));` + }, + textureSampleBias: { + keyword: `textureSampleBias`, + src: `_ = textureSampleBias(t_2d, s, vec2(1, 2), 2);` + }, + textureSampleCompare: { + keyword: `textureSampleCompare`, + src: `_ = textureSampleCompare(t_2d_depth, sc, vec2(1, 2), 2);` + }, + textureSampleCompareLevel: { + keyword: `textureSampleCompareLevel`, + src: `_ = textureSampleCompareLevel(t_2d_depth, sc, vec2(1, 2), 3, vec2(1, 2));` + }, + textureSampleGrad: { + keyword: `textureSampleGrad`, + src: `_ = textureSampleGrad(t_2d, s, vec2(1, 2), vec2(1, 2), vec2(1, 2));` + }, + textureSampleLevel: { + keyword: `textureSampleLevel`, + src: `_ = textureSampleLevel(t_2d, s, vec2(1, 2), 3);` + }, + textureSampleBaseClampToEdge: { + keyword: `textureSampleBaseClampToEdge`, + src: `_ = textureSampleBaseClampToEdge(t_2d, s, vec2(1, 2));` + } +}; + +g.test('shadow_hides_builtin_texture'). +desc(`Test that shadows hide texture builtins.`). +params((u) => +u. +combine('inject', ['none', 'function', 'sibling', 'module']). +beginSubcases(). +combine('builtin', keysOf(kTextureTests)) +). +fn((t) => { + const data = kTextureTests[t.params.builtin]; + const local = `let ${data.keyword} = 4;`; + + const module_shadow = t.params.inject === 'module' ? `var ${data.keyword} : i32;` : ``; + const sibling_func = t.params.inject === 'sibling' ? local : ``; + const func = t.params.inject === 'function' ? local : ``; + + const code = ` +@group(0) @binding(0) var t_2d: texture_2d; +@group(0) @binding(1) var t_2d_depth: texture_depth_2d; +@group(0) @binding(2) var t_2d_array: texture_2d_array; +@group(0) @binding(3) var t_2d_ms: texture_multisampled_2d; + +@group(1) @binding(0) var s: sampler; +@group(1) @binding(1) var sc: sampler_comparison; + +${module_shadow} + +fn sibling() { + ${sibling_func} +} + +@fragment +fn main() -> @location(0) vec4f { + ${func} + ${data.src} + return vec4f(1); +} + `; + + const pass = t.params.inject === 'none' || t.params.inject === 'sibling'; + t.expectCompileResult(pass, code); +}); + +g.test('shadow_hides_builtin_atomic_type'). +desc(`Test that shadows hide builtins when atomic types are used.`). +params((u) => u.combine('inject', ['none', 'function', 'module']).beginSubcases()). +fn((t) => { + const local = `let atomic = 4;`; + const module_shadow = t.params.inject === 'module' ? `var atomic: i32;` : ``; + const func = t.params.inject === 'function' ? local : ``; + + const code = ` +${module_shadow} + +var val: atomic; + +fn func() { + ${func} +} + `; + const pass = t.params.inject === 'none' || t.params.inject === 'function'; + t.expectCompileResult(pass, code); +}); + +const kAtomicTests = { + atomicLoad: { + keyword: `atomicLoad`, + src: `_ = atomicLoad(&a);` + }, + atomicStore: { + keyword: `atomicStore`, + src: `atomicStore(&a, 1);` + }, + atomicAdd: { + keyword: `atomicAdd`, + src: `_ = atomicAdd(&a, 1);` + }, + atomicSub: { + keyword: `atomicSub`, + src: `_ = atomicSub(&a, 1);` + }, + atomicMax: { + keyword: `atomicMax`, + src: `_ = atomicMax(&a, 1);` + }, + atomicMin: { + keyword: `atomicMin`, + src: `_ = atomicMin(&a, 1);` + }, + atomicAnd: { + keyword: `atomicAnd`, + src: `_ = atomicAnd(&a, 1);` + }, + atomicOr: { + keyword: `atomicOr`, + src: `_ = atomicOr(&a, 1);` + }, + atomicXor: { + keyword: `atomicXor`, + src: `_ = atomicXor(&a, 1);` + } +}; + +g.test('shadow_hides_builtin_atomic'). +desc(`Test that shadows hide builtin atomic methods.`). +params((u) => +u. +combine('inject', ['none', 'function', 'sibling', 'module']). +beginSubcases(). +combine('builtin', keysOf(kAtomicTests)) +). +fn((t) => { + const data = kAtomicTests[t.params.builtin]; + const local = `let ${data.keyword} = 4;`; + + const module_shadow = t.params.inject === 'module' ? `var ${data.keyword} : i32;` : ``; + const sibling_func = t.params.inject === 'sibling' ? local : ``; + const func = t.params.inject === 'function' ? local : ``; + + const code = ` +var a: atomic; + +${module_shadow} + +fn sibling() { + ${sibling_func} +} + +@compute @workgroup_size(1) +fn main() { + ${func} + ${data.src} +} + `; + + const pass = t.params.inject === 'none' || t.params.inject === 'sibling'; + t.expectCompileResult(pass, code); +}); + +const kBarrierTests = { + storageBarrier: { + keyword: `storageBarrier`, + src: `storageBarrier();` + }, + textureBarrier: { + keyword: `textureBarrier`, + src: `textureBarrier();` + }, + workgroupBarrier: { + keyword: `workgroupBarrier`, + src: `workgroupBarrier();` + }, + workgroupUniformLoad: { + keyword: `workgroupUniformLoad`, + src: `_ = workgroupUniformLoad(&u);` + } +}; + +g.test('shadow_hides_builtin_barriers'). +desc(`Test that shadows hide builtin barrier methods.`). +params((u) => +u. +combine('inject', ['none', 'function', 'sibling', 'module']). +beginSubcases(). +combine('builtin', keysOf(kBarrierTests)) +). +fn((t) => { + const data = kBarrierTests[t.params.builtin]; + const local = `let ${data.keyword} = 4;`; + + const module_shadow = t.params.inject === 'module' ? `var ${data.keyword} : i32;` : ``; + const sibling_func = t.params.inject === 'sibling' ? local : ``; + const func = t.params.inject === 'function' ? local : ``; + + const code = ` +var u: u32; + +${module_shadow} + +fn sibling() { + ${sibling_func} +} + +@compute @workgroup_size(1) +fn main() { + ${func} + ${data.src} +} + `; + + const pass = t.params.inject === 'none' || t.params.inject === 'sibling'; + t.expectCompileResult(pass, code); +}); + +const kAccessModeTests = { + read: { + keyword: `read`, + src: `var a: i32;` + }, + read_write: { + keyword: `read_write`, + src: `var a: i32;` + }, + write: { + keyword: `write`, + src: `var t: texture_storage_1d;` + } +}; + +g.test('shadow_hides_access_mode'). +desc(`Test that shadows hide access modes.`). +params((u) => +u. +combine('inject', ['none', 'function', 'module']). +beginSubcases(). +combine('builtin', keysOf(kAccessModeTests)) +). +fn((t) => { + const data = kAccessModeTests[t.params.builtin]; + const local = `let ${data.keyword} = 4;`; + + const module_shadow = t.params.inject === 'module' ? `var ${data.keyword} : i32;` : ``; + const func = t.params.inject === 'function' ? local : ``; + + const code = ` +${module_shadow} + +@group(0) @binding(0) ${data.src} + +@compute @workgroup_size(1) +fn main() { + ${func} +} + `; + + const pass = t.params.inject === 'none' || t.params.inject === 'function'; + t.expectCompileResult(pass, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/statement_behavior.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/statement_behavior.spec.js new file mode 100644 index 0000000000..95407a7d68 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/statement_behavior.spec.js @@ -0,0 +1,143 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Test statement behavior analysis. + +Functions must have a behavior of {Return}, {Next}, or {Return, Next}. +Functions with a return type must have a behavior of {Return}. + +Each statement in the function must be valid according to the table. +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kInvalidStatements = { + break: `break`, + break_if: `break if true`, + continue: `continue`, + loop1: `loop { }`, + loop2: `loop { continuing { } }`, + loop3: `loop { continue; continuing { } }`, + loop4: `loop { continuing { break; } }`, + loop5: `loop { continuing { continue; } }`, + loop6: `loop { continuing { return; } }`, + loop7: `loop { continue; break; }`, + loop8: `loop { continuing { break if true; return; } }`, + for1: `for (;;) { }`, + for2: `for (var i = 0; ; i++) { }`, + for3: `for (;; break) { }`, + for4: `for (;; continue ) { }`, + for5: `for (;; return ) { }`, + for6: `for (;;) { continue; break; }`, + // while loops always have break in their behaviors. + switch1: `switch (1) { case 1 { } }`, + sequence1: `return; loop { }`, + compound1: `{ loop { } }` +}; + +g.test('invalid_statements'). +desc('Test statements with invalid behaviors'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules'). +params((u) => u.combine('body', keysOf(kInvalidStatements))). +fn((t) => { + const body = kInvalidStatements[t.params.body]; + const code = `fn foo() { + ${body}; + }`; + t.expectCompileResult(false, code); +}); + +const kValidStatements = { + empty: ``, + const_assert: `const_assert true`, + let: `let x = 1`, + var1: `var x = 1`, + var2: `var x : i32`, + assign: `v = 1`, + phony_assign: `_ = 1`, + compound_assign: `v += 1`, + return: `return`, + discard: `discard`, + function_call1: `bar()`, + function_call2: `workgroupBarrier()`, + + if1: `if true { } else { }`, + if2: `if true { }`, + + break1: `loop { break; }`, + break2: `loop { if false { break; } }`, + break_if: `loop { continuing { break if false; } }`, + + continue1: `loop { continue; continuing { break if true; } }`, + + loop1: `loop { break; }`, + loop2: `loop { break; continuing { } }`, + loop3: `loop { continue; continuing { break if true; } }`, + loop4: `loop { break; continue; }`, + + for1: `for (; true; ) { }`, + for2: `for (;;) { break; }`, + for3: `for (;true;) { continue; }`, + + while1: `while true { }`, + while2: `while true { continue; }`, + while3: `while true { continue; break; }`, + + switch1: `switch 1 { default { } }`, + swtich2: `switch 1 { case 1 { } default { } }`, + switch3: `switch 1 { default { break; } }`, + switch4: `switch 1 { default { } case 1 { break; } }`, + + sequence1: `return; let x = 1`, + sequence2: `if true { } let x = 1`, + sequence3: `switch 1 { default { break; return; } }`, + + compound1: `{ }`, + compound2: `{ loop { break; } if true { return; } }` +}; + +g.test('valid_statements'). +desc('Test statements with valid behaviors'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules'). +params((u) => u.combine('body', keysOf(kValidStatements))). +fn((t) => { + const body = kValidStatements[t.params.body]; + const code = ` + var v : i32; + fn bar() { } + fn foo() { + ${body}; + }`; + t.expectCompileResult(true, code); +}); + +const kInvalidFunctions = { + next_for_type: `fn foo() -> bool { }`, + next_return_for_type: `fn foo() -> bool { if true { return true; } }` +}; + +g.test('invalid_functions'). +desc('Test functions with invalid behaviors'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules'). +params((u) => u.combine('function', keysOf(kInvalidFunctions))). +fn((t) => { + const func = kInvalidFunctions[t.params.function]; + t.expectCompileResult(false, func); +}); + +const kValidFunctions = { + empty: `fn foo() { }`, + next_return: `fn foo() { if true { return; } }`, + no_final_return: `fn foo() -> bool { if true { return true; } else { return false; } }` +}; + +g.test('valid_functions'). +desc('Test functions with valid behaviors'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules'). +params((u) => u.combine('function', keysOf(kValidFunctions))). +fn((t) => { + const func = kValidFunctions[t.params.function]; + t.expectCompileResult(true, func); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/binding.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/binding.spec.js index d87af51d30..6e287bb6cd 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/binding.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/binding.spec.js @@ -118,20 +118,6 @@ fn((t) => { @group(1) @binding(1h) var a: i32; -@workgroup_size(1, 1, 1) -@compute fn main() { - _ = a; -}`; - t.expectCompileResult(false, code); -}); - -g.test('binding_without_group'). -desc(`Test validation of binding without group`). -fn((t) => { - const code = ` -@binding(1) -var a: i32; - @workgroup_size(1, 1, 1) @compute fn main() { _ = a; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/builtins.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/builtins.spec.js index 07ea75828e..9aa013aa61 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/builtins.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/builtins.spec.js @@ -103,9 +103,9 @@ desc( params((u) => u. combineWithParams(kBuiltins). -combine('use_struct', [true, false]). +beginSubcases(). combine('target_type', kTestTypes). -beginSubcases() +combine('use_struct', [true, false]) ). fn((t) => { let code = ''; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/group.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/group.spec.js index 4c6a691e52..0477ef15f4 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/group.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/group.spec.js @@ -118,20 +118,6 @@ fn((t) => { @group(1h) @binding(1) var a: i32; -@workgroup_size(1, 1, 1) -@compute fn main() { - _ = a; -}`; - t.expectCompileResult(false, code); -}); - -g.test('group_without_binding'). -desc(`Test validation of group without binding`). -fn((t) => { - const code = ` -@group(1) -var a: i32; - @workgroup_size(1, 1, 1) @compute fn main() { _ = a; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/group_and_binding.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/group_and_binding.spec.js index d554700474..b63f33b4cf 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/group_and_binding.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/group_and_binding.spec.js @@ -95,12 +95,12 @@ u. combine('stage', ['vertex', 'fragment', 'compute']). combine('a_kind', kResourceKindsA). combine('b_kind', kResourceKindsB). +combine('usage', ['direct', 'transitive']). +beginSubcases(). combine('a_group', [0, 3]). combine('b_group', [0, 3]). combine('a_binding', [0, 3]). -combine('b_binding', [0, 3]). -combine('usage', ['direct', 'transitive']). -beginSubcases() +combine('b_binding', [0, 3]) ). fn((t) => { const resourceA = kResourceEmitters.get(t.params.a_kind); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/layout_constraints.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/layout_constraints.spec.js new file mode 100644 index 0000000000..1f595f7d23 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/layout_constraints.spec.js @@ -0,0 +1,543 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = `Validation of address space layout constraints`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + + + + + + + + +const kLayoutCases = { + // Scalars + u32: { + type: 'u32', + validity: true + }, + i32: { + type: 'i32', + validity: true + }, + f32: { + type: 'f32', + validity: true + }, + f16: { + type: 'f16', + validity: true, + f16: true + }, + bool: { + type: 'bool', + validity: 'non-interface' + }, + + // Vectors + vec2u: { + type: 'vec2u', + validity: true + }, + vec3u: { + type: 'vec3u', + validity: true + }, + vec4u: { + type: 'vec4u', + validity: true + }, + vec2i: { + type: 'vec2i', + validity: true + }, + vec3i: { + type: 'vec3i', + validity: true + }, + vec4i: { + type: 'vec4i', + validity: true + }, + vec2f: { + type: 'vec2f', + validity: true + }, + vec3f: { + type: 'vec3f', + validity: true + }, + vec4f: { + type: 'vec4f', + validity: true + }, + vec2h: { + type: 'vec2h', + validity: true, + f16: true + }, + vec3h: { + type: 'vec3h', + validity: true, + f16: true + }, + vec4h: { + type: 'vec4h', + validity: true, + f16: true + }, + vec2b: { + type: 'vec2', + validity: 'non-interface' + }, + vec3b: { + type: 'vec3', + validity: 'non-interface' + }, + vec4b: { + type: 'vec4', + validity: 'non-interface' + }, + + // Matrices + mat2x2f: { + type: 'mat2x2f', + validity: true + }, + mat2x3f: { + type: 'mat2x3f', + validity: true + }, + mat2x4f: { + type: 'mat2x4f', + validity: true + }, + mat3x2f: { + type: 'mat3x2f', + validity: true + }, + mat3x3f: { + type: 'mat3x3f', + validity: true + }, + mat3x4f: { + type: 'mat3x4f', + validity: true + }, + mat4x2f: { + type: 'mat4x2f', + validity: true + }, + mat4x3f: { + type: 'mat4x3f', + validity: true + }, + mat4x4f: { + type: 'mat4x4f', + validity: true + }, + mat2x2h: { + type: 'mat2x2h', + validity: true, + f16: true + }, + mat2x3h: { + type: 'mat2x3h', + validity: true, + f16: true + }, + mat2x4h: { + type: 'mat2x4h', + validity: true, + f16: true + }, + mat3x2h: { + type: 'mat3x2h', + validity: true, + f16: true + }, + mat3x3h: { + type: 'mat3x3h', + validity: true, + f16: true + }, + mat3x4h: { + type: 'mat3x4h', + validity: true, + f16: true + }, + mat4x2h: { + type: 'mat4x2h', + validity: true, + f16: true + }, + mat4x3h: { + type: 'mat4x3h', + validity: true, + f16: true + }, + mat4x4h: { + type: 'mat4x4h', + validity: true, + f16: true + }, + + // Atomics + atomic_u32: { + type: 'atomic', + validity: 'atomic' + }, + atomic_i32: { + type: 'atomic', + validity: 'atomic' + }, + + // Sized arrays + array_u32: { + type: 'array', + validity: 'non-uniform' + }, + array_i32: { + type: 'array', + validity: 'non-uniform' + }, + array_f32: { + type: 'array', + validity: 'non-uniform' + }, + array_f16: { + type: 'array', + validity: 'non-uniform', + f16: true + }, + array_bool: { + type: 'array', + validity: 'non-interface' + }, + array_vec2f: { + type: 'array', + validity: 'non-uniform' + }, + array_vec3f: { + type: 'array', + validity: true + }, + array_vec4f: { + type: 'array', + validity: true + }, + array_vec2h: { + type: 'array', + validity: 'non-uniform', + f16: true + }, + array_vec3h: { + type: 'array', + validity: 'non-uniform', + f16: true + }, + array_vec4h: { + type: 'array', + validity: 'non-uniform', + f16: true + }, + array_vec2b: { + type: 'array, 16>', + validity: 'non-interface' + }, + array_vec3b: { + type: 'array, 16>', + validity: 'non-interface' + }, + array_vec4b: { + type: 'array, 16>', + validity: 'non-interface' + }, + array_mat2x2f: { + type: 'array', + validity: true + }, + array_mat2x4f: { + type: 'array', + validity: true + }, + array_mat4x2f: { + type: 'array', + validity: true + }, + array_mat4x4f: { + type: 'array', + validity: true + }, + array_mat2x2h: { + type: 'array', + validity: 'non-uniform', + f16: true + }, + array_mat2x4h: { + type: 'array', + validity: true, + f16: true + }, + array_mat3x2h: { + type: 'array', + validity: 'non-uniform', + f16: true + }, + array_mat4x2h: { + type: 'array', + validity: true, + f16: true + }, + array_mat4x4h: { + type: 'array', + validity: true, + f16: true + }, + array_atomic: { + type: 'array, 16>', + validity: 'atomic' + }, + + // Runtime arrays + runtime_array_u32: { + type: 'array', + validity: 'storage' + }, + runtime_array_i32: { + type: 'array', + validity: 'storage' + }, + runtime_array_f32: { + type: 'array', + validity: 'storage' + }, + runtime_array_f16: { + type: 'array', + validity: 'storage', + f16: true + }, + runtime_array_bool: { + type: 'array', + validity: false + }, + runtime_array_vec2f: { + type: 'array', + validity: 'storage' + }, + runtime_array_vec3f: { + type: 'array', + validity: 'storage' + }, + runtime_array_vec4f: { + type: 'array', + validity: 'storage' + }, + runtime_array_vec2h: { + type: 'array', + validity: 'storage', + f16: true + }, + runtime_array_vec3h: { + type: 'array', + validity: 'storage', + f16: true + }, + runtime_array_vec4h: { + type: 'array', + validity: 'storage', + f16: true + }, + runtime_array_vec2b: { + type: 'array>', + validity: false + }, + runtime_array_vec3b: { + type: 'array>', + validity: false + }, + runtime_array_vec4b: { + type: 'array>', + validity: false + }, + runtime_array_mat2x2f: { + type: 'array', + validity: 'storage' + }, + runtime_array_mat2x4f: { + type: 'array', + validity: 'storage' + }, + runtime_array_mat4x2f: { + type: 'array', + validity: 'storage' + }, + runtime_array_mat4x4f: { + type: 'array', + validity: 'storage' + }, + runtime_array_mat2x2h: { + type: 'array', + validity: 'storage', + f16: true + }, + runtime_array_mat2x4h: { + type: 'array', + validity: 'storage', + f16: true + }, + runtime_array_mat3x2h: { + type: 'array', + validity: 'storage', + f16: true + }, + runtime_array_mat4x2h: { + type: 'array', + validity: 'storage', + f16: true + }, + runtime_array_mat4x4h: { + type: 'array', + validity: 'storage', + f16: true + }, + runtime_array_atomic: { + type: 'array>', + validity: 'storage' + }, + + // Structs (and arrays of structs) + array_struct_u32: { + type: 'array', + decls: 'struct S { x : u32 }', + validity: 'non-uniform' + }, + array_struct_u32_size16: { + type: 'array', + decls: 'struct S { @size(16) x : u32 }', + validity: true + }, + array_struct_vec2f: { + type: 'array', + decls: 'struct S { x : vec2f }', + validity: 'non-uniform' + }, + array_struct_vec2h: { + type: 'array', + decls: 'struct S { x : vec2h }', + validity: 'non-uniform', + f16: true + }, + array_struct_vec2h_align16: { + type: 'array', + decls: 'struct S { @align(16) x : vec2h }', + validity: true, + f16: true + }, + size_too_small: { + type: 'S', + decls: 'struct S { @size(2) x : u32 }', + validity: false + }, + struct_padding: { + type: 'S', + decls: `struct T { x : u32 } + struct S { t : T, x : u32 }`, + validity: 'non-uniform' + }, + struct_array_u32: { + type: 'S', + decls: 'struct S { x : array }', + validity: 'non-uniform' + }, + struct_runtime_array_u32: { + type: 'S', + decls: 'struct S { x : array }', + validity: 'storage' + }, + array_struct_size_5: { + type: 'array', + decls: 'struct S { @size(5) x : u32, y : u32 }', + validity: 'non-uniform' + }, + array_struct_size_5x2: { + type: 'array', + decls: 'struct S { @size(5) x : u32, @size(5) y : u32 }', + validity: true + }, + struct_size_5: { + type: 'S', + decls: `struct T { @size(5) x : u32 } + struct S { x : u32, y : T }`, + validity: 'non-uniform' + }, + struct_size_5_align16: { + type: 'S', + decls: `struct T { @align(16) @size(5) x : u32 } + struct S { x : u32, y : T }`, + validity: true + } +}; + +g.test('layout_constraints'). +desc('Test address space layout constraints'). +params((u) => +u. +combine('case', keysOf(kLayoutCases)). +beginSubcases(). +combine('aspace', ['storage', 'uniform', 'function', 'private', 'workgroup']) +). +beforeAllSubcases((t) => { + const testcase = kLayoutCases[t.params.case]; + if (testcase.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const testcase = kLayoutCases[t.params.case]; + const decls = testcase.decls !== undefined ? testcase.decls : ''; + let code = ` +${testcase.f16 ? 'enable f16;' : ''} +${decls} + +`; + + switch (t.params.aspace) { + case 'storage': + code += `@group(0) @binding(0) var v : ${testcase.type};\n`; + break; + case 'uniform': + code += `@group(0) @binding(0) var v : ${testcase.type};\n`; + break; + case 'workgroup': + code += `var v : ${testcase.type};\n`; + break; + case 'private': + code += `var v : ${testcase.type};\n`; + break; + default: + break; + } + + code += `@compute @workgroup_size(1,1,1) + fn main() { + `; + + if (t.params.aspace === 'function') { + code += `var v : ${testcase.type};\n`; + } + code += `}\n`; + + const is_interface = t.params.aspace === 'uniform' || t.params.aspace === 'storage'; + const supports_atomic = t.params.aspace === 'storage' || t.params.aspace === 'workgroup'; + const expect = + testcase.validity === true || + testcase.validity === 'non-uniform' && t.params.aspace !== 'uniform' || + testcase.validity === 'non-interface' && !is_interface || + testcase.validity === 'storage' && t.params.aspace === 'storage' || + testcase.validity === 'atomic' && supports_atomic; + t.expectCompileResult(expect, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/locations.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/locations.spec.js index 7dd5492283..2d2ae03b74 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/locations.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/locations.spec.js @@ -379,4 +379,153 @@ fn((t) => { return vec4f(); }`; t.expectCompileResult(t.params.ext === '', code); +}); + + + + + + + + + +const kOutOfOrderCases = { + reverse_params: { + params: `@location(2) p1 : f32, @location(1) p2 : f32, @location(0) p3 : f32`, + valid: true + }, + no_zero_params: { + params: `@location(2) p1 : f32, @location(1) p2 : f32`, + valid: true + }, + reverse_overlap: { + params: `@location(2) p1 : f32, @location(1) p2 : f32, @location(1) p3 : f32`, + valid: false + }, + struct: { + params: `p1 : S`, + decls: `struct S { + @location(1) x : f32, + @location(0) y : f32, + }`, + valid: true + }, + struct_override: { + params: `@location(0) p1 : S`, + decls: `struct S { + @location(1) x : f32, + @location(0) y : f32, + }`, + valid: false + }, + struct_random: { + params: `p1 : S, p2 : T`, + decls: `struct S { + @location(16) x : f32, + @location(4) y : f32, + } + struct T { + @location(13) x : f32, + @location(7) y : f32, + }`, + valid: true + }, + struct_random_overlap: { + params: `p1 : S, p2 : T`, + decls: `struct S { + @location(16) x : f32, + @location(4) y : f32, + } + struct T { + @location(13) x : f32, + @location(4) y : f32, + }`, + valid: false + }, + mixed_locations1: { + params: `@location(12) p1 : f32, p2 : S`, + decls: `struct S { + @location(2) x : f32, + }`, + valid: true + }, + mixed_locations2: { + params: `p1 : S, @location(2) p2 : f32`, + decls: `struct S { + @location(12) x : f32, + }`, + valid: true + }, + mixed_overlap: { + params: `p1 : S, @location(12) p2 : f32`, + decls: `struct S { + @location(12) x : f32, + }`, + valid: false + }, + with_param_builtin: { + params: `p : S`, + decls: `struct S { + @location(12) x : f32, + @builtin(position) pos : vec4f, + @location(0) y : f32, + }`, + valid: true + }, + non_zero_return: { + returnType: `@location(1) vec4f`, + returnValue: `vec4f()`, + valid: true + }, + reverse_return: { + returnType: `S`, + returnValue: `S()`, + decls: `struct S { + @location(2) x : f32, + @location(1) y : f32, + @location(0) z : f32, + }`, + valid: true + }, + gap_return: { + returnType: `S`, + returnValue: `S()`, + decls: `struct S { + @location(13) x : f32, + @location(7) y : f32, + @location(2) z : f32, + }`, + valid: true + }, + with_return_builtin: { + returnType: `S`, + returnValue: `S()`, + decls: `struct S { + @location(11) x : f32, + @builtin(frag_depth) d : f32, + @location(10) y : f32, + }`, + valid: true + } +}; + +g.test('out_of_order'). +desc(`Test validation of out of order locations`). +params((u) => u.combine('case', keysOf(kOutOfOrderCases))). +fn((t) => { + const testcase = kOutOfOrderCases[t.params.case]; + const decls = testcase.decls !== undefined ? testcase.decls : ``; + const params = testcase.params !== undefined ? testcase.params : ``; + const returnType = testcase.returnType !== undefined ? `-> ${testcase.returnType}` : ``; + const returnValue = testcase.returnValue !== undefined ? `return ${testcase.returnValue};` : ``; + const code = ` +${decls} + +@fragment +fn main(${params}) ${returnType} { + ${returnValue} +} +`; + + t.expectCompileResult(testcase.valid, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/size.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/size.spec.js index 74caf19e6d..22eecfc399 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/size.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/size.spec.js @@ -103,7 +103,7 @@ const kSizeTests = { }; g.test('size'). -desc(`Test validation of ize`). +desc(`Test validation of size`). params((u) => u.combine('attr', keysOf(kSizeTests))). fn((t) => { const code = ` @@ -209,4 +209,22 @@ fn((t) => { code += '}'; t.expectCompileResult(data.pass, code); +}); + +g.test('size_creation_fixed_footprint'). +desc(`Test that @size is only valid on types that have creation-fixed footprint.`). +params((u) => u.combine('array_size', [', 4', ''])). +fn((t) => { + const code = ` +struct S { + @size(64) a: array, +}; +@group(0) @binding(0) +var a: S; + +@workgroup_size(1) +@compute fn main() { + _ = a.a[0]; +}`; + t.expectCompileResult(t.params.array_size !== '', code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/alias.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/alias.spec.js index 012652df4b..7afdbbbb06 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/alias.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/alias.spec.js @@ -3,6 +3,7 @@ **/export const description = ` Validation tests for type aliases `;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; import { ShaderValidationTest } from '../shader_validation_test.js'; export const g = makeTestGroup(ShaderValidationTest); @@ -120,4 +121,125 @@ struct S { alias T = ${t.params.target}; `; t.expectCompileResult(t.params.target === 'i32', wgsl); +}); + +const kTypes = [ +'bool', +'i32', +'u32', +'f32', +'f16', +'vec2', +'vec3', +'vec4', +'mat2x2', +'mat2x3', +'mat2x4', +'mat3x2', +'mat3x3', +'mat3x4', +'mat4x2', +'mat4x3', +'mat4x4', +'array', +'array', +'array, 8>', +'S', +'T', +'atomic', +'atomic', +'ptr', +'ptr', +'ptr', +'ptr', +'ptr', +'ptr', +'ptr', +'sampler', +'sampler_comparison', +'texture_1d', +'texture_2d', +'texture_2d_array', +'texture_3d', +'texture_cube', +'texture_cube_array', +'texture_multisampled_2d', +'texture_depth_multisampled_2d', +'texture_external', +'texture_storage_1d', +'texture_storage_1d', +'texture_storage_1d', +'texture_storage_1d', +'texture_storage_2d', +'texture_storage_2d_array', +'texture_storage_3d', +'texture_depth_2d', +'texture_depth_2d_array', +'texture_depth_cube', +'texture_depth_cube_array', + +// Pre-declared aliases (spot check) +'vec2f', +'vec3u', +'vec4i', +'mat2x2f', + +// User-defined aliases +'anotherAlias', +'random_alias']; + + +g.test('any_type'). +desc('Test that any type can be aliased'). +params((u) => u.combine('type', kTypes)). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const ty = t.params.type; + t.skipIf( + ty.includes('texture_storage') && + ty.includes('read') && + !t.hasLanguageFeature('readonly_and_readwrite_storage_textures'), + 'Missing language feature' + ); + const enable = ty === 'f16' ? 'enable f16;' : ''; + const code = ` + ${enable} + struct S { x : u32 } + struct T { y : S } + alias anotherAlias = u32; + alias random_alias = i32; + alias myType = ${ty};`; + t.expectCompileResult(true, code); +}); + +const kMatchCases = { + function_param: ` + fn foo(x : u32) { } + fn bar() { + var x : alias_alias_u32; + foo(x); + }`, + constructor: `var v : u32 = alias_u32(1);`, + template_param: `var v : vec2 = vec2();`, + predeclared_alias: `var v : vec2 = vec2u();`, + struct_element: ` + struct S { x : alias_u32 } + const c_u32 = 0u; + const c = S(c_u32);` +}; + +g.test('match_non_alias'). +desc('Test that type checking succeeds using aliased and unaliased type'). +params((u) => u.combine('case', keysOf(kMatchCases))). +fn((t) => { + const testcase = kMatchCases[t.params.case]; + const code = ` + alias alias_u32 = u32; + alias alias_alias_u32 = alias_u32; + ${testcase}`; + t.expectCompileResult(true, code); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/array.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/array.spec.js new file mode 100644 index 0000000000..9fdf1c8d26 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/array.spec.js @@ -0,0 +1,122 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for array types +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidCases = { + // Basic element types. + i32: `alias T = array;`, + u32: `alias T = array;`, + f32: `alias T = array;`, + f16: `enable f16;\nalias T = array;`, + bool: `alias T = array;`, + + // Composite elements + vec2u: `alias T = array;`, + vec3i: `alias T = array;`, + vec4f: `alias T = array;`, + array: `alias T = array>;`, + struct: `struct S { x : u32 }\nalias T = array;`, + mat2x2f: `alias T = array;`, + mat4x4h: `enable f16;\nalias T = array;`, + + // Atomic elements + atomicu: `alias T = array>;`, + atomici: `alias T = array>;`, + + // Count expressions + literal_count: `alias T = array;`, + literali_count: `alias T = array;`, + literalu_count: `alias T = array;`, + const_count: `const x = 8;\nalias T = array;`, + const_expr_count1: `alias T = array;`, + const_expr_count2: `const x = 4;\nalias T = array;`, + override_count: `override x : u32;\nalias T = array;`, + override_expr1: `override x = 2;\nalias T = array;`, + override_expr2: `override x = 1;\nalias T = array;`, + override_zero: `override x = 0;\nalias T = array;`, + override_neg: `override x = -1;\nalias T = array;`, + + // Same array types + same_const_value1: ` + const x = 8; + const y = 8; + var v : array = array();`, + same_const_value2: ` + const x = 8; + var v : array = array();`, + same_const_value3: ` + var v : array = array();`, + same_override: ` + requires unrestricted_pointer_parameters; + override x : u32; + var v : array; + fn bar(p : ptr>) { } + fn foo() { bar(&v); }`, + + // Shadow + shadow: `alias array = vec2f;` +}; + +g.test('valid'). +desc('Valid array type tests'). +params((u) => u.combine('case', keysOf(kValidCases))). +beforeAllSubcases((t) => { + const code = kValidCases[t.params.case]; + if (code.indexOf('f16') >= 0) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const code = kValidCases[t.params.case]; + t.skipIf( + code.indexOf('unrestricted') >= 0 && !t.hasLanguageFeature('unrestricted_pointer_parameters'), + 'Test requires unrestricted_pointer_parameters' + ); + t.expectCompileResult(true, code); +}); + +const kInvalidCases = { + f16_without_enable: `alias T = array;`, + runtime_nested: `alias T = array, 4>;`, + override_nested: ` + override x : u32; + alias T = array, 4>;`, + override_nested_struct: ` + override x : u32; + struct T { x : array }`, + zero_size: `alias T = array;`, + negative_size: `alias T = array;`, + const_zero: `const x = 0;\nalias T = array;`, + const_neg: `const x = 1;\nconst y = 2;\nalias T = array;`, + incompatible_overrides: ` + requires unrestricted_pointer_parameters; + override x = 8; + override y = 8; + var v : array + fn bar(p : ptr>) { } + fn foo() { bar(&v); }` +}; + +g.test('invalid'). +desc('Invalid array type tests'). +params((u) => u.combine('case', keysOf(kInvalidCases))). +beforeAllSubcases((t) => { + const code = kInvalidCases[t.params.case]; + if (code.indexOf('f16') >= 0) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const code = kInvalidCases[t.params.case]; + t.skipIf( + code.indexOf('unrestricted') >= 0 && !t.hasLanguageFeature('unrestricted_pointer_parameters'), + 'Test requires unrestricted_pointer_parameters' + ); + t.expectCompileResult(false, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/atomics.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/atomics.spec.js new file mode 100644 index 0000000000..e16307baa9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/atomics.spec.js @@ -0,0 +1,145 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for atomic types + +Tests covered: +* Base type +* Address spaces +* Invalid operations (non-exhaustive) + +Note: valid operations (e.g. atomic built-in functions) are tested in the builtin tests. +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('type'). +desc('Test of the underlying atomic data type'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#atomic-types'). +params((u) => +u.combine('type', [ +'u32', +'i32', +'f32', +'f16', +'bool', +'vec2u', +'vec3i', +'vec4f', +'mat2x2f', +'R', +'S', +'array', +'array', +'array', +'array', +'atomic', +'atomic'] +) +). +beforeAllSubcases((t) => { + if (t.params.type === 'f16') { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const code = ` +struct S { + x : u32 +} +struct T { + x : i32 +} +struct R { + x : f32 +} + +struct Test { + x : atomic<${t.params.type}> +} +`; + + const expect = t.params.type === 'u32' || t.params.type === 'i32'; + t.expectCompileResult(expect, code); +}); + +g.test('address_space'). +desc('Test allowed address spaces for atomics'). +specURL('https://gpuweb.github.io/gpuweb/wgsl/#atomic-types'). +params((u) => +u. +combine('aspace', [ +'storage', +'workgroup', +'storage-ro', +'uniform', +'private', +'function', +'function-let'] +). +beginSubcases(). +combine('type', ['i32', 'u32']) +). +fn((t) => { + let moduleVar = ``; + let functionVar = ''; + switch (t.params.aspace) { + case 'storage-ro': + moduleVar = `@group(0) @binding(0) var x : atomic<${t.params.type}>;\n`; + break; + case 'storage': + moduleVar = `@group(0) @binding(0) var x : atomic<${t.params.type}>;\n`; + break; + case 'uniform': + moduleVar = `@group(0) @binding(0) var x : atomic<${t.params.type}>;\n`; + break; + case 'workgroup': + case 'private': + moduleVar = `var<${t.params.aspace}> x : atomic<${t.params.type}>;\n`; + break; + case 'function': + functionVar = `var x : atomic<${t.params.type}>;\n`; + break; + case 'function-let': + functionVar = `let x : atomic<${t.params.type}>;\n`; + break; + } + const code = ` +${moduleVar} + +fn foo() { + ${functionVar} +} +`; + + const expect = t.params.aspace === 'storage' || t.params.aspace === 'workgroup'; + t.expectCompileResult(expect, code); +}); + +const kInvalidOperations = { + add: `a1 + a2`, + load: `a1`, + store: `a1 = 1u`, + deref: `*a1 = 1u`, + equality: `a1 == a2`, + abs: `abs(a1)`, + address_abs: `abs(&a1)` +}; + +g.test('invalid_operations'). +desc('Tests that a selection of invalid operations are invalid'). +params((u) => u.combine('op', keysOf(kInvalidOperations))). +fn((t) => { + const code = ` +var a1 : atomic; +var a2 : atomic; + +fn foo() { + let x : u32 = ${kInvalidOperations[t.params.op]}; +} +`; + + t.expectCompileResult(false, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/matrix.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/matrix.spec.js new file mode 100644 index 0000000000..1fde9bdac7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/matrix.spec.js @@ -0,0 +1,152 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for matrix types +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kValidCases = { + // Basic matrices + mat2x2_f32: `alias T = mat2x2;`, + mat2x3_f32: `alias T = mat2x3;`, + mat2x4_f32: `alias T = mat2x4;`, + mat3x2_f32: `alias T = mat3x2;`, + mat3x3_f32: `alias T = mat3x3;`, + mat3x4_f32: `alias T = mat3x4;`, + mat4x2_f32: `alias T = mat4x2;`, + mat4x3_f32: `alias T = mat4x3;`, + mat4x4_f32: `alias T = mat4x4;`, + mat2x2_f16: `enable f16;\nalias T = mat2x2;`, + mat2x3_f16: `enable f16;\nalias T = mat2x3;`, + mat2x4_f16: `enable f16;\nalias T = mat2x4;`, + mat3x2_f16: `enable f16;\nalias T = mat3x2;`, + mat3x3_f16: `enable f16;\nalias T = mat3x3;`, + mat3x4_f16: `enable f16;\nalias T = mat3x4;`, + mat4x2_f16: `enable f16;\nalias T = mat4x2;`, + mat4x3_f16: `enable f16;\nalias T = mat4x3;`, + mat4x4_f16: `enable f16;\nalias T = mat4x4;`, + + // Pre-declared aliases + mat2x2f: `alias T = mat2x2f;`, + mat2x3f: `alias T = mat2x3f;`, + mat2x4f: `alias T = mat2x4f;`, + mat3x2f: `alias T = mat3x2f;`, + mat3x3f: `alias T = mat3x3f;`, + mat3x4f: `alias T = mat3x4f;`, + mat4x2f: `alias T = mat4x2f;`, + mat4x3f: `alias T = mat4x3f;`, + mat4x4f: `alias T = mat4x4f;`, + mat2x2h: `enable f16;\nalias T = mat2x2h;`, + mat2x3h: `enable f16;\nalias T = mat2x3h;`, + mat2x4h: `enable f16;\nalias T = mat2x4h;`, + mat3x2h: `enable f16;\nalias T = mat3x2h;`, + mat3x3h: `enable f16;\nalias T = mat3x3h;`, + mat3x4h: `enable f16;\nalias T = mat3x4h;`, + mat4x2h: `enable f16;\nalias T = mat4x2h;`, + mat4x3h: `enable f16;\nalias T = mat4x3h;`, + mat4x4h: `enable f16;\nalias T = mat4x4h;`, + + trailing_comman: `alias T = mat2x2;`, + + // Abstract matrices + abstract_2x2: `const m = mat2x2(1,1,1,1);`, + abstract_2x3: `const m = mat2x3(1,1,1,1,1,1);`, + abstract_2x4: `const m = mat2x4(1,1,1,1,1,1,1,1);`, + + // Base roots shadowable + shadow_mat2x2: `alias mat2x2 = array;`, + shadow_mat2x3: `alias mat2x3 = array;`, + shadow_mat2x4: `alias mat2x4 = array;`, + shadow_mat3x2: `alias mat3x2 = array;`, + shadow_mat3x3: `alias mat3x3 = array;`, + shadow_mat3x4: `alias mat3x4 = array;`, + shadow_mat4x2: `alias mat4x2 = array;`, + shadow_mat4x3: `alias mat4x3 = array;`, + shadow_mat4x4: `alias mat4x4 = array;`, + + // Pre-declared aliases shadowable + shadow_mat2x2f: `alias mat2x2f = mat2x2;`, + shadow_mat2x3f: `alias mat2x3f = mat2x3;`, + shadow_mat2x4f: `alias mat2x4f = mat2x4;`, + shadow_mat3x2f: `alias mat3x2f = mat3x2;`, + shadow_mat3x3f: `alias mat3x3f = mat3x3;`, + shadow_mat3x4f: `alias mat3x4f = mat3x4;`, + shadow_mat4x2f: `alias mat4x2f = mat4x2;`, + shadow_mat4x3f: `alias mat4x3f = mat4x3;`, + shadow_mat4x4f: `alias mat4x4f = mat4x4;`, + shadow_mat2x2h: `enable f16;\nalias mat2x2h = mat2x2;`, + shadow_mat2x3h: `enable f16;\nalias mat2x3h = mat2x3;`, + shadow_mat2x4h: `enable f16;\nalias mat2x4h = mat2x4;`, + shadow_mat3x2h: `enable f16;\nalias mat3x2h = mat3x2;`, + shadow_mat3x3h: `enable f16;\nalias mat3x3h = mat3x3;`, + shadow_mat3x4h: `enable f16;\nalias mat3x4h = mat3x4;`, + shadow_mat4x2h: `enable f16;\nalias mat4x2h = mat4x2;`, + shadow_mat4x3h: `enable f16;\nalias mat4x3h = mat4x3;`, + shadow_mat4x4h: `enable f16;\nalias mat4x4h = mat4x4;` +}; + +g.test('valid'). +desc('Valid matrix type tests'). +params((u) => u.combine('case', keysOf(kValidCases))). +beforeAllSubcases((t) => { + const code = kValidCases[t.params.case]; + if (code.indexOf('f16') >= 0) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const code = kValidCases[t.params.case]; + t.expectCompileResult(true, code); +}); + +const kInvalidCases = { + // Invalid component types + mat2x2_i32: `alias T = mat2x2;`, + mat3x3_u32: `alias T = mat3x3;`, + mat4x4_bool: `alias T = mat4x4;`, + mat2x2_vec4f: `alias T = mat2x2;`, + mat2x2_array: `alias T = mat2x2>;`, + mat2x2_struct: `struct S { x : f32 }\nalias T = mat2x2;`, + + // Invalid dimensions + mat1x1: `alias T = mat1x1;`, + mat2x1: `alias T = mat2x1;`, + mat2x5: `alias T = mat2x5;`, + mat5x5: `alias T = mat5x5;`, + + // Half-precision aliases require enable + no_enable_mat2x2h: `alias T = mat2x2h;`, + no_enable_mat2x3h: `alias T = mat2x3h;`, + no_enable_mat2x4h: `alias T = mat2x4h;`, + no_enable_mat3x2h: `alias T = mat3x2h;`, + no_enable_mat3x3h: `alias T = mat3x3h;`, + no_enable_mat3x4h: `alias T = mat3x4h;`, + no_enable_mat4x2h: `alias T = mat4x2h;`, + no_enable_mat4x3h: `alias T = mat4x3h;`, + no_enable_mat4x4h: `alias T = mat4x4h;`, + + missing_template: `alias T = mat2x2;`, + missing_left_template: `alias T = mat2x2f32>;`, + missing_right_template: `alias T = mat2x2;`, + mat2x2i: `alias T = mat2x2i;`, + mat2x2u: `alias T = mat2x2u;`, + mat2x2b: `alias T = mat2x2b;` +}; + +g.test('invalid'). +desc('Invalid matrix type tests'). +params((u) => u.combine('case', keysOf(kInvalidCases))). +beforeAllSubcases((t) => { + const code = kInvalidCases[t.params.case]; + if (code.indexOf('f16') >= 0) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } +}). +fn((t) => { + const code = kInvalidCases[t.params.case]; + t.expectCompileResult(false, code); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/textures.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/textures.spec.js new file mode 100644 index 0000000000..64f197615a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/types/textures.spec.js @@ -0,0 +1,170 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = ` +Validation tests for various texture types in shaders. +`;import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { + isTextureFormatUsableAsStorageFormat, + kAllTextureFormats, + kColorTextureFormats, + kTextureFormatInfo } from +'../../../format_info.js'; +import { getPlainTypeInfo } from '../../../util/shader.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +g.test('texel_formats'). +desc( + 'Test channels and channel format of various texel formats when using as the storage texture format' +). +params((u) => +u. +combine('format', kColorTextureFormats). +filter((p) => kTextureFormatInfo[p.format].color.storage). +beginSubcases(). +combine('shaderScalarType', ['f32', 'u32', 'i32', 'bool', 'f16']) +). +beforeAllSubcases((t) => { + if (t.params.shaderScalarType === 'f16') { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); + } + + if (!isTextureFormatUsableAsStorageFormat(t.params.format, t.isCompatibility)) { + t.skip('storage usage is unsupported'); + } +}). +fn((t) => { + const { format, shaderScalarType } = t.params; + const info = kTextureFormatInfo[format]; + const validShaderScalarType = getPlainTypeInfo(info.color.type); + const shaderValueType = `vec4<${shaderScalarType}>`; + const wgsl = ` + @group(0) @binding(0) var tex: texture_storage_2d<${format}, read>; + @compute @workgroup_size(1) fn main() { + let v : ${shaderValueType} = textureLoad(tex, vec2u(0)); + _ = v; + } +`; + t.expectCompileResult(validShaderScalarType === shaderScalarType, wgsl); +}); + +g.test('texel_formats,as_value'). +desc('Test that texel format cannot be used as value'). +fn((t) => { + const wgsl = ` + @compute @workgroup_size(1) fn main() { + var i = rgba8unorm; + } +`; + t.expectCompileResult(false, wgsl); +}); + +const kValidTextureSampledTypes = ['f32', 'i32', 'u32']; + +g.test('sampled_texture_types'). +desc( + `Test that for texture_xx +- The sampled type T must be f32, i32, or u32 +` +). +params((u) => +u. +combine('textureType', ['texture_2d', 'texture_multisampled_2d']). +beginSubcases(). +combine('sampledType', [ +...kValidTextureSampledTypes, +'bool', +'vec2', +'mat2x2', +'1.0', +'1', +'1u'] +) +). +fn((t) => { + const { textureType, sampledType } = t.params; + const wgsl = `@group(0) @binding(0) var tex: ${textureType}<${sampledType}>;`; + t.expectCompileResult(kValidTextureSampledTypes.includes(sampledType), wgsl); +}); + +g.test('external_sampled_texture_types'). +desc( + `Test that texture_extenal compiles and cannot specify address space +` +). +fn((t) => { + t.expectCompileResult(true, `@group(0) @binding(0) var tex: texture_external;`); + t.expectCompileResult(false, `@group(0) @binding(0) var tex: texture_external;`); +}); + +const kAccessModes = ['read', 'write', 'read_write']; + +g.test('storage_texture_types'). +desc( + `Test that for texture_storage_xx +- format must be an enumerant for one of the texel formats for storage textures +- access must be an enumerant for one of the access modes + +Besides, the shader compilation should always pass regardless of whether the format supports the usage indicated by the access or not. +` +). +params((u) => +u.combine('access', [...kAccessModes, 'storage']).combine('format', kAllTextureFormats) +). +fn((t) => { + const { format, access } = t.params; + const info = kTextureFormatInfo[format]; + // bgra8unorm is considered a valid storage format at shader compilation stage + const isFormatValid = + info.color?.storage || + info.depth?.storage || + info.stencil?.storage || + format === 'bgra8unorm'; + const isAccessValid = kAccessModes.includes(access); + const wgsl = `@group(0) @binding(0) var tex: texture_storage_2d<${format}, ${access}>;`; + t.expectCompileResult(isFormatValid && isAccessValid, wgsl); +}); + +g.test('depth_texture_types'). +desc( + `Test that for texture_depth_xx +- must not specify an address space +` +). +params((u) => +u.combine('textureType', [ +'texture_depth_2d', +'texture_depth_2d_array', +'texture_depth_cube', +'texture_depth_cube_array'] +) +). +fn((t) => { + const { textureType } = t.params; + t.expectCompileResult(true, `@group(0) @binding(0) var t: ${textureType};`); + t.expectCompileResult(false, `@group(0) @binding(0) var t: ${textureType};`); + t.expectCompileResult(false, `@group(0) @binding(0) var t: ${textureType};`); +}); + +g.test('sampler_types'). +desc( + `Test that for sampler and sampler_comparison +- cannot specify address space +- cannot be declared in WGSL function scope +` +). +params((u) => u.combine('samplerType', ['sampler', 'sampler_comparison'])). +fn((t) => { + const { samplerType } = t.params; + t.expectCompileResult(true, `@group(0) @binding(0) var s: ${samplerType};`); + t.expectCompileResult(false, `@group(0) @binding(0) var s: ${samplerType};`); + t.expectCompileResult( + false, + ` + @compute @workgroup_size(1) fn main() { + var s: ${samplerType}; + } + ` + ); +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/uniformity/uniformity.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/uniformity/uniformity.spec.js index a656f731f5..a808b17675 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/uniformity/uniformity.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/uniformity/uniformity.spec.js @@ -21,6 +21,7 @@ const kCollectiveOps = [ { op: 'fwidthCoarse', stage: 'fragment' }, { op: 'fwidthFine', stage: 'fragment' }, { op: 'storageBarrier', stage: 'compute' }, +{ op: 'textureBarrier', stage: 'compute' }, { op: 'workgroupBarrier', stage: 'compute' }, { op: 'workgroupUniformLoad', stage: 'compute' }]; @@ -42,7 +43,9 @@ const kConditions = [ { cond: 'nonuniform_and1', expectation: false }, { cond: 'nonuniform_and2', expectation: false }, { cond: 'uniform_func_var', expectation: true }, -{ cond: 'nonuniform_func_var', expectation: false }]; +{ cond: 'nonuniform_func_var', expectation: false }, +{ cond: 'storage_texture_ro', expectation: true }, +{ cond: 'storage_texture_rw', expectation: false }]; function generateCondition(condition) { @@ -98,6 +101,12 @@ function generateCondition(condition) { case 'nonuniform_func_var':{ return `n_f == 0`; } + case 'storage_texture_ro':{ + return `textureLoad(ro_storage_texture, vec2()).x == 0`; + } + case 'storage_texture_rw':{ + return `textureLoad(rw_storage_texture, vec2()).x == 0`; + } default:{ unreachable(`Unhandled condition`); } @@ -116,6 +125,7 @@ function generateOp(op) { return `let x = ${op}(tex_depth, s_comp, vec2(0,0), 0);\n`; } case 'storageBarrier': + case 'textureBarrier': case 'workgroupBarrier':{ return `${op}();\n`; } @@ -181,12 +191,16 @@ g.test('basics'). desc(`Test collective operations in simple uniform or non-uniform control flow.`). params((u) => u. -combineWithParams(kCollectiveOps). -combineWithParams(kConditions). combine('statement', ['if', 'for', 'while', 'switch']). -beginSubcases() +beginSubcases(). +combineWithParams(kConditions). +combineWithParams(kCollectiveOps) ). fn((t) => { + if (t.params.op === 'textureBarrier' || t.params.cond.startsWith('storage_texture')) { + t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); + } + let code = ` @group(0) @binding(0) var s : sampler; @group(0) @binding(1) var s_comp : sampler_comparison; @@ -197,6 +211,9 @@ fn((t) => { @group(1) @binding(1) var rw_buffer : array; @group(1) @binding(2) var uniform_buffer : vec4; + @group(2) @binding(0) var ro_storage_texture : texture_storage_2d; + @group(2) @binding(1) var rw_storage_texture : texture_storage_2d; + var priv_var : array = array(0,0,0,0); const c = false; @@ -367,6 +384,13 @@ function generatePointerCheck(check) { } } + + + + + + + const kPointerCases = { address_uniform_literal: { code: `let ptr = &wg_array[0];`, @@ -584,6 +608,168 @@ const kPointerCases = { let test_val = *p6;`, check: `contents`, uniform: false + }, + contents_lhs_ref_pointer_deref1: { + code: `*&func_scalar = uniform_value; + let test_val = func_scalar;`, + check: `contents`, + uniform: true + }, + contents_lhs_ref_pointer_deref1a: { + code: `*&func_scalar = nonuniform_value; + let test_val = func_scalar;`, + check: `contents`, + uniform: false + }, + contents_lhs_ref_pointer_deref2: { + code: `*&(func_array[nonuniform_value]) = uniform_value; + let test_val = func_array[0];`, + check: `contents`, + uniform: false + }, + contents_lhs_ref_pointer_deref2a: { + code: `(func_array[nonuniform_value]) = uniform_value; + let test_val = func_array[0];`, + check: `contents`, + uniform: false + }, + contents_lhs_ref_pointer_deref3: { + code: `*&(func_array[needs_uniform(uniform_value)]) = uniform_value; + let test_val = func_array[0];`, + check: `contents`, + uniform: true + }, + contents_lhs_ref_pointer_deref3a: { + code: `*&(func_array[needs_uniform(nonuniform_value)]) = uniform_value; + let test_val = func_array[0];`, + check: `contents`, + uniform: 'never' + }, + contents_lhs_ref_pointer_deref4: { + code: `*&((*&(func_struct.x[uniform_value])).x[uniform_value].x[uniform_value]) = uniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: true + }, + contents_lhs_ref_pointer_deref4a: { + code: `*&((*&(func_struct.x[uniform_value])).x[uniform_value].x[uniform_value]) = nonuniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: false + }, + contents_lhs_ref_pointer_deref4b: { + code: `*&((*&(func_struct.x[uniform_value])).x[uniform_value].x[nonuniform_value]) = uniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: false + }, + contents_lhs_ref_pointer_deref4c: { + code: `*&((*&(func_struct.x[uniform_value])).x[nonuniform_value]).x[uniform_value] = uniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: false + }, + contents_lhs_ref_pointer_deref4d: { + code: `*&((*&(func_struct.x[nonuniform_value])).x[uniform_value].x)[uniform_value] = uniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: false + }, + contents_lhs_ref_pointer_deref4e: { + code: `*&((*&(func_struct.x[uniform_value])).x[needs_uniform(nonuniform_value)].x[uniform_value]) = uniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: 'never' + }, + + // The following cases require the 'pointer_composite_access' language feature. + contents_lhs_pointer_deref2: { + code: `(&func_array)[uniform_value] = uniform_value; + let test_val = func_array[0];`, + check: `contents`, + uniform: true, + needs_deref_sugar: true + }, + contents_lhs_pointer_deref2a: { + code: `(&func_array)[nonuniform_value] = uniform_value; + let test_val = func_array[0];`, + check: `contents`, + uniform: false, + needs_deref_sugar: true + }, + contents_lhs_pointer_deref3: { + code: `(&func_array)[needs_uniform(uniform_value)] = uniform_value; + let test_val = func_array[0];`, + check: `contents`, + uniform: true, + needs_deref_sugar: true + }, + contents_lhs_pointer_deref3a: { + code: `(&func_array)[needs_uniform(nonuniform_value)] = uniform_value; + let test_val = func_array[0];`, + check: `contents`, + uniform: 'never', + needs_deref_sugar: true + }, + contents_lhs_pointer_deref4: { + code: `(&((&(func_struct.x[uniform_value])).x[uniform_value]).x)[uniform_value] = uniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: true, + needs_deref_sugar: true + }, + contents_lhs_pointer_deref4a: { + code: `(&((&(func_struct.x[uniform_value])).x[uniform_value]).x)[uniform_value] = nonuniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: false, + needs_deref_sugar: true + }, + contents_lhs_pointer_deref4b: { + code: `(&((&(func_struct.x[uniform_value])).x)[uniform_value]).x[nonuniform_value] = uniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: false, + needs_deref_sugar: true + }, + contents_lhs_pointer_deref4c: { + code: `(&((&(func_struct.x[uniform_value])).x[nonuniform_value]).x)[uniform_value] = uniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: false, + needs_deref_sugar: true + }, + contents_lhs_pointer_deref4d: { + code: `(&((&(func_struct.x[nonuniform_value])).x[uniform_value]).x)[uniform_value] = uniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: false, + needs_deref_sugar: true + }, + contents_lhs_pointer_deref4e: { + code: `(&((&(func_struct.x[uniform_value])).x)[needs_uniform(nonuniform_value)].x[uniform_value]) = uniform_value; + let test_val = func_struct.x[0].x[0].x[0];`, + check: `contents`, + uniform: 'never', + needs_deref_sugar: true + }, + contents_rhs_pointer_deref1: { + code: `let test_val = (&func_array)[uniform_value];`, + check: `contents`, + uniform: true, + needs_deref_sugar: true + }, + contents_rhs_pointer_deref1a: { + code: `let test_val = (&func_array)[nonuniform_value];`, + check: `contents`, + uniform: false, + needs_deref_sugar: true + }, + contents_rhs_pointer_deref2: { + code: `let test_val = (&func_array)[needs_uniform(nonuniform_value)];`, + check: `contents`, + uniform: `never`, + needs_deref_sugar: true } }; @@ -612,6 +798,13 @@ var uniform_value : u32; @group(0) @binding(1) var nonuniform_value : u32; +fn needs_uniform(val : u32) -> u32{ + if val == 0 { + workgroupBarrier(); + } + return val; +} + @compute @workgroup_size(16, 1, 1) fn main(@builtin(local_invocation_id) lid : vec3, @builtin(global_invocation_id) gid : vec3) { @@ -627,11 +820,16 @@ fn main(@builtin(local_invocation_id) lid : vec3, ` ${generatePointerCheck(testcase.check)} }`; - if (!testcase.uniform) { + + if (testcase.needs_deref_sugar === true) { + t.skipIfLanguageFeatureNotSupported('pointer_composite_access'); + } + // Explicitly check false to distinguish from never. + if (testcase.uniform === false) { const without_check = code + `}\n`; t.expectCompileResult(true, without_check); } - t.expectCompileResult(testcase.uniform, with_check); + t.expectCompileResult(testcase.uniform === true, with_check); }); function expectedUniformity(uniform, init) { @@ -2019,6 +2217,7 @@ params((u) => u. combine('e1', keysOf(kExpressionCases)). combine('e2', keysOf(kExpressionCases)). +beginSubcases(). combine('op', keysOf(kBinOps)) ). fn((t) => { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/binary_stream.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/binary_stream.js index cd90821ea4..5e5ff177ff 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/binary_stream.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/binary_stream.js @@ -85,6 +85,16 @@ export default class BinaryStream { return this.view.getInt16(this.alignedOffset(2), /* littleEndian */true); } + /** writeI64() writes a bitint to the buffer at the next 64-bit aligned offset */ + writeI64(value) { + this.view.setBigInt64(this.alignedOffset(8), value, /* littleEndian */true); + } + + /** readI64() reads a bigint from the buffer at the next 64-bit aligned offset */ + readI64() { + return this.view.getBigInt64(this.alignedOffset(8), /* littleEndian */true); + } + /** writeI32() writes a int32 to the buffer at the next 32-bit aligned offset */ writeI32(value) { this.view.setInt32(this.alignedOffset(4), value, /* littleEndian */true); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/check_contents.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/check_contents.js index 645d78de55..f9dfc95549 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/check_contents.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/check_contents.js @@ -43,7 +43,10 @@ actual, expected) { assert(actual.constructor === expected.constructor, 'TypedArray type mismatch'); - assert(actual.length === expected.length, 'size mismatch'); + assert( + actual.length === expected.length, + `length mismatch: expected ${expected.length} got ${actual.length}` + ); let failedElementsFirstMaybe = undefined; /** Sparse array with `true` for elements that failed. */ @@ -221,9 +224,13 @@ function failCheckElements({ const printElementsEnd = Math.min(size, failedElementsLast + 2); const printElementsCount = printElementsEnd - printElementsStart; - const numberToString = printAsFloat ? - (n) => n.toPrecision(4) : - (n) => intToPaddedHex(n, { byteLength: ctor.BYTES_PER_ELEMENT }); + const numericToString = (val) => { + if (typeof val === 'number' && printAsFloat) { + return val.toPrecision(4); + } + return intToPaddedHex(val, { byteLength: ctor.BYTES_PER_ELEMENT }); + }; + const numberPrefix = printAsFloat ? '' : '0x:'; const printActual = actual.subarray(printElementsStart, printElementsEnd); @@ -246,7 +253,7 @@ function failCheckElements({ const opts = { fillToWidth: 120, - numberToString + numericToString }; const msg = `Array had unexpected contents at indices ${failedElementsFirst} through ${failedElementsLast}. Starting at index ${printElementsStart}: @@ -263,10 +270,11 @@ ${generatePrettyTable(opts, [ // Helper helpers /** Convert an integral `number` into a hex string, padded to the specified `byteLength`. */ -function intToPaddedHex(number, { byteLength }) { - assert(Number.isInteger(number), 'number must be integer'); - let s = Math.abs(number).toString(16); - if (byteLength) s = s.padStart(byteLength * 2, '0'); - if (number < 0) s = '-' + s; - return s; +function intToPaddedHex(val, { byteLength }) { + assert(Number.isInteger(val), 'number must be integer'); + const is_negative = typeof val === 'number' ? val < 0 : val < 0n; + let str = (is_negative ? -val : val).toString(16); + if (byteLength) str = str.padStart(byteLength * 2, '0'); + if (is_negative) str = '-' + str; + return str; } \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/color_space_conversion.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/color_space_conversion.js index 7e85d4ed9b..2fdd642bfd 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/color_space_conversion.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/color_space_conversion.js @@ -143,12 +143,7 @@ function XYZ_to_lin_P3(XYZ) { * https://drafts.csswg.org/css-color/#predefined-to-predefined * display-p3 and sRGB share the same white points. */ -export function displayP3ToSrgb(pixel) - - - - -{ +export function displayP3ToSrgb(pixel) { assert( pixel.R !== undefined && pixel.G !== undefined && pixel.B !== undefined, 'color space conversion requires all of R, G and B components' @@ -161,11 +156,7 @@ export function displayP3ToSrgb(pixel) rgbVec = [rgbMatrix[0][0], rgbMatrix[1][0], rgbMatrix[2][0]]; rgbVec = gam_sRGB(rgbVec); - pixel.R = rgbVec[0]; - pixel.G = rgbVec[1]; - pixel.B = rgbVec[2]; - - return pixel; + return { R: rgbVec[0], G: rgbVec[1], B: rgbVec[2], A: pixel.A }; } /** * @returns the converted pixels in `{R: number, G: number, B: number, A: number}`. @@ -174,12 +165,7 @@ export function displayP3ToSrgb(pixel) * https://drafts.csswg.org/css-color/#predefined-to-predefined * display-p3 and sRGB share the same white points. */ -export function srgbToDisplayP3(pixel) - - - - -{ +export function srgbToDisplayP3(pixel) { assert( pixel.R !== undefined && pixel.G !== undefined && pixel.B !== undefined, 'color space conversion requires all of R, G and B components' @@ -192,11 +178,7 @@ export function srgbToDisplayP3(pixel) rgbVec = [rgbMatrix[0][0], rgbMatrix[1][0], rgbMatrix[2][0]]; rgbVec = gam_P3(rgbVec); - pixel.R = rgbVec[0]; - pixel.G = rgbVec[1]; - pixel.B = rgbVec[2]; - - return pixel; + return { R: rgbVec[0], G: rgbVec[1], B: rgbVec[2], A: pixel.A }; } @@ -206,6 +188,7 @@ export function srgbToDisplayP3(pixel) + /** * Returns a function which applies the specified colorspace/premultiplication conversion. * Does not clamp, so may return values outside of the `dstColorSpace` gamut, due to either @@ -247,9 +230,10 @@ export function makeInPlaceColorConversion({ // This technically represents colors outside the src gamut, so no clamping yet. if (requireColorSpaceConversion) { - // WebGPU currently only supports dstColorSpace = 'srgb'. if (srcColorSpace === 'display-p3' && dstColorSpace === 'srgb') { - rgba = displayP3ToSrgb(rgba); + Object.assign(rgba, displayP3ToSrgb(rgba)); + } else if (srcColorSpace === 'srgb' && dstColorSpace === 'display-p3') { + Object.assign(rgba, srgbToDisplayP3(rgba)); } else { unreachable(); } diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/compare.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/compare.js index af42e341c4..2b2cd9a751 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/compare.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/compare.js @@ -5,10 +5,18 @@ import { deserializeExpectation, serializeExpectation } from '../shader/execution/expression/case_cache.js'; -import { toComparator } from '../shader/execution/expression/expression.js'; +import { toComparator } from '../shader/execution/expression/expectation.js'; -import { isFloatValue, Matrix, Scalar, Vector } from './conversion.js'; +import { + ArrayValue, + isFloatValue, + isScalarValue, + MatrixValue, + + + VectorValue } from +'./conversion.js'; import { FPInterval } from './floating_point.js'; /** Comparison describes the result of a Comparator function. */ @@ -98,7 +106,7 @@ function compareValue(got, expected) { } } - if (got instanceof Scalar) { + if (isScalarValue(got)) { const g = got; const e = expected; const isFloat = g.type.kind === 'f64' || g.type.kind === 'f32' || g.type.kind === 'f16'; @@ -111,7 +119,7 @@ function compareValue(got, expected) { }; } - if (got instanceof Vector) { + if (got instanceof VectorValue || got instanceof ArrayValue) { const e = expected; const gLen = got.elements.length; const eLen = e.elements.length; @@ -130,7 +138,7 @@ function compareValue(got, expected) { }; } - if (got instanceof Matrix) { + if (got instanceof MatrixValue) { const e = expected; const gCols = got.type.cols; const eCols = e.type.cols; @@ -153,7 +161,7 @@ function compareValue(got, expected) { }; } - throw new Error(`unhandled type '${typeof got}`); + throw new Error(`unhandled type '${typeof got}'`); } /** @@ -175,7 +183,7 @@ function compareInterval(got, expected) { } } - if (got instanceof Scalar) { + if (isScalarValue(got)) { const g = got.value; const matched = expected.contains(g); return { @@ -197,7 +205,7 @@ function compareInterval(got, expected) { */ function compareVector(got, expected) { // Check got type - if (!(got instanceof Vector)) { + if (!(got instanceof VectorValue)) { return { matched: false, got: `${Colors.red((typeof got).toString())}(${got})`, @@ -262,7 +270,7 @@ function convertArrayToString(m) { */ function compareMatrix(got, expected) { // Check got type - if (!(got instanceof Matrix)) { + if (!(got instanceof MatrixValue)) { return { matched: false, got: `${Colors.red((typeof got).toString())}(${got})`, diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/constants.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/constants.js index b46a2b178b..332958cb24 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/constants.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/constants.js @@ -242,6 +242,21 @@ export const kBit = { }; export const kValue = { + // Limits of i64 + i64: { + positive: { + min: BigInt(0n), + max: BigInt(9223372036854775807n) + }, + negative: { + min: BigInt(-9223372036854775808n), + max: BigInt(0n) + }, + isOOB: (val) => { + return val > kValue.i64.positive.max || val < kValue.i64.negative.min; + } + }, + // Limits of i32 i32: { positive: { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/conversion.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/conversion.js index a56c09b3b7..528730dc79 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/conversion.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/conversion.js @@ -6,6 +6,7 @@ import { Float16Array } from '../../external/petamoriken/float16/float16.js'; import { kBit } from './constants.js'; import { + align, cartesianProduct, clamp, correctlyRoundedF16, @@ -84,6 +85,8 @@ const workingDataI16 = new Int16Array(workingData); const workingDataI32 = new Int32Array(workingData); const workingDataI8 = new Int8Array(workingData); const workingDataF64 = new Float64Array(workingData); +const workingDataI64 = new BigInt64Array(workingData); +const workingDataU64 = new BigUint64Array(workingData); const workingDataView = new DataView(workingData); /** @@ -107,7 +110,7 @@ bias) assert(mantissaBits <= 23); if (Number.isNaN(n)) { - // NaN = all exponent bits true, 1 or more mantissia bits true + // NaN = all exponent bits true, 1 or more mantissa bits true return (1 << exponentBits) - 1 << mantissaBits | (1 << mantissaBits) - 1; } @@ -589,15 +592,23 @@ export function float16ToInt16(f16) { + /** ScalarType describes the type of WGSL Scalar. */ export class ScalarType { // The named type // In bytes + // reads a scalar from a buffer - constructor(kind, size, read) { + constructor( + kind, + size, + signed, + read) + { this.kind = kind; this._size = size; + this._signed = signed; this.read = read; } @@ -609,32 +620,64 @@ export class ScalarType { return this._size; } - /** Constructs a Scalar of this type with `value` */ + get alignment() { + return this._size; + } + + get signed() { + return this._signed; + } + + // This allows width to be checked in cases where scalar and vector types are mixed. + get width() { + return 1; + } + + requiresF16() { + return this.kind === 'f16'; + } + + /** Constructs a ScalarValue of this type with `value` */ create(value) { - switch (this.kind) { - case 'abstract-float': - return abstractFloat(value); - case 'f64': - return f64(value); - case 'f32': - return f32(value); - case 'f16': - return f16(value); - case 'u32': - return u32(value); - case 'u16': - return u16(value); - case 'u8': - return u8(value); - case 'i32': - return i32(value); - case 'i16': - return i16(value); - case 'i8': - return i8(value); - case 'bool': - return bool(value !== 0); + switch (typeof value) { + case 'number': + switch (this.kind) { + case 'abstract-float': + return abstractFloat(value); + case 'abstract-int': + return abstractInt(BigInt(value)); + case 'f64': + return f64(value); + case 'f32': + return f32(value); + case 'f16': + return f16(value); + case 'u32': + return u32(value); + case 'u16': + return u16(value); + case 'u8': + return u8(value); + case 'i32': + return i32(value); + case 'i16': + return i16(value); + case 'i8': + return i8(value); + case 'bool': + return bool(value !== 0); + } + break; + case 'bigint': + switch (this.kind) { + case 'abstract-int': + return abstractInt(value); + case 'bool': + return bool(value !== 0n); + } + break; } + unreachable(`Scalar<${this.kind}>.create() does not support ${typeof value}`); } } @@ -643,6 +686,20 @@ export class VectorType { // Number of elements in the vector // Element type + // Maps a string representation of a vector type to vector type. + static instances = new Map(); + + static create(width, elementType) { + const key = `${elementType.toString()} ${width}}`; + let ty = this.instances.get(key); + if (ty !== undefined) { + return ty; + } + ty = new VectorType(width, elementType); + this.instances.set(key, ty); + return ty; + } + constructor(width, elementType) { this.width = width; this.elementType = elementType; @@ -658,7 +715,7 @@ export class VectorType { elements[i] = this.elementType.read(buf, offset); offset += this.elementType.size; } - return new Vector(elements); + return new VectorValue(elements); } toString() { @@ -669,6 +726,14 @@ export class VectorType { return this.elementType.size * this.width; } + get alignment() { + return VectorType.alignmentOf(this.width, this.elementType); + } + + static alignmentOf(width, elementType) { + return elementType.size * (width === 3 ? 4 : width); + } + /** Constructs a Vector of this type with the given values */ create(value) { if (value instanceof Array) { @@ -676,22 +741,12 @@ export class VectorType { } else { value = Array(this.width).fill(value); } - return new Vector(value.map((v) => this.elementType.create(v))); + return new VectorValue(value.map((v) => this.elementType.create(v))); } -} -// Maps a string representation of a vector type to vector type. -const vectorTypes = new Map(); - -export function TypeVec(width, elementType) { - const key = `${elementType.toString()} ${width}}`; - let ty = vectorTypes.get(key); - if (ty !== undefined) { - return ty; + requiresF16() { + return this.elementType.requiresF16(); } - ty = new VectorType(width, elementType); - vectorTypes.set(key, ty); - return ty; } /** MatrixType describes the type of WGSL Matrix. */ @@ -700,6 +755,20 @@ export class MatrixType { // Number of elements per column in the Matrix // Element type + // Maps a string representation of a Matrix type to Matrix type. + static instances = new Map(); + + static create(cols, rows, elementType) { + const key = `${elementType.toString()} ${cols} ${rows}`; + let ty = this.instances.get(key); + if (ty !== undefined) { + return ty; + } + ty = new MatrixType(cols, rows, elementType); + this.instances.set(key, ty); + return ty; + } + constructor(cols, rows, elementType) { this.cols = cols; this.rows = rows; @@ -729,100 +798,265 @@ export class MatrixType { offset += this.elementType.size; } } - return new Matrix(elements); + return new MatrixValue(elements); } toString() { return `mat${this.cols}x${this.rows}<${this.elementType}>`; } + + get size() { + return VectorType.alignmentOf(this.rows, this.elementType) * this.cols; + } + + get alignment() { + return VectorType.alignmentOf(this.rows, this.elementType); + } + + requiresF16() { + return this.elementType.requiresF16(); + } + + /** Constructs a Matrix of this type with the given values */ + create(value) { + if (value instanceof Array) { + assert(value.length === this.cols * this.rows); + } else { + value = Array(this.cols * this.rows).fill(value); + } + const columns = []; + for (let i = 0; i < this.cols; i++) { + const start = i * this.rows; + columns.push(value.slice(start, start + this.rows)); + } + return new MatrixValue(columns.map((c) => c.map((v) => this.elementType.create(v)))); + } } -// Maps a string representation of a Matrix type to Matrix type. -const matrixTypes = new Map(); +/** ArrayType describes the type of WGSL Array. */ +export class ArrayType { + // Number of elements in the array. Zero represents a runtime-sized array. + // Element type + + // Maps a string representation of a array type to array type. + static instances = new Map(); -export function TypeMat(cols, rows, elementType) { - const key = `${elementType.toString()} ${cols} ${rows}`; - let ty = matrixTypes.get(key); - if (ty !== undefined) { + static create(count, elementType) { + const key = `${elementType.toString()} ${count}`; + let ty = this.instances.get(key); + if (ty !== undefined) { + return ty; + } + ty = new ArrayType(count, elementType); + this.instances.set(key, ty); return ty; } - ty = new MatrixType(cols, rows, elementType); - matrixTypes.set(key, ty); - return ty; + + constructor(count, elementType) { + this.count = count; + this.elementType = elementType; + } + + /** + * @returns a array constructed from the values read from the buffer at the + * given byte offset + */ + read(buf, offset) { + const elements = []; + + for (let i = 0; i < this.count; i++) { + elements[i] = this.elementType.read(buf, offset); + offset += this.stride; + } + return new ArrayValue(elements); + } + + toString() { + return this.count !== 0 ? + `array<${this.elementType}, ${this.count}>` : + `array<${this.elementType}>`; + } + + get stride() { + return align(this.elementType.size, this.elementType.alignment); + } + + get size() { + return this.stride * this.count; + } + + get alignment() { + return this.elementType.alignment; + } + + requiresF16() { + return this.elementType.requiresF16(); + } + + /** Constructs an Array of this type with the given values */ + create(value) { + if (value instanceof Array) { + assert(value.length === this.count); + } else { + value = Array(this.count).fill(value); + } + return new ArrayValue(value.map((v) => this.elementType.create(v))); + } } -/** Type is a ScalarType, VectorType, or MatrixType. */ +/** ArrayElementType infers the element type of the indexable type A */ /** Copy bytes from `buf` at `offset` into the working data, then read it out using `workingDataOut` */ -function valueFromBytes(workingDataOut, buf, offset) { +function valueFromBytes( +workingDataOut, +buf, +offset) +{ for (let i = 0; i < workingDataOut.BYTES_PER_ELEMENT; ++i) { workingDataU8[i] = buf[offset + i]; } return workingDataOut[0]; } -export const TypeI32 = new ScalarType('i32', 4, (buf, offset) => +const abstractIntType = new ScalarType('abstract-int', 8, true, (buf, offset) => +abstractInt(valueFromBytes(workingDataI64, buf, offset)) +); +const i32Type = new ScalarType('i32', 4, true, (buf, offset) => i32(valueFromBytes(workingDataI32, buf, offset)) ); -export const TypeU32 = new ScalarType('u32', 4, (buf, offset) => +const u32Type = new ScalarType('u32', 4, false, (buf, offset) => u32(valueFromBytes(workingDataU32, buf, offset)) ); -export const TypeAbstractFloat = new ScalarType( +const i16Type = new ScalarType('i16', 2, true, (buf, offset) => +i16(valueFromBytes(workingDataI16, buf, offset)) +); +const u16Type = new ScalarType('u16', 2, false, (buf, offset) => +u16(valueFromBytes(workingDataU16, buf, offset)) +); +const i8Type = new ScalarType('i8', 1, true, (buf, offset) => +i8(valueFromBytes(workingDataI8, buf, offset)) +); +const u8Type = new ScalarType('u8', 1, false, (buf, offset) => +u8(valueFromBytes(workingDataU8, buf, offset)) +); +const abstractFloatType = new ScalarType( 'abstract-float', 8, + true, (buf, offset) => abstractFloat(valueFromBytes(workingDataF64, buf, offset)) ); -export const TypeF64 = new ScalarType('f64', 8, (buf, offset) => +const f64Type = new ScalarType('f64', 8, true, (buf, offset) => f64(valueFromBytes(workingDataF64, buf, offset)) ); -export const TypeF32 = new ScalarType('f32', 4, (buf, offset) => +const f32Type = new ScalarType('f32', 4, true, (buf, offset) => f32(valueFromBytes(workingDataF32, buf, offset)) ); -export const TypeI16 = new ScalarType('i16', 2, (buf, offset) => -i16(valueFromBytes(workingDataI16, buf, offset)) -); -export const TypeU16 = new ScalarType('u16', 2, (buf, offset) => -u16(valueFromBytes(workingDataU16, buf, offset)) -); -export const TypeF16 = new ScalarType('f16', 2, (buf, offset) => +const f16Type = new ScalarType('f16', 2, true, (buf, offset) => f16Bits(valueFromBytes(workingDataU16, buf, offset)) ); -export const TypeI8 = new ScalarType('i8', 1, (buf, offset) => -i8(valueFromBytes(workingDataI8, buf, offset)) -); -export const TypeU8 = new ScalarType('u8', 1, (buf, offset) => -u8(valueFromBytes(workingDataU8, buf, offset)) -); -export const TypeBool = new ScalarType('bool', 4, (buf, offset) => +const boolType = new ScalarType('bool', 4, false, (buf, offset) => bool(valueFromBytes(workingDataU32, buf, offset) !== 0) ); +/** Type is a ScalarType, VectorType, MatrixType or ArrayType. */ + + +/** Type holds pre-declared Types along with helper constructor functions. */ +export const Type = { + abstractInt: abstractIntType, + 'abstract-int': abstractIntType, + i32: i32Type, + u32: u32Type, + i16: i16Type, + u16: u16Type, + i8: i8Type, + u8: u8Type, + + abstractFloat: abstractFloatType, + 'abstract-float': abstractFloatType, + f64: f64Type, + f32: f32Type, + f16: f16Type, + + bool: boolType, + + vec: (width, elementType) => VectorType.create(width, elementType), + + vec2ai: VectorType.create(2, abstractIntType), + vec2i: VectorType.create(2, i32Type), + vec2u: VectorType.create(2, u32Type), + vec2af: VectorType.create(2, abstractFloatType), + vec2f: VectorType.create(2, f32Type), + vec2h: VectorType.create(2, f16Type), + vec2b: VectorType.create(2, boolType), + vec3ai: VectorType.create(3, abstractIntType), + vec3i: VectorType.create(3, i32Type), + vec3u: VectorType.create(3, u32Type), + vec3af: VectorType.create(3, abstractFloatType), + vec3f: VectorType.create(3, f32Type), + vec3h: VectorType.create(3, f16Type), + vec3b: VectorType.create(3, boolType), + vec4ai: VectorType.create(4, abstractIntType), + vec4i: VectorType.create(4, i32Type), + vec4u: VectorType.create(4, u32Type), + vec4af: VectorType.create(4, abstractFloatType), + vec4f: VectorType.create(4, f32Type), + vec4h: VectorType.create(4, f16Type), + vec4b: VectorType.create(4, boolType), + + mat: (cols, rows, elementType) => + MatrixType.create(cols, rows, elementType), + + mat2x2f: MatrixType.create(2, 2, f32Type), + mat2x2h: MatrixType.create(2, 2, f16Type), + mat3x2f: MatrixType.create(3, 2, f32Type), + mat3x2h: MatrixType.create(3, 2, f16Type), + mat4x2f: MatrixType.create(4, 2, f32Type), + mat4x2h: MatrixType.create(4, 2, f16Type), + mat2x3f: MatrixType.create(2, 3, f32Type), + mat2x3h: MatrixType.create(2, 3, f16Type), + mat3x3f: MatrixType.create(3, 3, f32Type), + mat3x3h: MatrixType.create(3, 3, f16Type), + mat4x3f: MatrixType.create(4, 3, f32Type), + mat4x3h: MatrixType.create(4, 3, f16Type), + mat2x4f: MatrixType.create(2, 4, f32Type), + mat2x4h: MatrixType.create(2, 4, f16Type), + mat3x4f: MatrixType.create(3, 4, f32Type), + mat3x4h: MatrixType.create(3, 4, f16Type), + mat4x4f: MatrixType.create(4, 4, f32Type), + mat4x4h: MatrixType.create(4, 4, f16Type), + + array: (count, elementType) => ArrayType.create(count, elementType) +}; + /** @returns the ScalarType from the ScalarKind */ export function scalarType(kind) { switch (kind) { case 'abstract-float': - return TypeAbstractFloat; + return Type.abstractFloat; case 'f64': - return TypeF64; + return Type.f64; case 'f32': - return TypeF32; + return Type.f32; case 'f16': - return TypeF16; + return Type.f16; case 'u32': - return TypeU32; + return Type.u32; case 'u16': - return TypeU16; + return Type.u16; case 'u8': - return TypeU8; + return Type.u8; + case 'abstract-int': + return Type.abstractInt; case 'i32': - return TypeI32; + return Type.i32; case 'i16': - return TypeI16; + return Type.i16; case 'i8': - return TypeI8; + return Type.i8; case 'bool': - return TypeBool; + return Type.bool; } } @@ -837,55 +1071,540 @@ export function numElementsOf(ty) { if (ty instanceof MatrixType) { return ty.cols * ty.rows; } + if (ty instanceof ArrayType) { + return ty.count; + } throw new Error(`unhandled type ${ty}`); } /** @returns the scalar elements of the given Value */ export function elementsOf(value) { - if (value instanceof Scalar) { + if (isScalarValue(value)) { + return [value]; + } + if (value instanceof VectorValue) { + return value.elements; + } + if (value instanceof MatrixValue) { + return value.elements.flat(); + } + if (value instanceof ArrayValue) { + return value.elements; + } + throw new Error(`unhandled value ${value}`); +} + +/** @returns the scalar elements of the given Value */ +export function scalarElementsOf(value) { + if (isScalarValue(value)) { return [value]; } - if (value instanceof Vector) { + if (value instanceof VectorValue) { return value.elements; } - if (value instanceof Matrix) { + if (value instanceof MatrixValue) { return value.elements.flat(); } - throw new Error(`unhandled value ${value}`); -} + if (value instanceof ArrayValue) { + return value.elements.map((els) => scalarElementsOf(els)).flat(); + } + throw new Error(`unhandled value ${value}`); +} + +/** @returns the inner element type of the given type */ +export function elementTypeOf(t) { + if (t instanceof ScalarType) { + return t; + } + return t.elementType; +} + +/** @returns the scalar (element) type of the given Type */ +export function scalarTypeOf(ty) { + if (ty instanceof ScalarType) { + return ty; + } + if (ty instanceof VectorType) { + return ty.elementType; + } + if (ty instanceof MatrixType) { + return ty.elementType; + } + if (ty instanceof ArrayType) { + return scalarTypeOf(ty.elementType); + } + throw new Error(`unhandled type ${ty}`); +} + +/** + * @returns the implicit concretized type of the given Type. + * @param abstractIntToF32 if true, returns f32 for abstractInt else i32 + * Example: vec3 -> vec3 + */ +export function concreteTypeOf(ty, allowedScalarTypes) { + if (allowedScalarTypes && allowedScalarTypes.length > 0) { + // https://www.w3.org/TR/WGSL/#conversion-rank + switch (ty) { + case Type.abstractInt: + if (allowedScalarTypes.includes(Type.i32)) { + return Type.i32; + } + if (allowedScalarTypes.includes(Type.u32)) { + return Type.u32; + } + // fallthrough. + case Type.abstractFloat: + if (allowedScalarTypes.includes(Type.f32)) { + return Type.f32; + } + if (allowedScalarTypes.includes(Type.f16)) { + return Type.f32; + } + throw new Error(`no ${ty}`); + } + } else { + switch (ty) { + case Type.abstractInt: + return Type.i32; + case Type.abstractFloat: + return Type.f32; + } + } + if (ty instanceof ScalarType) { + return ty; + } + if (ty instanceof VectorType) { + return Type.vec(ty.width, concreteTypeOf(ty.elementType, allowedScalarTypes)); + } + if (ty instanceof MatrixType) { + return Type.mat( + ty.cols, + ty.rows, + concreteTypeOf(ty.elementType, allowedScalarTypes) + ); + } + if (ty instanceof ArrayType) { + return Type.array(ty.count, concreteTypeOf(ty.elementType, allowedScalarTypes)); + } + throw new Error(`unhandled type ${ty}`); +} + +function hex(sizeInBytes, bitsLow, bitsHigh) { + let hex = ''; + workingDataU32[0] = bitsLow; + if (bitsHigh !== undefined) { + workingDataU32[1] = bitsHigh; + } + for (let i = 0; i < sizeInBytes; ++i) { + hex = workingDataU8[i].toString(16).padStart(2, '0') + hex; + } + return `0x${hex}`; +} + +function withPoint(x) { + const str = `${x}`; + return str.indexOf('.') > 0 || str.indexOf('e') > 0 ? str : `${str}.0`; +} + +/** Class that encapsulates a single abstract-int value. */ +export class AbstractIntValue { + // The abstract-integer value + // The low 32 bits of the abstract-integer value. + // The high 32 bits of the abstract-integer value. + type = Type.abstractInt; // The type of the value. + + constructor(value, bitsLow, bitsHigh) { + this.value = value; + this.bitsLow = bitsLow; + this.bitsHigh = bitsHigh; + } + + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + workingDataU32[0] = this.bitsLow; + workingDataU32[1] = this.bitsHigh; + for (let i = 0; i < 8; i++) { + buffer[offset + i] = workingDataU8[i]; + } + } + + /** @returns the WGSL representation of this scalar value */ + wgsl() { + // WGSL parses negative numbers as a negated positive. + // This means '-9223372036854775808' parses as `-' & '9223372036854775808', so must be written as + // '(-9223372036854775807 - 1)' in WGSL, because '9223372036854775808' is not a valid AbstractInt. + if (this.value === -9223372036854775808n) { + return `(-9223372036854775807 - 1)`; + } + return `${this.value}`; + } + + toString() { + return `${Colors.bold(this.value.toString())} (${hex(8, this.bitsLow, this.bitsHigh)})`; + } +} + +/** Class that encapsulates a single abstract-float value. */ +export class AbstractFloatValue { + // The f32 value + // The low 32 bits of the abstract-float value. + // The high 32 bits of the abstract-float value. + type = Type.abstractFloat; // The type of the value. + + constructor(value, bitsLow, bitsHigh) { + this.value = value; + this.bitsLow = bitsLow; + this.bitsHigh = bitsHigh; + } + + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + workingDataU32[0] = this.bitsLow; + workingDataU32[1] = this.bitsHigh; + for (let i = 0; i < 8; i++) { + buffer[offset + i] = workingDataU8[i]; + } + } + + /** @returns the WGSL representation of this scalar value */ + wgsl() { + return `${withPoint(this.value)}`; + } + + toString() { + switch (this.value) { + case Infinity: + case -Infinity: + return Colors.bold(this.value.toString()); + default:{ + let str = this.value.toString(); + str = str.indexOf('.') > 0 || str.indexOf('e') > 0 ? str : `${str}.0`; + return isSubnormalNumberF64(this.value.valueOf()) ? + `${Colors.bold(str)} (${hex(8, this.bitsLow, this.bitsHigh)} subnormal)` : + `${Colors.bold(str)} (${hex(8, this.bitsLow, this.bitsHigh)})`; + } + } + } +} + +/** Class that encapsulates a single i32 value. */ +export class I32Value { + // The i32 value + // The i32 value, bitcast to a 32-bit integer. + type = Type.i32; // The type of the value. + + constructor(value, bits) { + this.value = value; + this.bits = bits; + } + + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + workingDataU32[0] = this.bits; + for (let i = 0; i < 4; i++) { + buffer[offset + i] = workingDataU8[i]; + } + } + + /** @returns the WGSL representation of this scalar value */ + wgsl() { + return `i32(${this.value})`; + } + + toString() { + return `${Colors.bold(this.value.toString())} (${hex(4, this.bits)})`; + } +} + +/** Class that encapsulates a single u32 value. */ +export class U32Value { + // The u32 value + type = Type.u32; // The type of the value. + + constructor(value) { + this.value = value; + } + + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + workingDataU32[0] = this.value; + for (let i = 0; i < 4; i++) { + buffer[offset + i] = workingDataU8[i]; + } + } + + /** @returns the WGSL representation of this scalar value */ + wgsl() { + return `${this.value}u`; + } + + toString() { + return `${Colors.bold(this.value.toString())} (${hex(4, this.value)})`; + } +} + +/** + * Class that encapsulates a single i16 value. + * @note type does not exist in WGSL yet + */ +export class I16Value { + // The i16 value + // The i16 value, bitcast to a 16-bit integer. + type = Type.i16; // The type of the value. + + constructor(value, bits) { + this.value = value; + this.bits = bits; + } + + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + workingDataU16[0] = this.bits; + for (let i = 0; i < 4; i++) { + buffer[offset + i] = workingDataU8[i]; + } + } + + /** @returns the WGSL representation of this scalar value */ + wgsl() { + return `i16(${this.value})`; + } + + toString() { + return `${Colors.bold(this.value.toString())} (${hex(2, this.bits)})`; + } +} + +/** + * Class that encapsulates a single u16 value. + * @note type does not exist in WGSL yet + */ +export class U16Value { + // The u16 value + type = Type.u16; // The type of the value. + + constructor(value) { + this.value = value; + } + + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + workingDataU16[0] = this.value; + for (let i = 0; i < 2; i++) { + buffer[offset + i] = workingDataU8[i]; + } + } + + /** @returns the WGSL representation of this scalar value */ + wgsl() { + assert(false, 'u16 is not a WGSL type'); + return `u16(${this.value})`; + } + + toString() { + return `${Colors.bold(this.value.toString())} (${hex(2, this.value)})`; + } +} + +/** + * Class that encapsulates a single i8 value. + * @note type does not exist in WGSL yet + */ +export class I8Value { + // The i8 value + // The i8 value, bitcast to a 8-bit integer. + type = Type.i8; // The type of the value. + + constructor(value, bits) { + this.value = value; + this.bits = bits; + } + + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + workingDataU8[0] = this.bits; + for (let i = 0; i < 4; i++) { + buffer[offset + i] = workingDataU8[i]; + } + } + + /** @returns the WGSL representation of this scalar value */ + wgsl() { + return `i8(${this.value})`; + } + + toString() { + return `${Colors.bold(this.value.toString())} (${hex(2, this.bits)})`; + } +} + +/** + * Class that encapsulates a single u8 value. + * @note type does not exist in WGSL yet + */ +export class U8Value { + // The u8 value + type = Type.u8; // The type of the value. + + constructor(value) { + this.value = value; + } + + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + workingDataU8[0] = this.value; + for (let i = 0; i < 2; i++) { + buffer[offset + i] = workingDataU8[i]; + } + } + + /** @returns the WGSL representation of this scalar value */ + wgsl() { + assert(false, 'u8 is not a WGSL type'); + return `u8(${this.value})`; + } + + toString() { + return `${Colors.bold(this.value.toString())} (${hex(2, this.value)})`; + } +} + +/** + * Class that encapsulates a single f64 value + * @note type does not exist in WGSL yet + */ +export class F64Value { + // The f32 value + // The low 32 bits of the abstract-float value. + // The high 32 bits of the abstract-float value. + type = Type.f64; // The type of the value. + + constructor(value, bitsLow, bitsHigh) { + this.value = value; + this.bitsLow = bitsLow; + this.bitsHigh = bitsHigh; + } -/** @returns the scalar (element) type of the given Type */ -export function scalarTypeOf(ty) { - if (ty instanceof ScalarType) { - return ty; + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + workingDataU32[0] = this.bitsLow; + workingDataU32[1] = this.bitsHigh; + for (let i = 0; i < 8; i++) { + buffer[offset + i] = workingDataU8[i]; + } } - if (ty instanceof VectorType) { - return ty.elementType; + + /** @returns the WGSL representation of this scalar value */ + wgsl() { + assert(false, 'f64 is not a WGSL type'); + return `${withPoint(this.value)}`; } - if (ty instanceof MatrixType) { - return ty.elementType; + + toString() { + switch (this.value) { + case Infinity: + case -Infinity: + return Colors.bold(this.value.toString()); + default:{ + let str = this.value.toString(); + str = str.indexOf('.') > 0 || str.indexOf('e') > 0 ? str : `${str}.0`; + return isSubnormalNumberF64(this.value.valueOf()) ? + `${Colors.bold(str)} (${hex(8, this.bitsLow, this.bitsHigh)} subnormal)` : + `${Colors.bold(str)} (${hex(8, this.bitsLow, this.bitsHigh)})`; + } + } } - throw new Error(`unhandled type ${ty}`); } -/** ScalarValue is the JS type that can be held by a Scalar */ +/** Class that encapsulates a single f32 value. */ +export class F32Value { + // The f32 value + // The f32 value, bitcast to a 32-bit integer. + type = Type.f32; // The type of the value. + constructor(value, bits) { + this.value = value; + this.bits = bits; + } -/** Class that encapsulates a single scalar value of various types. */ -export class Scalar { - // The scalar value - // The type of the scalar + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + workingDataU32[0] = this.bits; + for (let i = 0; i < 4; i++) { + buffer[offset + i] = workingDataU8[i]; + } + } - // The scalar value, packed in one or two 32-bit unsigned integers. - // Whether or not the bits1 is used depends on `this.type.size`. + /** @returns the WGSL representation of this scalar value */ + wgsl() { + return `${withPoint(this.value)}f`; + } + toString() { + switch (this.value) { + case Infinity: + case -Infinity: + return Colors.bold(this.value.toString()); + default:{ + let str = this.value.toString(); + str = str.indexOf('.') > 0 || str.indexOf('e') > 0 ? str : `${str}.0`; + return isSubnormalNumberF32(this.value.valueOf()) ? + `${Colors.bold(str)} (${hex(4, this.bits)} subnormal)` : + `${Colors.bold(str)} (${hex(4, this.bits)})`; + } + } + } +} +/** Class that encapsulates a single f16 value. */ +export class F16Value { + // The f16 value + // The f16 value, bitcast to a 16-bit integer. + type = Type.f16; // The type of the value. - constructor(type, value, bits1, bits0) { + constructor(value, bits) { this.value = value; - this.type = type; - this.bits1 = bits1; - this.bits0 = bits0; + this.bits = bits; } /** @@ -894,200 +1613,195 @@ export class Scalar { * @param offset the offset in buffer, in units of `buffer` */ copyTo(buffer, offset) { - assert(this.type.kind !== 'f64', `Copying f64 values to/from buffers is not defined`); - workingDataU32[1] = this.bits1; - workingDataU32[0] = this.bits0; - for (let i = 0; i < this.type.size; i++) { + workingDataU16[0] = this.bits; + for (let i = 0; i < 2; i++) { buffer[offset + i] = workingDataU8[i]; } } - /** - * @returns the WGSL representation of this scalar value - */ + /** @returns the WGSL representation of this scalar value */ wgsl() { - const withPoint = (x) => { - const str = `${x}`; - return str.indexOf('.') > 0 || str.indexOf('e') > 0 ? str : `${str}.0`; - }; - if (isFinite(this.value)) { - switch (this.type.kind) { - case 'abstract-float': - return `${withPoint(this.value)}`; - case 'f64': - return `${withPoint(this.value)}`; - case 'f32': - return `${withPoint(this.value)}f`; - case 'f16': - return `${withPoint(this.value)}h`; - case 'u32': - return `${this.value}u`; - case 'i32': - return `i32(${this.value})`; - case 'bool': - return `${this.value}`; - } - } - throw new Error( - `scalar of value ${this.value} and type ${this.type} has no WGSL representation` - ); + return `${withPoint(this.value)}h`; } toString() { - if (this.type.kind === 'bool') { - return Colors.bold(this.value.toString()); - } switch (this.value) { case Infinity: case -Infinity: return Colors.bold(this.value.toString()); default:{ - workingDataU32[1] = this.bits1; - workingDataU32[0] = this.bits0; - let hex = ''; - for (let i = 0; i < this.type.size; ++i) { - hex = workingDataU8[i].toString(16).padStart(2, '0') + hex; - } - const n = this.value; - if (n !== null && isFloatValue(this)) { - let str = this.value.toString(); - str = str.indexOf('.') > 0 || str.indexOf('e') > 0 ? str : `${str}.0`; - switch (this.type.kind) { - case 'abstract-float': - return isSubnormalNumberF64(n.valueOf()) ? - `${Colors.bold(str)} (0x${hex} subnormal)` : - `${Colors.bold(str)} (0x${hex})`; - case 'f64': - return isSubnormalNumberF64(n.valueOf()) ? - `${Colors.bold(str)} (0x${hex} subnormal)` : - `${Colors.bold(str)} (0x${hex})`; - case 'f32': - return isSubnormalNumberF32(n.valueOf()) ? - `${Colors.bold(str)} (0x${hex} subnormal)` : - `${Colors.bold(str)} (0x${hex})`; - case 'f16': - return isSubnormalNumberF16(n.valueOf()) ? - `${Colors.bold(str)} (0x${hex} subnormal)` : - `${Colors.bold(str)} (0x${hex})`; - default: - unreachable( - `Printing of floating point kind ${this.type.kind} is not implemented...` - ); - } - } - return `${Colors.bold(this.value.toString())} (0x${hex})`; + let str = this.value.toString(); + str = str.indexOf('.') > 0 || str.indexOf('e') > 0 ? str : `${str}.0`; + return isSubnormalNumberF16(this.value.valueOf()) ? + `${Colors.bold(str)} (${hex(2, this.bits)} subnormal)` : + `${Colors.bold(str)} (${hex(2, this.bits)})`; } } } } +/** Class that encapsulates a single bool value. */ +export class BoolValue { + // The bool value + type = Type.bool; // The type of the value. + constructor(value) { + this.value = value; + } + /** + * Copies the scalar value to the buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the offset in buffer, in units of `buffer` + */ + copyTo(buffer, offset) { + buffer[offset] = this.value ? 1 : 0; + } + /** @returns the WGSL representation of this scalar value */ + wgsl() { + return this.value.toString(); + } - -/** Create a Scalar of `type` by storing `value` as an element of `workingDataArray` and retrieving it. - * The working data array *must* be an alias of `workingData`. - */ -function scalarFromValue( -type, -workingDataArray, -value) -{ - // Clear all bits of the working data since `value` may be smaller; the upper bits should be 0. - workingDataU32[1] = 0; - workingDataU32[0] = 0; - workingDataArray[0] = value; - return new Scalar(type, workingDataArray[0], workingDataU32[1], workingDataU32[0]); + toString() { + return Colors.bold(this.value.toString()); + } } -/** Create a Scalar of `type` by storing `value` as an element of `workingDataStoreArray` and - * reinterpreting it as an element of `workingDataLoadArray`. - * Both working data arrays *must* be aliases of `workingData`. - */ -function scalarFromBits( -type, -workingDataStoreArray, -workingDataLoadArray, -bits) -{ - // Clear all bits of the working data since `value` may be smaller; the upper bits should be 0. - workingDataU32[1] = 0; - workingDataU32[0] = 0; - workingDataStoreArray[0] = bits; - return new Scalar(type, workingDataLoadArray[0], workingDataU32[1], workingDataU32[0]); -} +/** Scalar represents all the scalar value types */ -/** Create an AbstractFloat from a numeric value, a JS `number`. */ -export const abstractFloat = (value) => -scalarFromValue(TypeAbstractFloat, workingDataF64, value); -/** Create an f64 from a numeric value, a JS `number`. */ -export const f64 = (value) => scalarFromValue(TypeF64, workingDataF64, value); -/** Create an f32 from a numeric value, a JS `number`. */ -export const f32 = (value) => scalarFromValue(TypeF32, workingDataF32, value); -/** Create an f16 from a numeric value, a JS `number`. */ -export const f16 = (value) => scalarFromValue(TypeF16, workingDataF16, value); -/** Create an f32 from a bit representation, a uint32 represented as a JS `number`. */ -export const f32Bits = (bits) => -scalarFromBits(TypeF32, workingDataU32, workingDataF32, bits); -/** Create an f16 from a bit representation, a uint16 represented as a JS `number`. */ -export const f16Bits = (bits) => -scalarFromBits(TypeF16, workingDataU16, workingDataF16, bits); -/** Create an i32 from a numeric value, a JS `number`. */ -export const i32 = (value) => scalarFromValue(TypeI32, workingDataI32, value); -/** Create an i16 from a numeric value, a JS `number`. */ -export const i16 = (value) => scalarFromValue(TypeI16, workingDataI16, value); -/** Create an i8 from a numeric value, a JS `number`. */ -export const i8 = (value) => scalarFromValue(TypeI8, workingDataI8, value); -/** Create an i32 from a bit representation, a uint32 represented as a JS `number`. */ -export const i32Bits = (bits) => -scalarFromBits(TypeI32, workingDataU32, workingDataI32, bits); -/** Create an i16 from a bit representation, a uint16 represented as a JS `number`. */ -export const i16Bits = (bits) => -scalarFromBits(TypeI16, workingDataU16, workingDataI16, bits); -/** Create an i8 from a bit representation, a uint8 represented as a JS `number`. */ -export const i8Bits = (bits) => -scalarFromBits(TypeI8, workingDataU8, workingDataI8, bits); + + + + + + +export function isScalarValue(value) { + return ( + value instanceof AbstractIntValue || + value instanceof AbstractFloatValue || + value instanceof I32Value || + value instanceof U32Value || + value instanceof I16Value || + value instanceof U16Value || + value instanceof I8Value || + value instanceof U8Value || + value instanceof F64Value || + value instanceof F32Value || + value instanceof F16Value || + value instanceof BoolValue); + +} + +/** Create an AbstractInt from a numeric value, a JS `bigint`. */ +export function abstractInt(value) { + workingDataI64[0] = value; + return new AbstractIntValue(workingDataI64[0], workingDataU32[0], workingDataU32[1]); +} + +/** Create an AbstractInt from a bit representation, a uint64 represented as a JS `bigint`. */ +export function abstractIntBits(value) { + workingDataU64[0] = value; + return new AbstractIntValue(workingDataI64[0], workingDataU32[0], workingDataU32[1]); +} + +/** Create an AbstractFloat from a numeric value, a JS `number`. */ +export function abstractFloat(value) { + workingDataF64[0] = value; + return new AbstractFloatValue(workingDataF64[0], workingDataU32[0], workingDataU32[1]); +} + +/** Create an i32 from a numeric value, a JS `number`. */ +export function i32(value) { + workingDataI32[0] = value; + return new I32Value(workingDataI32[0], workingDataU32[0]); +} + +/** Create an i32 from a bit representation, a uint32 represented as a JS `number`. */ +export function i32Bits(bits) { + workingDataU32[0] = bits; + return new I32Value(workingDataI32[0], workingDataU32[0]); +} /** Create a u32 from a numeric value, a JS `number`. */ -export const u32 = (value) => scalarFromValue(TypeU32, workingDataU32, value); +export function u32(value) { + workingDataU32[0] = value; + return new U32Value(workingDataU32[0]); +} + +/** Create a u32 from a bit representation, a uint32 represented as a JS `number`. */ +export function u32Bits(bits) { + workingDataU32[0] = bits; + return new U32Value(workingDataU32[0]); +} + +/** Create an i16 from a numeric value, a JS `number`. */ +export function i16(value) { + workingDataI16[0] = value; + return new I16Value(workingDataI16[0], workingDataU16[0]); +} /** Create a u16 from a numeric value, a JS `number`. */ -export const u16 = (value) => scalarFromValue(TypeU16, workingDataU16, value); +export function u16(value) { + workingDataU16[0] = value; + return new U16Value(workingDataU16[0]); +} + +/** Create an i8 from a numeric value, a JS `number`. */ +export function i8(value) { + workingDataI8[0] = value; + return new I8Value(workingDataI8[0], workingDataU8[0]); +} /** Create a u8 from a numeric value, a JS `number`. */ -export const u8 = (value) => scalarFromValue(TypeU8, workingDataU8, value); +export function u8(value) { + workingDataU8[0] = value; + return new U8Value(workingDataU8[0]); +} + +/** Create an f64 from a numeric value, a JS `number`. */ +export function f64(value) { + workingDataF64[0] = value; + return new F64Value(workingDataF64[0], workingDataU32[0], workingDataU32[1]); +} -/** Create an u32 from a bit representation, a uint32 represented as a JS `number`. */ -export const u32Bits = (bits) => -scalarFromBits(TypeU32, workingDataU32, workingDataU32, bits); +/** Create an f32 from a numeric value, a JS `number`. */ +export function f32(value) { + workingDataF32[0] = value; + return new F32Value(workingDataF32[0], workingDataU32[0]); +} + +/** Create an f32 from a bit representation, a uint32 represented as a JS `number`. */ +export function f32Bits(bits) { + workingDataU32[0] = bits; + return new F32Value(workingDataF32[0], workingDataU32[0]); +} -/** Create an u16 from a bit representation, a uint16 represented as a JS `number`. */ -export const u16Bits = (bits) => -scalarFromBits(TypeU16, workingDataU16, workingDataU16, bits); +/** Create an f16 from a numeric value, a JS `number`. */ +export function f16(value) { + workingDataF16[0] = value; + return new F16Value(workingDataF16[0], workingDataU16[0]); +} -/** Create an u8 from a bit representation, a uint8 represented as a JS `number`. */ -export const u8Bits = (bits) => -scalarFromBits(TypeU8, workingDataU8, workingDataU8, bits); +/** Create an f16 from a bit representation, a uint16 represented as a JS `number`. */ +export function f16Bits(bits) { + workingDataU16[0] = bits; + return new F16Value(workingDataF16[0], workingDataU16[0]); +} /** Create a boolean value. */ export function bool(value) { - // WGSL does not support using 'bool' types directly in storage / uniform - // buffers, so instead we pack booleans in a u32, where 'false' is zero and - // 'true' is any non-zero value. - workingDataU32[0] = value ? 1 : 0; - workingDataU32[1] = 0; - return new Scalar(TypeBool, value, workingDataU32[1], workingDataU32[0]); + return new BoolValue(value); } /** A 'true' literal value */ @@ -1099,7 +1813,7 @@ export const False = bool(false); /** * Class that encapsulates a vector value. */ -export class Vector { +export class VectorValue { @@ -1117,7 +1831,7 @@ export class Vector { } } this.elements = elements; - this.type = TypeVec(elements.length, elements[0].type); + this.type = VectorType.create(elements.length, elements[0].type); } /** @@ -1165,19 +1879,24 @@ export class Vector { } } +/** Helper for constructing a new vector with the provided values */ +export function vec(...elements) { + return new VectorValue(elements); +} + /** Helper for constructing a new two-element vector with the provided values */ export function vec2(x, y) { - return new Vector([x, y]); + return new VectorValue([x, y]); } /** Helper for constructing a new three-element vector with the provided values */ export function vec3(x, y, z) { - return new Vector([x, y, z]); + return new VectorValue([x, y, z]); } /** Helper for constructing a new four-element vector with the provided values */ export function vec4(x, y, z, w) { - return new Vector([x, y, z, w]); + return new VectorValue([x, y, z, w]); } /** @@ -1201,7 +1920,7 @@ export function toVector(v, op) { /** * Class that encapsulates a Matrix value. */ -export class Matrix { +export class MatrixValue { @@ -1226,7 +1945,7 @@ export class Matrix { } this.elements = elements; - this.type = TypeMat(num_cols, num_rows, elem_type); + this.type = MatrixType.create(num_cols, num_rows, elem_type); } /** @@ -1261,6 +1980,53 @@ export class Matrix { } } +/** + * Class that encapsulates an Array value. + */ +export class ArrayValue { + + + + constructor(elements) { + const elem_type = elements[0].type; + if (!elements.every((c) => elements.every((r) => objectEquals(r.type, elem_type)))) { + throw new Error(`cannot mix array element types`); + } + + this.elements = elements; + this.type = ArrayType.create(elements.length, elem_type); + } + + /** + * Copies the array value to the Uint8Array buffer at the provided byte offset. + * @param buffer the destination buffer + * @param offset the byte offset within buffer + */ + copyTo(buffer, offset) { + for (const element of this.elements) { + element.copyTo(buffer, offset); + offset += this.type.elementType.size; + } + } + + /** + * @returns the WGSL representation of this array value + */ + wgsl() { + const els = this.elements.map((r) => r.wgsl()).join(', '); + return isAbstractType(this.type.elementType) ? `array(${els})` : `${this.type}(${els})`; + } + + toString() { + return this.wgsl(); + } +} + +/** Helper for constructing an ArrayValue with the provided values */ +export function array(...elements) { + return new ArrayValue(elements); +} + /** * Helper for constructing Matrices from arrays of numbers * @@ -1271,17 +2037,20 @@ export class Matrix { export function toMatrix(m, op) { const cols = m.length; const rows = m[0].length; - const elements = [...Array(cols)].map((_) => [...Array(rows)]); + const elements = [...Array(cols)].map((_) => [ + ...Array(rows)] + ); for (let i = 0; i < cols; i++) { for (let j = 0; j < rows; j++) { elements[i][j] = op(m[i][j]); } } - return new Matrix(elements); + return new MatrixValue(elements); } -/** Value is a Scalar or Vector value. */var +/** Value is a Scalar, Vector, Matrix or Array value. */var + @@ -1301,8 +2070,8 @@ export function toMatrix(m, op) { +SerializedScalarKind = /*#__PURE__*/function (SerializedScalarKind) {SerializedScalarKind[SerializedScalarKind["AbstractFloat"] = 0] = "AbstractFloat";SerializedScalarKind[SerializedScalarKind["F64"] = 1] = "F64";SerializedScalarKind[SerializedScalarKind["F32"] = 2] = "F32";SerializedScalarKind[SerializedScalarKind["F16"] = 3] = "F16";SerializedScalarKind[SerializedScalarKind["U32"] = 4] = "U32";SerializedScalarKind[SerializedScalarKind["U16"] = 5] = "U16";SerializedScalarKind[SerializedScalarKind["U8"] = 6] = "U8";SerializedScalarKind[SerializedScalarKind["I32"] = 7] = "I32";SerializedScalarKind[SerializedScalarKind["I16"] = 8] = "I16";SerializedScalarKind[SerializedScalarKind["I8"] = 9] = "I8";SerializedScalarKind[SerializedScalarKind["Bool"] = 10] = "Bool";SerializedScalarKind[SerializedScalarKind["AbstractInt"] = 11] = "AbstractInt";return SerializedScalarKind;}(SerializedScalarKind || {}); -SerializedScalarKind = /*#__PURE__*/function (SerializedScalarKind) {SerializedScalarKind[SerializedScalarKind["AbstractFloat"] = 0] = "AbstractFloat";SerializedScalarKind[SerializedScalarKind["F64"] = 1] = "F64";SerializedScalarKind[SerializedScalarKind["F32"] = 2] = "F32";SerializedScalarKind[SerializedScalarKind["F16"] = 3] = "F16";SerializedScalarKind[SerializedScalarKind["U32"] = 4] = "U32";SerializedScalarKind[SerializedScalarKind["U16"] = 5] = "U16";SerializedScalarKind[SerializedScalarKind["U8"] = 6] = "U8";SerializedScalarKind[SerializedScalarKind["I32"] = 7] = "I32";SerializedScalarKind[SerializedScalarKind["I16"] = 8] = "I16";SerializedScalarKind[SerializedScalarKind["I8"] = 9] = "I8";SerializedScalarKind[SerializedScalarKind["Bool"] = 10] = "Bool";return SerializedScalarKind;}(SerializedScalarKind || {}); @@ -1340,6 +2109,9 @@ function serializeScalarKind(s, v) { case 'u8': s.writeU8(SerializedScalarKind.U8); return; + case 'abstract-int': + s.writeU8(SerializedScalarKind.AbstractInt); + return; case 'i32': s.writeU8(SerializedScalarKind.I32); return; @@ -1353,6 +2125,7 @@ function serializeScalarKind(s, v) { s.writeU8(SerializedScalarKind.Bool); return; } + unreachable(`Do not know what to write scalar kind = ${v}`); } /** deserializeScalarKind() deserializes a ScalarKind from a BinaryStream */ @@ -1373,6 +2146,8 @@ function deserializeScalarKind(s) { return 'u16'; case SerializedScalarKind.U8: return 'u8'; + case SerializedScalarKind.AbstractInt: + return 'abstract-int'; case SerializedScalarKind.I32: return 'i32'; case SerializedScalarKind.I16: @@ -1395,50 +2170,65 @@ SerializedValueKind = /*#__PURE__*/function (SerializedValueKind) {SerializedVal /** serializeValue() serializes a Value to a BinaryStream */ export function serializeValue(s, v) { const serializeScalar = (scalar, kind) => { - switch (kind) { - case 'abstract-float': - s.writeF64(scalar.value); - return; - case 'f64': - s.writeF64(scalar.value); - return; - case 'f32': - s.writeF32(scalar.value); - return; - case 'f16': - s.writeF16(scalar.value); - return; - case 'u32': - s.writeU32(scalar.value); - return; - case 'u16': - s.writeU16(scalar.value); - return; - case 'u8': - s.writeU8(scalar.value); - return; - case 'i32': - s.writeI32(scalar.value); - return; - case 'i16': - s.writeI16(scalar.value); - return; - case 'i8': - s.writeI8(scalar.value); - return; - case 'bool': - s.writeBool(scalar.value); - return; + switch (typeof scalar.value) { + case 'number': + switch (kind) { + case 'abstract-float': + s.writeF64(scalar.value); + return; + case 'f64': + s.writeF64(scalar.value); + return; + case 'f32': + s.writeF32(scalar.value); + return; + case 'f16': + s.writeF16(scalar.value); + return; + case 'u32': + s.writeU32(scalar.value); + return; + case 'u16': + s.writeU16(scalar.value); + return; + case 'u8': + s.writeU8(scalar.value); + return; + case 'i32': + s.writeI32(scalar.value); + return; + case 'i16': + s.writeI16(scalar.value); + return; + case 'i8': + s.writeI8(scalar.value); + return; + } + break; + case 'bigint': + switch (kind) { + case 'abstract-int': + s.writeI64(scalar.value); + return; + } + break; + case 'boolean': + switch (kind) { + case 'bool': + s.writeBool(scalar.value); + return; + } + break; } }; - if (v instanceof Scalar) { + if (isScalarValue(v)) { s.writeU8(SerializedValueKind.Scalar); serializeScalarKind(s, v.type.kind); serializeScalar(v, v.type.kind); return; } - if (v instanceof Vector) { + if (v instanceof VectorValue) { s.writeU8(SerializedValueKind.Vector); serializeScalarKind(s, v.type.elementType.kind); s.writeU8(v.type.width); @@ -1447,7 +2237,7 @@ export function serializeValue(s, v) { } return; } - if (v instanceof Matrix) { + if (v instanceof MatrixValue) { s.writeU8(SerializedValueKind.Matrix); serializeScalarKind(s, v.type.elementType.kind); s.writeU8(v.type.cols); @@ -1481,6 +2271,8 @@ export function deserializeValue(s) { return u16(s.readU16()); case 'u8': return u8(s.readU8()); + case 'abstract-int': + return abstractInt(s.readI64()); case 'i32': return i32(s.readI32()); case 'i16': @@ -1502,7 +2294,7 @@ export function deserializeValue(s) { for (let i = 0; i < width; i++) { scalars[i] = deserializeScalar(scalarKind); } - return new Vector(scalars); + return new VectorValue(scalars); } case SerializedValueKind.Matrix:{ const numCols = s.readU8(); @@ -1514,7 +2306,7 @@ export function deserializeValue(s) { columns[c][i] = deserializeScalar(scalarKind); } } - return new Matrix(columns); + return new MatrixValue(columns); } default: unreachable(`invalid serialized value kind: ${valueKind}`); @@ -1533,7 +2325,7 @@ export function isFloatValue(v) { */ export function isAbstractType(ty) { if (ty instanceof ScalarType) { - return ty.kind === 'abstract-float'; + return ty.kind === 'abstract-float' || ty.kind === 'abstract-int'; } return false; } @@ -1552,84 +2344,221 @@ export function isFloatType(ty) { return false; } +/** + * @returns if `ty` is a type convertible to floating point type. + * @note this does not consider composite types. + * Use elementType() if you want to test the element type. + */ +export function isConvertibleToFloatType(ty) { + if (ty instanceof ScalarType) { + return ( + ty.kind === 'abstract-int' || + ty.kind === 'abstract-float' || + ty.kind === 'f64' || + ty.kind === 'f32' || + ty.kind === 'f16'); + + } + return false; +} + +/** + * @returns if `ty` is an unsigned type. + */ +export function isUnsignedType(ty) { + if (ty instanceof ScalarType) { + return ty.kind === 'u8' || ty.kind === 'u16' || ty.kind === 'u32'; + } else { + return isUnsignedType(ty.elementType); + } +} + +/** @returns true if an argument of type 'src' can be used for a parameter of type 'dst' */ +export function isConvertible(src, dst) { + if (src === dst) { + return true; + } + + const widthOf = (ty) => { + return ty instanceof VectorType ? ty.width : 1; + }; + + if (widthOf(src) !== widthOf(dst)) { + return false; + } + + const elSrc = scalarTypeOf(src); + const elDst = scalarTypeOf(dst); + + switch (elSrc.kind) { + case 'abstract-float': + switch (elDst.kind) { + case 'abstract-float': + case 'f16': + case 'f32': + case 'f64': + return true; + default: + return false; + } + case 'abstract-int': + switch (elDst.kind) { + case 'abstract-int': + case 'abstract-float': + case 'f16': + case 'f32': + case 'f64': + case 'u16': + case 'u32': + case 'u8': + case 'i16': + case 'i32': + case 'i8': + return true; + default: + return false; + } + default: + return false; + } +} + /// All floating-point scalar types -export const kAllFloatScalars = [TypeAbstractFloat, TypeF32, TypeF16]; +const kFloatScalars = [Type.abstractFloat, Type.f32, Type.f16]; /// All floating-point vec2 types -export const kAllFloatVector2 = [ -TypeVec(2, TypeAbstractFloat), -TypeVec(2, TypeF32), -TypeVec(2, TypeF16)]; - +const kFloatVec2 = [Type.vec2af, Type.vec2f, Type.vec2h]; /// All floating-point vec3 types -export const kAllFloatVector3 = [ -TypeVec(3, TypeAbstractFloat), -TypeVec(3, TypeF32), -TypeVec(3, TypeF16)]; - +const kFloatVec3 = [Type.vec3af, Type.vec3f, Type.vec3h]; /// All floating-point vec4 types -export const kAllFloatVector4 = [ -TypeVec(4, TypeAbstractFloat), -TypeVec(4, TypeF32), -TypeVec(4, TypeF16)]; +const kFloatVec4 = [Type.vec4af, Type.vec4f, Type.vec4h]; - -/// All floating-point vector types -export const kAllFloatVectors = [ -...kAllFloatVector2, -...kAllFloatVector3, -...kAllFloatVector4]; +export const kConcreteF32ScalarsAndVectors = [ +Type.f32, +Type.vec2f, +Type.vec3f, +Type.vec4f]; -/// All floating-point scalar and vector types -export const kAllFloatScalarsAndVectors = [...kAllFloatScalars, ...kAllFloatVectors]; +/// All f16 floating-point scalar and vector types +export const kConcreteF16ScalarsAndVectors = [ +Type.f16, +Type.vec2h, +Type.vec3h, +Type.vec4h]; -/// All integer scalar and vector types -export const kAllIntegerScalarsAndVectors = [ -TypeI32, -TypeVec(2, TypeI32), -TypeVec(3, TypeI32), -TypeVec(4, TypeI32), -TypeU32, -TypeVec(2, TypeU32), -TypeVec(3, TypeU32), -TypeVec(4, TypeU32)]; +/// All floating-point vector types +export const kFloatVectors = [...kFloatVec2, ...kFloatVec3, ...kFloatVec4]; -/// All signed integer scalar and vector types -export const kAllSignedIntegerScalarsAndVectors = [ -TypeI32, -TypeVec(2, TypeI32), -TypeVec(3, TypeI32), -TypeVec(4, TypeI32)]; +/// All floating-point scalar and vector types +export const kFloatScalarsAndVectors = [...kFloatScalars, ...kFloatVectors]; +// Abstract and concrete integer types are not grouped into an 'all' type, +// because for many validation tests there is a valid conversion of +// AbstractInt -> AbstractFloat, but not one for the concrete integers. Thus, an +// AbstractInt literal will be a potentially valid input, whereas the concrete +// integers will not be. For many tests the pattern is to have separate fixtures +// for the things that might be valid and those that are never valid. -/// All unsigned integer scalar and vector types -export const kAllUnsignedIntegerScalarsAndVectors = [ -TypeU32, -TypeVec(2, TypeU32), -TypeVec(3, TypeU32), -TypeVec(4, TypeU32)]; +/// All signed integer vector types +export const kConcreteSignedIntegerVectors = [Type.vec2i, Type.vec3i, Type.vec4i]; +/// All unsigned integer vector types +export const kConcreteUnsignedIntegerVectors = [Type.vec2u, Type.vec3u, Type.vec4u]; -/// All floating-point and integer scalar and vector types -export const kAllFloatAndIntegerScalarsAndVectors = [ -...kAllFloatScalarsAndVectors, -...kAllIntegerScalarsAndVectors]; +/// All concrete integer vector types +export const kConcreteIntegerVectors = [ +...kConcreteSignedIntegerVectors, +...kConcreteUnsignedIntegerVectors]; -/// All floating-point and signed integer scalar and vector types -export const kAllFloatAndSignedIntegerScalarsAndVectors = [ -...kAllFloatScalarsAndVectors, -...kAllSignedIntegerScalarsAndVectors]; +/// All signed integer scalar and vector types +export const kConcreteSignedIntegerScalarsAndVectors = [ +Type.i32, +...kConcreteSignedIntegerVectors]; -/** @returns the inner element type of the given type */ -export function elementType(t) { - if (t instanceof ScalarType) { - return t; - } - return t.elementType; -} \ No newline at end of file +/// All unsigned integer scalar and vector types +export const kConcreteUnsignedIntegerScalarsAndVectors = [ +Type.u32, +...kConcreteUnsignedIntegerVectors]; + + +/// All concrete integer scalar and vector types +export const kConcreteIntegerScalarsAndVectors = [ +...kConcreteSignedIntegerScalarsAndVectors, +...kConcreteUnsignedIntegerScalarsAndVectors]; + + +/// All types which are convertable to floating-point scalar types. +export const kConvertableToFloatScalar = [Type.abstractInt, ...kFloatScalars]; + +/// All types which are convertable to floating-point vector 2 types. +export const kConvertableToFloatVec2 = [Type.vec2ai, ...kFloatVec2]; + +/// All types which are convertable to floating-point vector 3 types. +export const kConvertableToFloatVec3 = [Type.vec3ai, ...kFloatVec3]; + +/// All types which are convertable to floating-point vector 4 types. +export const kConvertableToFloatVec4 = [Type.vec4ai, ...kFloatVec4]; + +/// All the types which are convertable to floating-point vector types. +export const kConvertableToFloatVectors = [ +Type.vec2ai, +Type.vec3ai, +Type.vec4ai, +...kFloatVectors]; + + +/// All types which are convertable to floating-point scalar or vector types. +export const kConvertableToFloatScalarsAndVectors = [ +Type.abstractInt, +...kFloatScalars, +...kConvertableToFloatVectors]; + + +/// All the numeric scalar and vector types. +export const kAllNumericScalarsAndVectors = [ +...kConvertableToFloatScalarsAndVectors, +...kConcreteIntegerScalarsAndVectors]; + + +/// All the concrete integer and floating point scalars and vectors. +export const kConcreteNumericScalarsAndVectors = [ +...kConcreteIntegerScalarsAndVectors, +...kConcreteF16ScalarsAndVectors, +...kConcreteF32ScalarsAndVectors]; + + +/// All boolean types. +export const kAllBoolScalarsAndVectors = [Type.bool, Type.vec2b, Type.vec3b, Type.vec4b]; + +/// All the scalar and vector types. +export const kAllScalarsAndVectors = [ +...kAllBoolScalarsAndVectors, +...kAllNumericScalarsAndVectors]; + + +/// All the matrix types +export const kAllMatrices = [ +Type.mat2x2f, +Type.mat2x2h, +Type.mat2x3f, +Type.mat2x3h, +Type.mat2x4f, +Type.mat2x4h, +Type.mat3x2f, +Type.mat3x2h, +Type.mat3x3f, +Type.mat3x3h, +Type.mat3x4f, +Type.mat3x4h, +Type.mat4x2f, +Type.mat4x2h, +Type.mat4x3f, +Type.mat4x3h, +Type.mat4x4f, +Type.mat4x4h]; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/device_pool.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/device_pool.js index feb62bc1be..e5f7eb90a7 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/device_pool.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/device_pool.js @@ -9,6 +9,11 @@ import { '../../common/util/util.js'; import { getDefaultLimits, kLimits } from '../capability_info.js'; +// MUST_NOT_BE_IMPORTED_BY_DATA_CACHE +// This file should not be transitively imported by .cache.ts files + + + @@ -283,6 +288,8 @@ descriptor) * Holds a GPUDevice and tracks its state (free/acquired) and handles device loss. */ class DeviceHolder { + /** Adapter the device was created from. Cannot be reused; just for adapter info. */ + /** The device. Will be cleared during cleanup if there were unexpected errors. */ /** Whether the device is in use by a test or not. */ @@ -307,10 +314,11 @@ class DeviceHolder { const device = await adapter.requestDevice(descriptor); assert(device !== null, 'requestDevice returned null'); - return new DeviceHolder(device); + return new DeviceHolder(adapter, device); } - constructor(device) { + constructor(adapter, device) { + this.adapter = adapter; this._device = device; void this._device.lost.then((ev) => { this.lostInfo = ev; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/floating_point.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/floating_point.js index aada64711c..6b98800fd2 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/floating_point.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/floating_point.js @@ -4,6 +4,7 @@ + import { anyOf } from './compare.js'; import { kValue } from './constants.js'; import { @@ -23,6 +24,7 @@ import { correctlyRoundedF16, correctlyRoundedF32, correctlyRoundedF64, + every2DArray, flatten2DArray, flushSubnormalNumberF16, @@ -36,10 +38,24 @@ import { map2DArray, oneULPF16, oneULPF32, - quantizeToF32, quantizeToF16, + quantizeToF32, + scalarF16Range, + scalarF32Range, + scalarF64Range, + sparseMatrixF16Range, + sparseMatrixF32Range, + sparseMatrixF64Range, + sparseScalarF16Range, + sparseScalarF32Range, + sparseScalarF64Range, + sparseVectorF16Range, + sparseVectorF32Range, + sparseVectorF64Range, unflatten2DArray, - every2DArray } from + vectorF16Range, + vectorF32Range, + vectorF64Range } from './math.js'; /** Indicate the kind of WGSL floating point numbers being operated on */var @@ -83,10 +99,10 @@ export function deserializeFPKind(s) { // Containers /** - * Representation of bounds for an interval as an array with either one or two - * elements. Single element indicates that the interval is a single point. For - * two elements, the first is the lower bound of the interval and the second is - * the upper bound. + * Representation of endpoints for an interval as an array with either one or + * two elements. Single element indicates that the interval is a single point. + * For two elements, the first is the lower edges of the interval and the + * second is the upper edge, i.e. e[0] <= e[1], where e is an IntervalEndpoints */ @@ -102,15 +118,18 @@ export class FPInterval { * `FPTraits.toInterval` is the preferred way to create FPIntervals * * @param kind the floating point number type this is an interval for - * @param bounds beginning and end of the interval + * @param endpoints beginning and end of the interval */ - constructor(kind, ...bounds) { + constructor(kind, ...endpoints) { this.kind = kind; - const begin = bounds[0]; - const end = bounds.length === 2 ? bounds[1] : bounds[0]; - assert(!Number.isNaN(begin) && !Number.isNaN(end), `bounds need to be non-NaN`); - assert(begin <= end, `bounds[0] (${begin}) must be less than or equal to bounds[1] (${end})`); + const begin = endpoints[0]; + const end = endpoints.length === 2 ? endpoints[1] : endpoints[0]; + assert(!Number.isNaN(begin) && !Number.isNaN(end), `endpoints need to be non-NaN`); + assert( + begin <= end, + `endpoints[0] (${begin}) must be less than or equal to endpoints[1] (${end})` + ); this.begin = begin; this.end = end; @@ -122,7 +141,7 @@ export class FPInterval { } /** @returns begin and end if non-point interval, otherwise just begin */ - bounds() { + endpoints() { return this.isPoint() ? [this.begin] : [this.begin, this.end]; } @@ -163,7 +182,7 @@ export class FPInterval { /** @returns a string representation for logging purposes */ toString() { - return `{ '${this.kind}', [${this.bounds().map(this.traits().scalarBuilder)}] }`; + return `{ '${this.kind}', [${this.endpoints().map(this.traits().scalarBuilder)}] }`; } } @@ -316,6 +335,14 @@ function addFlushedIfNeededF16(values) { + + + + + + + + @@ -334,6 +361,13 @@ function addFlushedIfNeededF16(values) { +/** Domain for a ScalarPairToInterval implementation */ + + + + + + /** Operation used to implement a ScalarPairToInterval */ @@ -355,7 +389,8 @@ function addFlushedIfNeededF16(values) { -/** Domain for a ScalarPairToInterval implementation */ + + @@ -556,7 +591,7 @@ function addFlushedIfNeededF16(values) { // Traits /** - * Typed structure containing all the limits/constants defined for each + * Typed structure containing all the constants defined for each * WGSL floating point kind */ @@ -629,6 +664,8 @@ function addFlushedIfNeededF16(values) { + + @@ -661,7 +698,7 @@ export class FPTraits { return this.constants().unboundedInterval; } - return new FPInterval(this.kind, ...n.bounds()); + return new FPInterval(this.kind, ...n.endpoints()); } if (n instanceof Array) { @@ -696,7 +733,7 @@ export class FPTraits { } /** - * @returns an interval with the tightest bounds that includes all provided + * @returns an interval with the tightest endpoints that includes all provided * intervals */ spanIntervals(...intervals) { @@ -840,48 +877,6 @@ export class FPTraits { return needs_zero ? values.concat(0) : values; } - /** - * Restrict the inputs to an ScalarToInterval operation - * - * Only used for operations that have tighter domain requirements than 'must - * be finite'. - * - * @param domain interval to restrict inputs to - * @param impl operation implementation to run if input is within the required domain - * @returns a ScalarToInterval that calls impl if domain contains the input, - * otherwise it returns an unbounded interval */ - limitScalarToIntervalDomain( - domain, - impl) - { - return (n) => { - return domain.contains(n) ? impl(n) : this.constants().unboundedInterval; - }; - } - - /** - * Restrict the inputs to a ScalarPairToInterval - * - * Only used for operations that have tighter domain requirements than 'must be - * finite'. - * - * @param domain set of intervals to restrict inputs to - * @param impl operation implementation to run if input is within the required domain - * @returns a ScalarPairToInterval that calls impl if domain contains the input, - * otherwise it returns an unbounded interval */ - limitScalarPairToIntervalDomain( - domain, - impl) - { - return (x, y) => { - if (!domain.x.some((d) => d.contains(x)) || !domain.y.some((d) => d.contains(y))) { - return this.constants().unboundedInterval; - } - - return impl(x, y); - }; - } - /** Stub for scalar to interval generator */ unimplementedScalarToInterval(name, _x) { unreachable(`'${name}' is not yet implemented for '${this.kind}'`); @@ -1053,14 +1048,14 @@ export class FPTraits { unreachable(`'refract' is not yet implemented for '${this.kind}'`); } - /** Version of absoluteErrorInterval that always returns the unboundedInterval */ - unboundedAbsoluteErrorInterval(_n, _error_range) { - return this.constants().unboundedInterval; + /** Stub for absolute errors */ + unimplementedAbsoluteErrorInterval(_n, _error_range) { + unreachable(`Absolute Error is not implement for '${this.kind}'`); } - /** Version of ulpInterval that always returns the unboundedInterval */ - unboundedUlpInterval(_n, _numULP) { - return this.constants().unboundedInterval; + /** Stub for ULP errors */ + unimplementedUlpInterval(_n, _numULP) { + unreachable(`ULP Error is not implement for '${this.kind}'`); } // Utilities - Defined by subclass @@ -1079,7 +1074,21 @@ export class FPTraits { /** @returns 1 * ULP: (number) */ - /** @returns a builder for converting numbers to Scalars */ + /** @returns a builder for converting numbers to ScalarsValues */ + + /** @returns a range of scalars for testing */ + + /** @returns a reduced range of scalars for testing */ + + /** @returns a range of dim element vectors for testing */ + + /** @returns a reduced range of dim element vectors for testing */ + + /** @returns a reduced range of cols x rows matrices for testing + * + * A non-sparse version of this generator is intentionally not provided due to + * runtime issues with more dense ranges. + */ // Framework - Cases @@ -1705,7 +1714,6 @@ export class FPTraits { { param0 = map2DArray(param0, this.quantize); param1 = map2DArray(param1, this.quantize); - const results = ops.map((o) => o(param0, param1)); if (filter === 'finite' && results.some((m) => m.some((c) => c.some((r) => !r.isFinite())))) { return undefined; @@ -1973,6 +1981,15 @@ export class FPTraits { assert(!Number.isNaN(n), `flush not defined for NaN`); const values = this.correctlyRounded(n); const inputs = this.addFlushedIfNeeded(values); + + if (op.domain !== undefined) { + // Cannot invoke op.domain() directly in the .some, because the narrowing doesn't propegate. + const domain = op.domain(); + if (inputs.some((i) => !domain.contains(i))) { + return this.constants().unboundedInterval; + } + } + const results = new Set(inputs.map(op.impl)); return this.spanIntervals(...results); } @@ -1998,10 +2015,25 @@ export class FPTraits { { assert(!Number.isNaN(x), `flush not defined for NaN`); assert(!Number.isNaN(y), `flush not defined for NaN`); + const x_values = this.correctlyRounded(x); const y_values = this.correctlyRounded(y); const x_inputs = this.addFlushedIfNeeded(x_values); const y_inputs = this.addFlushedIfNeeded(y_values); + + if (op.domain !== undefined) { + // Cannot invoke op.domain() directly in the .some, because the narrowing doesn't propegate. + const domain = op.domain(); + + if (x_inputs.some((i) => !domain.x.some((e) => e.contains(i)))) { + return this.constants().unboundedInterval; + } + + if (y_inputs.some((j) => !domain.y.some((e) => e.contains(j)))) { + return this.constants().unboundedInterval; + } + } + const intervals = new Set(); x_inputs.forEach((inner_x) => { y_inputs.forEach((inner_y) => { @@ -2252,7 +2284,7 @@ export class FPTraits { } const result = this.spanIntervals( - ...x.bounds().map((b) => this.roundAndFlushScalarToInterval(b, op)) + ...x.endpoints().map((b) => this.roundAndFlushScalarToInterval(b, op)) ); return result.isFinite() ? result : this.constants().unboundedInterval; } @@ -2282,8 +2314,8 @@ export class FPTraits { } const outputs = new Set(); - x.bounds().forEach((inner_x) => { - y.bounds().forEach((inner_y) => { + x.endpoints().forEach((inner_x) => { + y.endpoints().forEach((inner_y) => { outputs.add(this.roundAndFlushScalarPairToInterval(inner_x, inner_y, op)); }); }); @@ -2312,9 +2344,9 @@ export class FPTraits { } const outputs = new Set(); - x.bounds().forEach((inner_x) => { - y.bounds().forEach((inner_y) => { - z.bounds().forEach((inner_z) => { + x.endpoints().forEach((inner_x) => { + y.endpoints().forEach((inner_y) => { + z.endpoints().forEach((inner_z) => { outputs.add(this.roundAndFlushScalarTripleToInterval(inner_x, inner_y, inner_z, op)); }); }); @@ -2337,7 +2369,7 @@ export class FPTraits { return this.constants().unboundedInterval; } - const x_values = cartesianProduct(...x.map((e) => e.bounds())); + const x_values = cartesianProduct(...x.map((e) => e.endpoints())); const outputs = new Set(); x_values.forEach((inner_x) => { @@ -2366,8 +2398,8 @@ export class FPTraits { return this.constants().unboundedInterval; } - const x_values = cartesianProduct(...x.map((e) => e.bounds())); - const y_values = cartesianProduct(...y.map((e) => e.bounds())); + const x_values = cartesianProduct(...x.map((e) => e.endpoints())); + const y_values = cartesianProduct(...y.map((e) => e.endpoints())); const outputs = new Set(); x_values.forEach((inner_x) => { @@ -2393,7 +2425,7 @@ export class FPTraits { return this.constants().unboundedVector[x.length]; } - const x_values = cartesianProduct(...x.map((e) => e.bounds())); + const x_values = cartesianProduct(...x.map((e) => e.endpoints())); const outputs = new Set(); x_values.forEach((inner_x) => { @@ -2437,8 +2469,8 @@ export class FPTraits { return this.constants().unboundedVector[x.length]; } - const x_values = cartesianProduct(...x.map((e) => e.bounds())); - const y_values = cartesianProduct(...y.map((e) => e.bounds())); + const x_values = cartesianProduct(...x.map((e) => e.endpoints())); + const y_values = cartesianProduct(...y.map((e) => e.endpoints())); const outputs = new Set(); x_values.forEach((inner_x) => { @@ -2495,12 +2527,15 @@ export class FPTraits { runMatrixToMatrixOp(m, op) { const num_cols = m.length; const num_rows = m[0].length; - if (m.some((c) => c.some((r) => !r.isFinite()))) { - return this.constants().unboundedMatrix[num_cols][num_rows]; - } + + // Do not check for OOB inputs and exit early here, because the shape of + // the output matrix may be determined by the operation being run, + // i.e. transpose. const m_flat = flatten2DArray(m); - const m_values = cartesianProduct(...m_flat.map((e) => e.bounds())); + const m_values = cartesianProduct( + ...m_flat.map((e) => e.endpoints()) + ); const outputs = new Set(); m_values.forEach((inner_m) => { @@ -2520,6 +2555,33 @@ export class FPTraits { this.constants().unboundedMatrix[result_cols][result_rows]; } + /** + * Calculate the Matrix of acceptance intervals by running a scalar operation + * component-wise over a scalar and a matrix. + * + * An example of this is performing constant scaling. + * + * @param i scalar input + * @param m matrix input + * @param op scalar operation to be run component-wise + * @returns a matrix of intervals with the outputs of op.impl + */ + runScalarPairToIntervalOpScalarMatrixComponentWise( + i, + m, + op) + { + const cols = m.length; + const rows = m[0].length; + return this.toMatrix( + unflatten2DArray( + flatten2DArray(m).map((e) => this.runScalarPairToIntervalOp(i, e, op)), + cols, + rows + ) + ); + } + /** * Calculate the Matrix of acceptance intervals by running a scalar operation * component-wise over a pair of matrices. @@ -2531,14 +2593,14 @@ export class FPTraits { * @param op scalar operation to be run component-wise * @returns a matrix of intervals with the outputs of op.impl */ - runScalarPairToIntervalOpMatrixComponentWise( + runScalarPairToIntervalOpMatrixMatrixComponentWise( x, y, op) { assert( x.length === y.length && x[0].length === y[0].length, - `runScalarPairToIntervalOpMatrixComponentWise requires matrices of the same dimensions` + `runScalarPairToIntervalOpMatrixMatrixComponentWise requires matrices of the same dimensions` ); const cols = x.length; @@ -2673,7 +2735,7 @@ export class FPTraits { // This op is implemented differently for f32 and f16. AcosIntervalOp = { - impl: this.limitScalarToIntervalDomain(this.toInterval([-1.0, 1.0]), (n) => { + impl: (n) => { assert(this.kind === 'f32' || this.kind === 'f16'); // acos(n) = atan2(sqrt(1.0 - n * n), n) or a polynomial approximation with absolute error const y = this.sqrtInterval(this.subtractionInterval(1, this.multiplicationInterval(n, n))); @@ -2682,7 +2744,10 @@ export class FPTraits { this.atan2Interval(y, n), this.absoluteErrorInterval(Math.acos(n), approx_abs_error) ); - }) + }, + domain: () => { + return this.constants().negOneToOneInterval; + } }; acosIntervalImpl(n) { @@ -2751,7 +2816,7 @@ export class FPTraits { additionMatrixMatrixIntervalImpl(x, y) { - return this.runScalarPairToIntervalOpMatrixComponentWise( + return this.runScalarPairToIntervalOpMatrixMatrixComponentWise( this.toMatrix(x), this.toMatrix(y), this.AdditionIntervalOp @@ -2766,16 +2831,19 @@ export class FPTraits { // This op is implemented differently for f32 and f16. AsinIntervalOp = { - impl: this.limitScalarToIntervalDomain(this.toInterval([-1.0, 1.0]), (n) => { + impl: (n) => { assert(this.kind === 'f32' || this.kind === 'f16'); // asin(n) = atan2(n, sqrt(1.0 - n * n)) or a polynomial approximation with absolute error const x = this.sqrtInterval(this.subtractionInterval(1, this.multiplicationInterval(n, n))); - const approx_abs_error = this.kind === 'f32' ? 6.77e-5 : 3.91e-3; + const approx_abs_error = this.kind === 'f32' ? 6.81e-5 : 3.91e-3; return this.spanIntervals( this.atan2Interval(n, x), this.absoluteErrorInterval(Math.asin(n), approx_abs_error) ); - }) + }, + domain: () => { + return this.constants().negOneToOneInterval; + } }; /** Calculate an acceptance interval for asin(n) */ @@ -2836,29 +2904,23 @@ export class FPTraits { [this.toInterval([-(2 ** 14), -(2 ** -14)]), this.toInterval([2 ** -14, 2 ** 14])]; const ulp_error = this.kind === 'f32' ? 4096 : 5; return { - impl: this.limitScalarPairToIntervalDomain( - { - x: domain_x, - y: domain_y - }, - (y, x) => { - // Accurate result in f64 - let atan_yx = Math.atan(y / x); - // Offset by +/-pi according to the definition. Use pi value in f64 because we are - // handling accurate result. - if (x < 0) { - // x < 0, y > 0, result is atan(y/x) + π - if (y > 0) { - atan_yx = atan_yx + kValue.f64.positive.pi.whole; - } else { - // x < 0, y < 0, result is atan(y/x) - π - atan_yx = atan_yx - kValue.f64.positive.pi.whole; - } + impl: (y, x) => { + // Accurate result in f64 + let atan_yx = Math.atan(y / x); + // Offset by +/-pi according to the definition. Use pi value in f64 because we are + // handling accurate result. + if (x < 0) { + // x < 0, y > 0, result is atan(y/x) + π + if (y > 0) { + atan_yx = atan_yx + kValue.f64.positive.pi.whole; + } else { + // x < 0, y < 0, result is atan(y/x) - π + atan_yx = atan_yx - kValue.f64.positive.pi.whole; } - - return this.ulpInterval(atan_yx, ulp_error); } - ), + + return this.ulpInterval(atan_yx, ulp_error); + }, extrema: (y, x) => { // There is discontinuity, which generates an unbounded result, at y/x = 0 that will dominate the accuracy if (y.contains(0)) { @@ -2868,6 +2930,9 @@ export class FPTraits { return [this.toInterval(0), x]; } return [y, x]; + }, + domain: () => { + return { x: domain_x, y: domain_y }; } }; } @@ -2984,14 +3049,14 @@ export class FPTraits { CosIntervalOp = { - impl: this.limitScalarToIntervalDomain( - this.constants().negPiToPiInterval, - (n) => { - assert(this.kind === 'f32' || this.kind === 'f16'); - const abs_error = this.kind === 'f32' ? 2 ** -11 : 2 ** -7; - return this.absoluteErrorInterval(Math.cos(n), abs_error); - } - ) + impl: (n) => { + assert(this.kind === 'f32' || this.kind === 'f16'); + const abs_error = this.kind === 'f32' ? 2 ** -11 : 2 ** -7; + return this.absoluteErrorInterval(Math.cos(n), abs_error); + }, + domain: () => { + return this.constants().negPiToPiInterval; + } }; cosIntervalImpl(n) { @@ -3041,7 +3106,11 @@ export class FPTraits { this.multiplicationInterval(x[0], y[1]), this.multiplicationInterval(x[1], y[0]) ); - return [r0, r1, r2]; + + if (r0.isFinite() && r1.isFinite() && r2.isFinite()) { + return [r0, r1, r2]; + } + return this.constants().unboundedVector[3]; } }; @@ -3281,24 +3350,21 @@ export class FPTraits { [this.toInterval([-(2 ** 126), -(2 ** -126)]), this.toInterval([2 ** -126, 2 ** 126])] : [this.toInterval([-(2 ** 14), -(2 ** -14)]), this.toInterval([2 ** -14, 2 ** 14])]; return { - impl: this.limitScalarPairToIntervalDomain( - { - x: domain_x, - y: domain_y - }, - (x, y) => { - if (y === 0) { - return constants.unboundedInterval; - } - return this.ulpInterval(x / y, 2.5); + impl: (x, y) => { + if (y === 0) { + return constants.unboundedInterval; } - ), + return this.ulpInterval(x / y, 2.5); + }, extrema: (x, y) => { // division has a discontinuity at y = 0. if (y.contains(0)) { y = this.toInterval(0); } return [x, y]; + }, + domain: () => { + return { x: domain_x, y: domain_y }; } }; } @@ -3346,7 +3412,10 @@ export class FPTraits { x, y) { - assert(x.length === y.length, `dot not defined for vectors with different lengths`); + assert( + x.length === y.length, + `dot not defined for vectors with different lengths, x = ${x}, y = ${y}` + ); return this.runVectorPairToIntervalOp(this.toVector(x), this.toVector(y), this.DotIntervalOp); } @@ -3517,12 +3586,12 @@ export class FPTraits { InverseSqrtIntervalOp = { - impl: this.limitScalarToIntervalDomain( - this.constants().greaterThanZeroInterval, - (n) => { - return this.ulpInterval(1 / Math.sqrt(n), 2); - } - ) + impl: (n) => { + return this.ulpInterval(1 / Math.sqrt(n), 2); + }, + domain: () => { + return this.constants().greaterThanZeroInterval; + } }; inverseSqrtIntervalImpl(n) { @@ -3534,21 +3603,19 @@ export class FPTraits { LdexpIntervalOp = { impl: (e1, e2) => { - assert(this.kind === 'f32' || this.kind === 'f16'); assert(Number.isInteger(e2), 'the second param of ldexp must be an integer'); - const bias = this.kind === 'f32' ? 127 : 15; // Spec explicitly calls indeterminate value if e2 > bias + 1 - if (e2 > bias + 1) { + if (e2 > this.constants().bias + 1) { return this.constants().unboundedInterval; } - // The spec says the result of ldexp(e1, e2) = e1 * 2 ^ e2, and the accuracy is correctly - // rounded to the true value, so the inheritance framework does not need to be invoked to - // determine bounds. + // The spec says the result of ldexp(e1, e2) = e1 * 2 ^ e2, and the + // accuracy is correctly rounded to the true value, so the inheritance + // framework does not need to be invoked to determine endpoints. // Instead, the value at a higher precision is calculated and passed to // correctlyRoundedInterval. const result = e1 * 2 ** e2; if (!Number.isFinite(result)) { - // Overflowed TS's number type, so definitely out of bounds for f32/f16 + // Overflowed TS's number type, so definitely out of bounds return this.constants().unboundedInterval; } // The result may be zero if e2 + bias <= 0, but we can't simply span the interval to 0.0. @@ -3606,17 +3673,17 @@ export class FPTraits { LogIntervalOp = { - impl: this.limitScalarToIntervalDomain( - this.constants().greaterThanZeroInterval, - (n) => { - assert(this.kind === 'f32' || this.kind === 'f16'); - const abs_error = this.kind === 'f32' ? 2 ** -21 : 2 ** -7; - if (n >= 0.5 && n <= 2.0) { - return this.absoluteErrorInterval(Math.log(n), abs_error); - } - return this.ulpInterval(Math.log(n), 3); + impl: (n) => { + assert(this.kind === 'f32' || this.kind === 'f16'); + const abs_error = this.kind === 'f32' ? 2 ** -21 : 2 ** -7; + if (n >= 0.5 && n <= 2.0) { + return this.absoluteErrorInterval(Math.log(n), abs_error); } - ) + return this.ulpInterval(Math.log(n), 3); + }, + domain: () => { + return this.constants().greaterThanZeroInterval; + } }; logIntervalImpl(x) { @@ -3627,17 +3694,17 @@ export class FPTraits { Log2IntervalOp = { - impl: this.limitScalarToIntervalDomain( - this.constants().greaterThanZeroInterval, - (n) => { - assert(this.kind === 'f32' || this.kind === 'f16'); - const abs_error = this.kind === 'f32' ? 2 ** -21 : 2 ** -7; - if (n >= 0.5 && n <= 2.0) { - return this.absoluteErrorInterval(Math.log2(n), abs_error); - } - return this.ulpInterval(Math.log2(n), 3); + impl: (n) => { + assert(this.kind === 'f32' || this.kind === 'f16'); + const abs_error = this.kind === 'f32' ? 2 ** -21 : 2 ** -7; + if (n >= 0.5 && n <= 2.0) { + return this.absoluteErrorInterval(Math.log2(n), abs_error); } - ) + return this.ulpInterval(Math.log2(n), 3); + }, + domain: () => { + return this.constants().greaterThanZeroInterval; + } }; log2IntervalImpl(x) { @@ -3791,14 +3858,10 @@ export class FPTraits { } multiplicationMatrixScalarIntervalImpl(mat, scalar) { - const cols = mat.length; - const rows = mat[0].length; - return this.toMatrix( - unflatten2DArray( - flatten2DArray(mat).map((e) => this.multiplicationInterval(e, scalar)), - cols, - rows - ) + return this.runScalarPairToIntervalOpScalarMatrixComponentWise( + this.toInterval(scalar), + this.toMatrix(mat), + this.MultiplicationIntervalOp ); } @@ -3809,7 +3872,7 @@ export class FPTraits { multiplicationScalarMatrixIntervalImpl(scalar, mat) { - return this.multiplicationMatrixScalarIntervalImpl(mat, scalar); + return this.multiplicationMatrixScalarInterval(mat, scalar); } /** Calculate an acceptance interval of x * y, when x is a scalar and y is a matrix */ @@ -3830,13 +3893,22 @@ export class FPTraits { const x_transposed = this.transposeInterval(mat_x); + let oob_result = false; const result = [...Array(y_cols)].map((_) => [...Array(x_rows)]); mat_y.forEach((y, i) => { x_transposed.forEach((x, j) => { result[i][j] = this.dotInterval(x, y); + if (!oob_result && !result[i][j].isFinite()) { + oob_result = true; + } }); }); + if (oob_result) { + return this.constants().unboundedMatrix[result.length][ + result[0].length]; + + } return result; } @@ -3896,7 +3968,11 @@ export class FPTraits { NormalizeIntervalOp = { impl: (n) => { const length = this.lengthInterval(n); - return this.toVector(n.map((e) => this.divisionInterval(e, length))); + const result = this.toVector(n.map((e) => this.divisionInterval(e, length))); + if (result.some((r) => !r.isFinite())) { + return this.constants().unboundedVector[result.length]; + } + return result; } }; @@ -3955,11 +4031,16 @@ export class FPTraits { // y = normal of reflecting surface const t = this.multiplicationInterval(2.0, this.dotInterval(x, y)); const rhs = this.multiplyVectorByScalar(y, t); - return this.runScalarPairToIntervalOpVectorComponentWise( + const result = this.runScalarPairToIntervalOpVectorComponentWise( this.toVector(x), rhs, this.SubtractionIntervalOp ); + + if (result.some((r) => !r.isFinite())) { + return this.constants().unboundedVector[result.length]; + } + return result; } }; @@ -4015,11 +4096,16 @@ export class FPTraits { const k_sqrt = this.sqrtInterval(k); const t = this.additionInterval(dot_times_r, k_sqrt); // t = r * dot(i, s) + sqrt(k) - return this.runScalarPairToIntervalOpVectorComponentWise( + const result = this.runScalarPairToIntervalOpVectorComponentWise( this.multiplyVectorByScalar(i, r), this.multiplyVectorByScalar(s, t), this.SubtractionIntervalOp ); // (i * r) - (s * t) + + if (result.some((r) => !r.isFinite())) { + return this.constants().unboundedVector[result.length]; + } + return result; } /** Calculate acceptance interval vectors of reflect(i, s, r) */ @@ -4116,14 +4202,14 @@ export class FPTraits { SinIntervalOp = { - impl: this.limitScalarToIntervalDomain( - this.constants().negPiToPiInterval, - (n) => { - assert(this.kind === 'f32' || this.kind === 'f16'); - const abs_error = this.kind === 'f32' ? 2 ** -11 : 2 ** -7; - return this.absoluteErrorInterval(Math.sin(n), abs_error); - } - ) + impl: (n) => { + assert(this.kind === 'f32' || this.kind === 'f16'); + const abs_error = this.kind === 'f32' ? 2 ** -11 : 2 ** -7; + return this.absoluteErrorInterval(Math.sin(n), abs_error); + }, + domain: () => { + return this.constants().negPiToPiInterval; + } }; sinIntervalImpl(n) { @@ -4250,7 +4336,7 @@ export class FPTraits { subtractionMatrixMatrixIntervalImpl(x, y) { - return this.runScalarPairToIntervalOpMatrixComponentWise( + return this.runScalarPairToIntervalOpMatrixMatrixComponentWise( this.toMatrix(x), this.toMatrix(y), this.SubtractionIntervalOp @@ -4375,6 +4461,7 @@ class F32Traits extends FPTraits { sixth: kValue.f32.negative.pi.sixth } }, + bias: 127, unboundedInterval: kF32UnboundedInterval, zeroInterval: kF32ZeroInterval, // Have to use the constants.ts values here, because values defined in the @@ -4389,6 +4476,7 @@ class F32Traits extends FPTraits { kValue.f32.positive.subnormal.min, kValue.f32.positive.max ), + negOneToOneInterval: new FPInterval('f32', -1, 1), zeroVector: { 2: [kF32ZeroInterval, kF32ZeroInterval], 3: [kF32ZeroInterval, kF32ZeroInterval, kF32ZeroInterval], @@ -4520,6 +4608,11 @@ class F32Traits extends FPTraits { flushSubnormal = flushSubnormalNumberF32; oneULP = oneULPF32; scalarBuilder = f32; + scalarRange = scalarF32Range; + sparseScalarRange = sparseScalarF32Range; + vectorRange = vectorF32Range; + sparseVectorRange = sparseVectorF32Range; + sparseMatrixRange = sparseMatrixF32Range; // Framework - Fundamental Error Intervals - Overrides absoluteErrorInterval = this.absoluteErrorIntervalImpl.bind(this); @@ -4686,7 +4779,7 @@ class F32Traits extends FPTraits { unpack2x16floatIntervalImpl(n) { assert( n >= kValue.u32.min && n <= kValue.u32.max, - 'unpack2x16floatInterval only accepts values on the bounds of u32' + 'unpack2x16floatInterval only accepts valid u32 values' ); this.unpackDataU32[0] = n; if (this.unpackDataF16.some((f) => !isFiniteF16(f))) { @@ -4710,7 +4803,7 @@ class F32Traits extends FPTraits { unpack2x16snormIntervalImpl(n) { assert( n >= kValue.u32.min && n <= kValue.u32.max, - 'unpack2x16snormInterval only accepts values on the bounds of u32' + 'unpack2x16snormInterval only accepts valid u32 values' ); const op = (n) => { return this.ulpInterval(Math.max(n / 32767, -1), 3); @@ -4726,7 +4819,7 @@ class F32Traits extends FPTraits { unpack2x16unormIntervalImpl(n) { assert( n >= kValue.u32.min && n <= kValue.u32.max, - 'unpack2x16unormInterval only accepts values on the bounds of u32' + 'unpack2x16unormInterval only accepts valid u32 values' ); const op = (n) => { return this.ulpInterval(n / 65535, 3); @@ -4742,7 +4835,7 @@ class F32Traits extends FPTraits { unpack4x8snormIntervalImpl(n) { assert( n >= kValue.u32.min && n <= kValue.u32.max, - 'unpack4x8snormInterval only accepts values on the bounds of u32' + 'unpack4x8snormInterval only accepts valid u32 values' ); const op = (n) => { return this.ulpInterval(Math.max(n / 127, -1), 3); @@ -4762,7 +4855,7 @@ class F32Traits extends FPTraits { unpack4x8unormIntervalImpl(n) { assert( n >= kValue.u32.min && n <= kValue.u32.max, - 'unpack4x8unormInterval only accepts values on the bounds of u32' + 'unpack4x8unormInterval only accepts valid u32 values' ); const op = (n) => { return this.ulpInterval(n / 255, 3); @@ -4836,6 +4929,7 @@ class FPAbstractTraits extends FPTraits { sixth: kValue.f64.negative.pi.sixth } }, + bias: 1023, unboundedInterval: kAbstractUnboundedInterval, zeroInterval: kAbstractZeroInterval, // Have to use the constants.ts values here, because values defined in the @@ -4850,6 +4944,8 @@ class FPAbstractTraits extends FPTraits { kValue.f64.positive.subnormal.min, kValue.f64.positive.max ), + negOneToOneInterval: new FPInterval('abstract', -1, 1), + zeroVector: { 2: [kAbstractZeroInterval, kAbstractZeroInterval], 3: [kAbstractZeroInterval, kAbstractZeroInterval, kAbstractZeroInterval], @@ -4992,14 +5088,17 @@ class FPAbstractTraits extends FPTraits { unreachable(`'FPAbstractTraits.oneULP should never be called`); }; scalarBuilder = abstractFloat; + scalarRange = scalarF64Range; + sparseScalarRange = sparseScalarF64Range; + vectorRange = vectorF64Range; + sparseVectorRange = sparseVectorF64Range; + sparseMatrixRange = sparseMatrixF64Range; // Framework - Fundamental Error Intervals - Overrides - absoluteErrorInterval = this.unboundedAbsoluteErrorInterval.bind(this); + absoluteErrorInterval = this.unimplementedAbsoluteErrorInterval.bind(this); // Should use FP.f32 instead correctlyRoundedInterval = this.correctlyRoundedIntervalImpl.bind(this); correctlyRoundedMatrix = this.correctlyRoundedMatrixImpl.bind(this); - ulpInterval = (n, numULP) => { - return this.toInterval(kF32Traits.ulpInterval(n, numULP)); - }; + ulpInterval = this.unimplementedUlpInterval.bind(this); // Should use FP.f32 instead // Framework - API - Overrides absInterval = this.absIntervalImpl.bind(this); @@ -5023,40 +5122,38 @@ class FPAbstractTraits extends FPTraits { 'atan2Interval' ); atanhInterval = this.unimplementedScalarToInterval.bind(this, 'atanhInterval'); - ceilInterval = this.unimplementedScalarToInterval.bind(this, 'ceilInterval'); + ceilInterval = this.ceilIntervalImpl.bind(this); clampMedianInterval = this.clampMedianIntervalImpl.bind(this); clampMinMaxInterval = this.clampMinMaxIntervalImpl.bind(this); clampIntervals = [this.clampMedianInterval, this.clampMinMaxInterval]; cosInterval = this.unimplementedScalarToInterval.bind(this, 'cosInterval'); coshInterval = this.unimplementedScalarToInterval.bind(this, 'coshInterval'); - crossInterval = this.crossIntervalImpl.bind(this); - degreesInterval = this.degreesIntervalImpl.bind(this); + crossInterval = this.unimplementedVectorPairToVector.bind(this, 'crossInterval'); + degreesInterval = this.unimplementedScalarToInterval.bind( + this, + 'degreesInterval' + ); determinantInterval = this.unimplementedMatrixToInterval.bind( this, - 'determinantInterval' + 'determinant' ); distanceInterval = this.unimplementedDistance.bind(this); - divisionInterval = ( - x, - y) => - { - return this.toInterval(kF32Traits.divisionInterval(x, y)); - }; + divisionInterval = this.unimplementedScalarPairToInterval.bind( + this, + 'divisionInterval' + ); dotInterval = this.unimplementedVectorPairToInterval.bind(this, 'dotInterval'); expInterval = this.unimplementedScalarToInterval.bind(this, 'expInterval'); exp2Interval = this.unimplementedScalarToInterval.bind(this, 'exp2Interval'); faceForwardIntervals = this.unimplementedFaceForward.bind(this); floorInterval = this.floorIntervalImpl.bind(this); - fmaInterval = this.fmaIntervalImpl.bind(this); - fractInterval = this.unimplementedScalarToInterval.bind(this, 'fractInterval'); + fmaInterval = this.unimplementedScalarTripleToInterval.bind(this, 'fmaInterval'); + fractInterval = this.fractIntervalImpl.bind(this); inverseSqrtInterval = this.unimplementedScalarToInterval.bind( this, 'inverseSqrtInterval' ); - ldexpInterval = this.unimplementedScalarPairToInterval.bind( - this, - 'ldexpInterval' - ); + ldexpInterval = this.ldexpIntervalImpl.bind(this); lengthInterval = this.unimplementedLength.bind(this); logInterval = this.unimplementedScalarToInterval.bind(this, 'logInterval'); log2Interval = this.unimplementedScalarToInterval.bind(this, 'log2Interval'); @@ -5077,14 +5174,10 @@ class FPAbstractTraits extends FPTraits { this, 'multiplicationMatrixMatrixInterval' ); - multiplicationMatrixScalarInterval = this.unimplementedMatrixScalarToMatrix.bind( - this, - 'multiplicationMatrixScalarInterval' - ); - multiplicationScalarMatrixInterval = this.unimplementedScalarMatrixToMatrix.bind( - this, - 'multiplicationScalarMatrixInterval' - ); + multiplicationMatrixScalarInterval = + this.multiplicationMatrixScalarIntervalImpl.bind(this); + multiplicationScalarMatrixInterval = + this.multiplicationScalarMatrixIntervalImpl.bind(this); multiplicationMatrixVectorInterval = this.unimplementedMatrixVectorToVector.bind( this, 'multiplicationMatrixVectorInterval' @@ -5099,16 +5192,17 @@ class FPAbstractTraits extends FPTraits { 'normalizeInterval' ); powInterval = this.unimplementedScalarPairToInterval.bind(this, 'powInterval'); - radiansInterval = this.radiansIntervalImpl.bind(this); + radiansInterval = this.unimplementedScalarToInterval.bind(this, 'radiansImpl'); reflectInterval = this.unimplementedVectorPairToVector.bind( this, 'reflectInterval' ); refractInterval = this.unimplementedRefract.bind(this); - remainderInterval = (x, y) => { - return this.toInterval(kF32Traits.remainderInterval(x, y)); - }; - roundInterval = this.unimplementedScalarToInterval.bind(this, 'roundInterval'); + remainderInterval = this.unimplementedScalarPairToInterval.bind( + this, + 'remainderInterval' + ); + roundInterval = this.roundIntervalImpl.bind(this); saturateInterval = this.saturateIntervalImpl.bind(this); signInterval = this.signIntervalImpl.bind(this); sinInterval = this.unimplementedScalarToInterval.bind(this, 'sinInterval'); @@ -5118,7 +5212,7 @@ class FPAbstractTraits extends FPTraits { 'smoothStepInterval' ); sqrtInterval = this.unimplementedScalarToInterval.bind(this, 'sqrtInterval'); - stepInterval = this.unimplementedScalarPairToInterval.bind(this, 'stepInterval'); + stepInterval = this.stepIntervalImpl.bind(this); subtractionInterval = this.subtractionIntervalImpl.bind(this); subtractionMatrixMatrixInterval = this.subtractionMatrixMatrixIntervalImpl.bind(this); @@ -5179,6 +5273,7 @@ class F16Traits extends FPTraits { sixth: kValue.f16.negative.pi.sixth } }, + bias: 15, unboundedInterval: kF16UnboundedInterval, zeroInterval: kF16ZeroInterval, // Have to use the constants.ts values here, because values defined in the @@ -5193,6 +5288,8 @@ class F16Traits extends FPTraits { kValue.f16.positive.subnormal.min, kValue.f16.positive.max ), + negOneToOneInterval: new FPInterval('f16', -1, 1), + zeroVector: { 2: [kF16ZeroInterval, kF16ZeroInterval], 3: [kF16ZeroInterval, kF16ZeroInterval, kF16ZeroInterval], @@ -5324,6 +5421,11 @@ class F16Traits extends FPTraits { flushSubnormal = flushSubnormalNumberF16; oneULP = oneULPF16; scalarBuilder = f16; + scalarRange = scalarF16Range; + sparseScalarRange = sparseScalarF16Range; + vectorRange = vectorF16Range; + sparseVectorRange = sparseVectorF16Range; + sparseMatrixRange = sparseMatrixF16Range; // Framework - Fundamental Error Intervals - Overrides absoluteErrorInterval = this.absoluteErrorIntervalImpl.bind(this); @@ -5437,5 +5539,6 @@ export function isRepresentable(value, type) { const constants = fpTraitsFor(type).constants(); return value >= constants.negative.min && value <= constants.positive.max; } + assert(false, `isRepresentable() is not yet implemented for type ${type}`); } \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/math.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/math.js index 873c4315ae..e44458cfbd 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/math.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/math.js @@ -413,6 +413,25 @@ export function oneULPF32(target, mode = 'flush') { } } +/** + * @returns an integer value between 0..0xffffffff using a simple non-cryptographic hash function + * @param values integers to generate hash from. + */ +export function hashU32(...values) { + let n = 0x3504_f333; + for (const v of values) { + n = v + (n << 7) + (n >>> 1); + n = n * 0x29493 & 0xffff_ffff; + } + n ^= n >>> 8; + n += n << 15; + n = n & 0xffff_ffff; + if (n < 0) { + n = ~n * 2 + 1; + } + return n; +} + /** * @returns ulp(x), the unit of least precision for a specific number as a 32-bit float * @@ -880,6 +899,41 @@ export function biasedRange(a, b, num_steps) { return Array.from(Array(num_steps).keys()).map((i) => lerp(a, b, Math.pow(i / (num_steps - 1), c))); } +/** + * Version of biasedRange that operates on bigint values + * + * biasedRange was not made into a generic or to take in (number|bigint), + * because that introduces a bunch of complexity overhead related to type + * differentiation. + * + * Scaling is used internally so that the number of possible indices is + * significantly larger than num_steps. This is done to avoid duplicate entries + * in the resulting range due to quantizing to integers during the calculation. + * + * If a and b are close together, such that the number of integers between them + * is close to num_steps, then duplicates will occur regardless of scaling. + */ +export function biasedRangeBigInt(a, b, num_steps) { + if (num_steps <= 0) { + return []; + } + + // Avoid division by 0 + if (num_steps === 1) { + return [a]; + } + + const c = 2; + const scaling = 1000; + const scaled_num_steps = num_steps * scaling; + + return Array.from(Array(num_steps).keys()).map((i) => { + const biased_i = Math.pow(i / (num_steps - 1), c); // Floating Point on [0, 1] + const scaled_i = Math.trunc((scaled_num_steps - 1) * biased_i); // Integer on [0, scaled_num_steps - 1] + return lerpBigInt(a, b, scaled_i, scaled_num_steps); + }); +} + /** * @returns an ascending sorted array of numbers spread over the entire range of 32-bit floats * @@ -891,12 +945,12 @@ export function biasedRange(a, b, num_steps) { * for a wide range of magnitudes to be generated, instead of being extremely biased towards the edges of the f32 range. * * This function is intended to provide dense coverage of the f32 range, for a minimal list of values to use to cover - * f32 behaviour, use sparseF32Range instead. + * f32 behaviour, use sparseScalarF32Range instead. * * @param counts structure param with 4 entries indicating the number of entries to be generated each region, entries * must be 0 or greater. */ -export function fullF32Range( +export function scalarF32Range( counts = @@ -943,8 +997,8 @@ counts = * @param low the lowest f32 value to permit when filtered * @param high the highest f32 value to permit when filtered */ -export function sourceFilteredF32Range(source, low, high) { - return fullF32Range().filter((x) => source !== 'const' || x >= low && x <= high); +export function filteredScalarF32Range(source, low, high) { + return scalarF32Range().filter((x) => source !== 'const' || x >= low && x <= high); } /** @@ -958,12 +1012,12 @@ export function sourceFilteredF32Range(source, low, high) { * for a wide range of magnitudes to be generated, instead of being extremely biased towards the edges of the f16 range. * * This function is intended to provide dense coverage of the f16 range, for a minimal list of values to use to cover - * f16 behaviour, use sparseF16Range instead. + * f16 behaviour, use sparseScalarF16Range instead. * * @param counts structure param with 4 entries indicating the number of entries to be generated each region, entries * must be 0 or greater. */ -export function fullF16Range( +export function scalarF16Range( counts = @@ -1009,12 +1063,12 @@ counts = * for a wide range of magnitudes to be generated, instead of being extremely biased towards the edges of the f64 range. * * This function is intended to provide dense coverage of the f64 range, for a minimal list of values to use to cover - * f64 behaviour, use sparseF64Range instead. + * f64 behaviour, use sparseScalarF64Range instead. * * @param counts structure param with 4 entries indicating the number of entries to be generated each region, entries * must be 0 or greater. */ -export function fullF64Range( +export function scalarF64Range( counts = @@ -1065,7 +1119,7 @@ counts = * @param counts structure param with 4 entries indicating the number of entries * to be generated each region, entries must be 0 or greater. */ -export function filteredF64Range( +export function limitedScalarF64Range( begin, end, counts = { @@ -1136,27 +1190,18 @@ export function sparseI32Range() { const kVectorI32Values = { 2: kInterestingI32Values.flatMap((f) => [ [f, 1], - [1, f], - [f, -1], [-1, f]] ), 3: kInterestingI32Values.flatMap((f) => [ - [f, 1, 2], - [1, f, 2], - [1, 2, f], - [f, -1, -2], - [-1, f, -2], - [-1, -2, f]] + [f, 1, -2], + [-1, f, 2], + [1, -2, f]] ), 4: kInterestingI32Values.flatMap((f) => [ - [f, 1, 2, 3], - [1, f, 2, 3], - [1, 2, f, 3], - [1, 2, 3, f], - [f, -1, -2, -3], - [-1, f, -2, -3], - [-1, -2, f, -3], - [-1, -2, -3, f]] + [f, -1, 2, 3], + [1, f, -2, 3], + [1, 2, f, -3], + [-1, 2, -3, f]] ) }; @@ -1178,6 +1223,38 @@ export function vectorI32Range(dim) { return kVectorI32Values[dim]; } +const kSparseVectorI32Values = { + 2: sparseI32Range().map((i, idx) => [idx % 2 === 0 ? i : idx, idx % 2 === 1 ? i : -idx]), + 3: sparseI32Range().map((i, idx) => [ + idx % 3 === 0 ? i : idx, + idx % 3 === 1 ? i : -idx, + idx % 3 === 2 ? i : idx] + ), + 4: sparseI32Range().map((i, idx) => [ + idx % 4 === 0 ? i : idx, + idx % 4 === 1 ? i : -idx, + idx % 4 === 2 ? i : idx, + idx % 4 === 3 ? i : -idx] + ) +}; + +/** + * Minimal set of vectors, indexed by dimension, that contain interesting + * abstract integer values. + * + * This is an even more stripped down version of `vectorI32Range` for when + * pairs of vectors are being tested. + * All interesting integers from sparseI32Range are guaranteed to be + * tested, but not in every position. + */ +export function sparseVectorI32Range(dim) { + assert( + dim === 2 || dim === 3 || dim === 4, + 'sparseVectorI32Range only accepts dimensions 2, 3, and 4' + ); + return kSparseVectorI32Values[dim]; +} + /** * @returns an ascending sorted array of numbers spread over the entire range of 32-bit signed ints * @@ -1256,6 +1333,38 @@ export function vectorU32Range(dim) { return kVectorU32Values[dim]; } +const kSparseVectorU32Values = { + 2: sparseU32Range().map((i, idx) => [idx % 2 === 0 ? i : idx, idx % 2 === 1 ? i : -idx]), + 3: sparseU32Range().map((i, idx) => [ + idx % 3 === 0 ? i : idx, + idx % 3 === 1 ? i : -idx, + idx % 3 === 2 ? i : idx] + ), + 4: sparseU32Range().map((i, idx) => [ + idx % 4 === 0 ? i : idx, + idx % 4 === 1 ? i : -idx, + idx % 4 === 2 ? i : idx, + idx % 4 === 3 ? i : -idx] + ) +}; + +/** + * Minimal set of vectors, indexed by dimension, that contain interesting + * abstract integer values. + * + * This is an even more stripped down version of `vectorU32Range` for when + * pairs of vectors are being tested. + * All interesting integers from sparseU32Range are guaranteed to be + * tested, but not in every position. + */ +export function sparseVectorU32Range(dim) { + assert( + dim === 2 || dim === 3 || dim === 4, + 'sparseVectorU32Range only accepts dimensions 2, 3, and 4' + ); + return kSparseVectorU32Values[dim]; +} + /** * @returns an ascending sorted array of numbers spread over the entire range of 32-bit unsigned ints * @@ -1267,6 +1376,124 @@ export function fullU32Range(count = 50) { return [0, ...biasedRange(1, kValue.u32.max, count)].map(Math.trunc); } +/** Short list of i64 values of interest to test against */ +const kInterestingI64Values = [ +kValue.i64.negative.max, +kValue.i64.negative.max / 2n, +-256n, +-10n, +-1n, +0n, +1n, +10n, +256n, +kValue.i64.positive.max / 2n, +kValue.i64.positive.max]; + + +/** @returns minimal i64 values that cover the entire range of i64 behaviours + * + * This is used instead of fullI64Range when the number of test cases being + * generated is a super linear function of the length of i64 values which is + * leading to time outs. + */ +export function sparseI64Range() { + return kInterestingI64Values; +} + +const kVectorI64Values = { + 2: kInterestingI64Values.flatMap((f) => [ + [f, 1n], + [-1n, f]] + ), + 3: kInterestingI64Values.flatMap((f) => [ + [f, 1n, -2n], + [-1n, f, 2n], + [1n, -2n, f]] + ), + 4: kInterestingI64Values.flatMap((f) => [ + [f, -1n, 2n, 3n], + [1n, f, -2n, 3n], + [1n, 2n, f, -3n], + [-1n, 2n, -3n, f]] + ) +}; + +/** + * Returns set of vectors, indexed by dimension containing interesting i64 + * values. + * + * The tests do not do the simple option for coverage of computing the cartesian + * product of all of the interesting i64 values N times for vecN tests, + * because that creates a huge number of tests for vec3 and vec4, leading to + * time outs. + * + * Instead they insert the interesting i64 values into each location of the + * vector to get a spread of testing over the entire range. This reduces the + * number of cases being run substantially, but maintains coverage. + */ +export function vectorI64Range(dim) { + assert(dim === 2 || dim === 3 || dim === 4, 'vectorI64Range only accepts dimensions 2, 3, and 4'); + return kVectorI64Values[dim]; +} + +const kSparseVectorI64Values = { + 2: sparseI64Range().map((i, idx) => [ + idx % 2 === 0 ? i : BigInt(idx), + idx % 2 === 1 ? i : -BigInt(idx)] + ), + 3: sparseI64Range().map((i, idx) => [ + idx % 3 === 0 ? i : BigInt(idx), + idx % 3 === 1 ? i : -BigInt(idx), + idx % 3 === 2 ? i : BigInt(idx)] + ), + 4: sparseI64Range().map((i, idx) => [ + idx % 4 === 0 ? i : BigInt(idx), + idx % 4 === 1 ? i : -BigInt(idx), + idx % 4 === 2 ? i : BigInt(idx), + idx % 4 === 3 ? i : -BigInt(idx)] + ) +}; + +/** + * Minimal set of vectors, indexed by dimension, that contain interesting + * abstract integer values. + * + * This is an even more stripped down version of `vectorI64Range` for when + * pairs of vectors are being tested. + * All interesting integers from sparseI64Range are guaranteed to be + * tested, but not in every position. + */ +export function sparseVectorI64Range(dim) { + assert( + dim === 2 || dim === 3 || dim === 4, + 'sparseVectorI64Range only accepts dimensions 2, 3, and 4' + ); + return kSparseVectorI64Values[dim]; +} + +/** + * @returns an ascending sorted array of numbers spread over the entire range of 64-bit signed ints + * + * Numbers are divided into 2 regions: negatives, and positives, with their spreads biased towards 0 + * Zero is included in range. + * + * @param counts structure param with 2 entries indicating the number of entries to be generated each region, values must be 0 or greater. + */ +export function fullI64Range( +counts = + + +{ positive: 50 }) +{ + counts.negative = counts.negative === undefined ? counts.positive : counts.negative; + return [ + ...biasedRangeBigInt(kValue.i64.negative.min, -1n, counts.negative), + 0n, + ...biasedRangeBigInt(1n, kValue.i64.positive.max, counts.positive)]; + +} + /** Short list of f32 values of interest to test against */ const kInterestingF32Values = [ kValue.f32.negative.min, @@ -1299,34 +1526,25 @@ kValue.f32.positive.max]; * specific values of interest. If there are known values of interest they * should be appended to this list in the test generation code. */ -export function sparseF32Range() { +export function sparseScalarF32Range() { return kInterestingF32Values; } const kVectorF32Values = { - 2: sparseF32Range().flatMap((f) => [ + 2: kInterestingF32Values.flatMap((f) => [ [f, 1.0], - [1.0, f], - [f, -1.0], [-1.0, f]] ), - 3: sparseF32Range().flatMap((f) => [ - [f, 1.0, 2.0], - [1.0, f, 2.0], - [1.0, 2.0, f], - [f, -1.0, -2.0], - [-1.0, f, -2.0], - [-1.0, -2.0, f]] + 3: kInterestingF32Values.flatMap((f) => [ + [f, 1.0, -2.0], + [-1.0, f, 2.0], + [1.0, -2.0, f]] ), - 4: sparseF32Range().flatMap((f) => [ - [f, 1.0, 2.0, 3.0], - [1.0, f, 2.0, 3.0], - [1.0, 2.0, f, 3.0], - [1.0, 2.0, 3.0, f], - [f, -1.0, -2.0, -3.0], - [-1.0, f, -2.0, -3.0], - [-1.0, -2.0, f, -3.0], - [-1.0, -2.0, -3.0, f]] + 4: kInterestingF32Values.flatMap((f) => [ + [f, -1.0, 2.0, 3.0], + [1.0, f, -2.0, 3.0], + [1.0, 2.0, f, -3.0], + [-1.0, 2.0, -3.0, f]] ) }; @@ -1349,13 +1567,13 @@ export function vectorF32Range(dim) { } const kSparseVectorF32Values = { - 2: sparseF32Range().map((f, idx) => [idx % 2 === 0 ? f : idx, idx % 2 === 1 ? f : -idx]), - 3: sparseF32Range().map((f, idx) => [ + 2: sparseScalarF32Range().map((f, idx) => [idx % 2 === 0 ? f : idx, idx % 2 === 1 ? f : -idx]), + 3: sparseScalarF32Range().map((f, idx) => [ idx % 3 === 0 ? f : idx, idx % 3 === 1 ? f : -idx, idx % 3 === 2 ? f : idx] ), - 4: sparseF32Range().map((f, idx) => [ + 4: sparseScalarF32Range().map((f, idx) => [ idx % 4 === 0 ? f : idx, idx % 4 === 1 ? f : -idx, idx % 4 === 2 ? f : idx, @@ -1369,8 +1587,8 @@ const kSparseVectorF32Values = { * * This is an even more stripped down version of `vectorF32Range` for when * pairs of vectors are being tested. - * All of the interesting floats from sparseF32 are guaranteed to be tested, but - * not in every position. + * All of the interesting floats from sparseScalarF32 are guaranteed to be + * tested, but not in every position. */ export function sparseVectorF32Range(dim) { assert( @@ -1480,16 +1698,16 @@ const kSparseMatrixF32Values = { }; /** - * Returns a minimal set of matrices, indexed by dimension containing interesting - * float values. + * Returns a minimal set of matrices, indexed by dimension containing + * interesting float values. * * This is the matrix analogue of `sparseVectorF32Range`, so it is producing a * minimal coverage set of matrices that test all of the interesting f32 values. * There is not a more expansive set of matrices, since matrices are even more * expensive than vectors for increasing runtime with coverage. * - * All of the interesting floats from sparseF32 are guaranteed to be tested, but - * not in every position. + * All of the interesting floats from sparseScalarF32 are guaranteed to be + * tested, but not in every position. */ export function sparseMatrixF32Range(c, r) { assert( @@ -1535,34 +1753,25 @@ kValue.f16.positive.max]; * specific values of interest. If there are known values of interest they * should be appended to this list in the test generation code. */ -export function sparseF16Range() { +export function sparseScalarF16Range() { return kInterestingF16Values; } const kVectorF16Values = { - 2: sparseF16Range().flatMap((f) => [ + 2: kInterestingF16Values.flatMap((f) => [ [f, 1.0], - [1.0, f], - [f, -1.0], [-1.0, f]] ), - 3: sparseF16Range().flatMap((f) => [ - [f, 1.0, 2.0], - [1.0, f, 2.0], - [1.0, 2.0, f], - [f, -1.0, -2.0], - [-1.0, f, -2.0], - [-1.0, -2.0, f]] + 3: kInterestingF16Values.flatMap((f) => [ + [f, 1.0, -2.0], + [-1.0, f, 2.0], + [1.0, -2.0, f]] ), - 4: sparseF16Range().flatMap((f) => [ - [f, 1.0, 2.0, 3.0], - [1.0, f, 2.0, 3.0], - [1.0, 2.0, f, 3.0], - [1.0, 2.0, 3.0, f], - [f, -1.0, -2.0, -3.0], - [-1.0, f, -2.0, -3.0], - [-1.0, -2.0, f, -3.0], - [-1.0, -2.0, -3.0, f]] + 4: kInterestingF16Values.flatMap((f) => [ + [f, -1.0, 2.0, 3.0], + [1.0, f, -2.0, 3.0], + [1.0, 2.0, f, -3.0], + [-1.0, 2.0, -3.0, f]] ) }; @@ -1585,13 +1794,13 @@ export function vectorF16Range(dim) { } const kSparseVectorF16Values = { - 2: sparseF16Range().map((f, idx) => [idx % 2 === 0 ? f : idx, idx % 2 === 1 ? f : -idx]), - 3: sparseF16Range().map((f, idx) => [ + 2: sparseScalarF16Range().map((f, idx) => [idx % 2 === 0 ? f : idx, idx % 2 === 1 ? f : -idx]), + 3: sparseScalarF16Range().map((f, idx) => [ idx % 3 === 0 ? f : idx, idx % 3 === 1 ? f : -idx, idx % 3 === 2 ? f : idx] ), - 4: sparseF16Range().map((f, idx) => [ + 4: sparseScalarF16Range().map((f, idx) => [ idx % 4 === 0 ? f : idx, idx % 4 === 1 ? f : -idx, idx % 4 === 2 ? f : idx, @@ -1605,8 +1814,8 @@ const kSparseVectorF16Values = { * * This is an even more stripped down version of `vectorF16Range` for when * pairs of vectors are being tested. - * All of the interesting floats from sparseF16 are guaranteed to be tested, but - * not in every position. + * All of the interesting floats from sparseScalarF16 are guaranteed to be + * tested, but not in every position. */ export function sparseVectorF16Range(dim) { assert( @@ -1724,7 +1933,7 @@ const kSparseMatrixF16Values = { * There is not a more expansive set of matrices, since matrices are even more * expensive than vectors for increasing runtime with coverage. * - * All of the interesting floats from sparseF16 are guaranteed to be tested, but + * All of the interesting floats from sparseScalarF16 are guaranteed to be tested, but * not in every position. */ export function sparseMatrixF16Range(c, r) { @@ -1771,34 +1980,25 @@ kValue.f64.positive.max]; * specific values of interest. If there are known values of interest they * should be appended to this list in the test generation code. */ -export function sparseF64Range() { +export function sparseScalarF64Range() { return kInterestingF64Values; } const kVectorF64Values = { - 2: sparseF64Range().flatMap((f) => [ + 2: kInterestingF64Values.flatMap((f) => [ [f, 1.0], - [1.0, f], - [f, -1.0], [-1.0, f]] ), - 3: sparseF64Range().flatMap((f) => [ - [f, 1.0, 2.0], - [1.0, f, 2.0], - [1.0, 2.0, f], - [f, -1.0, -2.0], - [-1.0, f, -2.0], - [-1.0, -2.0, f]] + 3: kInterestingF64Values.flatMap((f) => [ + [f, 1.0, -2.0], + [-1.0, f, 2.0], + [1.0, -2.0, f]] ), - 4: sparseF64Range().flatMap((f) => [ - [f, 1.0, 2.0, 3.0], - [1.0, f, 2.0, 3.0], - [1.0, 2.0, f, 3.0], - [1.0, 2.0, 3.0, f], - [f, -1.0, -2.0, -3.0], - [-1.0, f, -2.0, -3.0], - [-1.0, -2.0, f, -3.0], - [-1.0, -2.0, -3.0, f]] + 4: kInterestingF64Values.flatMap((f) => [ + [f, -1.0, 2.0, 3.0], + [1.0, f, -2.0, 3.0], + [1.0, 2.0, f, -3.0], + [-1.0, 2.0, -3.0, f]] ) }; @@ -1821,13 +2021,13 @@ export function vectorF64Range(dim) { } const kSparseVectorF64Values = { - 2: sparseF64Range().map((f, idx) => [idx % 2 === 0 ? f : idx, idx % 2 === 1 ? f : -idx]), - 3: sparseF64Range().map((f, idx) => [ + 2: sparseScalarF64Range().map((f, idx) => [idx % 2 === 0 ? f : idx, idx % 2 === 1 ? f : -idx]), + 3: sparseScalarF64Range().map((f, idx) => [ idx % 3 === 0 ? f : idx, idx % 3 === 1 ? f : -idx, idx % 3 === 2 ? f : idx] ), - 4: sparseF64Range().map((f, idx) => [ + 4: sparseScalarF64Range().map((f, idx) => [ idx % 4 === 0 ? f : idx, idx % 4 === 1 ? f : -idx, idx % 4 === 2 ? f : idx, @@ -1841,7 +2041,7 @@ const kSparseVectorF64Values = { * * This is an even more stripped down version of `vectorF64Range` for when * pairs of vectors are being tested. - * All the interesting floats from sparseF64 are guaranteed to be tested, but + * All the interesting floats from sparseScalarF64 are guaranteed to be tested, but * not in every position. */ export function sparseVectorF64Range(dim) { @@ -1960,19 +2160,19 @@ const kSparseMatrixF64Values = { * There is not a more expansive set of matrices, since matrices are even more * expensive than vectors for increasing runtime with coverage. * - * All the interesting floats from sparseF64 are guaranteed to be tested, but + * All the interesting floats from sparseScalarF64 are guaranteed to be tested, but * not in every position. */ -export function sparseMatrixF64Range(c, r) { +export function sparseMatrixF64Range(cols, rows) { assert( - c === 2 || c === 3 || c === 4, + cols === 2 || cols === 3 || cols === 4, 'sparseMatrixF64Range only accepts column counts of 2, 3, and 4' ); assert( - r === 2 || r === 3 || r === 4, + rows === 2 || rows === 3 || rows === 4, 'sparseMatrixF64Range only accepts row counts of 2, 3, and 4' ); - return kSparseMatrixF64Values[c][r]; + return kSparseMatrixF64Values[cols][rows]; } /** @@ -2051,11 +2251,25 @@ export function quantizeToU32(num) { return Math.trunc(num); } +/** + * @returns the closest 64-bit signed integer value to the input. + */ +export function quantizeToI64(num) { + if (num >= kValue.i64.positive.max) { + return kValue.i64.positive.max; + } + if (num <= kValue.i64.negative.min) { + return kValue.i64.negative.min; + } + return num; +} + /** @returns whether the number is an integer and a power of two */ export function isPowerOfTwo(n) { if (!Number.isInteger(n)) { return false; } + assert((n | 0) === n, 'isPowerOfTwo only supports 32-bit numbers'); return n !== 0 && (n & n - 1) === 0; } @@ -2244,4 +2458,33 @@ export function every2DArray(m, op) { `Unexpectedly received jagged array to map` ); return m.every((col) => col.every((el) => op(el))); +} + +/** + * Subtracts 2 vectors + */ +export function subtractVectors(v1, v2) { + return v1.map((v, i) => v - v2[i]); +} + +/** + * Computes the dot product of 2 vectors + */ +export function dotProduct(v1, v2) { + return v1.reduce((a, v, i) => a + v * v2[i], 0); +} + +/** @returns the absolute value of a bigint */ +export function absBigInt(v) { + return v < 0n ? -v : v; +} + +/** @returns the maximum from a list of bigints */ +export function maxBigInt(...vals) { + return vals.reduce((prev, cur) => cur > prev ? cur : prev); +} + +/** @returns the minimum from a list of bigints */ +export function minBigInt(...vals) { + return vals.reduce((prev, cur) => cur < prev ? cur : prev); } \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/pretty_diff_tables.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/pretty_diff_tables.js index 3803540fe9..a61fdb9e8b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/pretty_diff_tables.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/pretty_diff_tables.js @@ -1,6 +1,28 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { range } from '../../common/util/util.js'; /** + * @returns a function that converts numerics to strings, depending on if they + * should be treated as integers or not. + */ +export function numericToStringBuilder(is_integer) { + if (is_integer) { + return (val) => { + if (typeof val === 'number') { + return val.toFixed(); + } + return val.toString(); + }; + } + + return (val) => { + if (typeof val === 'number') { + return val.toPrecision(6); + } + return val.toString(); + }; +} + +/** * Pretty-prints a "table" of cell values (each being `number | string`), right-aligned. * Each row may be any iterator, including lazily-generated (potentially infinite) rows. * @@ -12,7 +34,10 @@ * Each remaining argument provides one row for the table. */ export function generatePrettyTable( -{ fillToWidth, numberToString }, +{ + fillToWidth, + numericToString +}, rows) { const rowStrings = range(rows.length, () => ''); @@ -23,7 +48,13 @@ rows) for (;;) { const cellsForColumn = iters.map((iter) => { const r = iter.next(); // Advance the iterator for each row, in lock-step. - return r.done ? undefined : typeof r.value === 'number' ? numberToString(r.value) : r.value; + if (r.done) { + return undefined; + } + if (typeof r.value === 'number' || typeof r.value === 'bigint') { + return numericToString(r.value); + } + return r.value; }); if (cellsForColumn.every((cell) => cell === undefined)) break; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/shader.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/shader.js index 51029e0c82..c4fd89c3af 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/shader.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/shader.js @@ -11,6 +11,27 @@ export const kDefaultFragmentShaderCode = ` return vec4(1.0, 1.0, 1.0, 1.0); }`; +// MAINTENANCE_TODO(#3344): deduplicate fullscreen quad shader code. +export const kFullscreenQuadVertexShaderCode = ` + struct VertexOutput { + @builtin(position) Position : vec4 + }; + + @vertex fn main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput { + var pos = array, 6>( + vec2( 1.0, 1.0), + vec2( 1.0, -1.0), + vec2(-1.0, -1.0), + vec2( 1.0, 1.0), + vec2(-1.0, -1.0), + vec2(-1.0, 1.0)); + + var output : VertexOutput; + output.Position = vec4(pos[VertexIndex], 0.0, 1.0); + return output; + } +`; + const kPlainTypeInfo = { i32: { suffix: '', @@ -157,6 +178,8 @@ fragDepth = null) }`; } +export const kValidShaderStages = ['compute', 'vertex', 'fragment']; + /** diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/base.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/base.js index 349a08a486..99636b9ad9 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/base.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/base.js @@ -157,15 +157,23 @@ export function viewDimensionsForTextureDimension(textureDimension) { } } -/** Returns the default view dimension for a given texture descriptor. */ -export function defaultViewDimensionsForTexture(textureDescriptor) { - switch (textureDescriptor.dimension) { +/** Returns the effective view dimension for a given texture dimension and depthOrArrayLayers */ +export function effectiveViewDimensionForDimension( +viewDimension, +dimension, +depthOrArrayLayers) +{ + if (viewDimension) { + return viewDimension; + } + + switch (dimension || '2d') { case '1d': return '1d'; - case '2d':{ - const sizeDict = reifyExtent3D(textureDescriptor.size); - return sizeDict.depthOrArrayLayers > 1 ? '2d-array' : '2d'; - } + case '2d': + case undefined: + return depthOrArrayLayers > 1 ? '2d-array' : '2d'; + break; case '3d': return '3d'; default: @@ -173,6 +181,28 @@ export function defaultViewDimensionsForTexture(textureDescriptor) { } } +/** Returns the effective view dimension for a given texture */ +export function effectiveViewDimensionForTexture( +texture, +viewDimension) +{ + return effectiveViewDimensionForDimension( + viewDimension, + texture.dimension, + texture.depthOrArrayLayers + ); +} + +/** Returns the default view dimension for a given texture descriptor. */ +export function defaultViewDimensionsForTexture(textureDescriptor) { + const sizeDict = reifyExtent3D(textureDescriptor.size); + return effectiveViewDimensionForDimension( + undefined, + textureDescriptor.dimension, + sizeDict.depthOrArrayLayers + ); +} + /** Reifies the optional fields of `GPUTextureDescriptor`. * MAINTENANCE_TODO: viewFormats should not be omitted here, but it seems likely that the * @webgpu/types definition will have to change before we can include it again. diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/color_space_conversions.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/color_space_conversions.spec.js new file mode 100644 index 0000000000..cc6c5201d8 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/color_space_conversions.spec.js @@ -0,0 +1,108 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = 'Color space conversion helpers';import { Fixture } from '../../../common/framework/fixture.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; +import { ErrorWithExtra } from '../../../common/util/util.js'; +import { makeInPlaceColorConversion } from '../color_space_conversion.js'; +import { clamp } from '../math.js'; + +import { TexelView } from './texel_view.js'; +import { findFailedPixels } from './texture_ok.js'; + +const kTestColors = [ +[0xff, 0, 0], +[0, 0xff, 0], +[0, 0, 0xff], +[0x80, 0x80, 0], +[0, 0x80, 0x80], +[0x80, 0, 0x80]]; + + +function floatToU8(v) { + return clamp(Math.round(v * 255), { min: 0, max: 255 }); +} + +export const g = makeTestGroup(Fixture); + +g.test('util_matches_2d_canvas'). +desc(`Test color space conversion helpers matches canvas 2d's color space conversion`). +params((u) => +u.combineWithParams([ +{ srcColorSpace: 'srgb', dstColorSpace: 'display-p3' }, +{ srcColorSpace: 'display-p3', dstColorSpace: 'srgb' }] +) +). +fn((t) => { + const { srcColorSpace, dstColorSpace } = t.params; + + // putImageData an ImageData(srcColorSpace) in to a canvas2D(dstColorSpace) + // then call getImageData. This will convert the colors via the canvas 2D API + const width = kTestColors.length; + const height = 1; + const imgData = new ImageData( + new Uint8ClampedArray(kTestColors.map((v) => [...v, 255]).flat()), + width, + height, + { colorSpace: srcColorSpace } + ); + const ctx = new OffscreenCanvas(width, height).getContext('2d', { + colorSpace: dstColorSpace + }); + ctx.putImageData(imgData, 0, 0); + const expectedData = ctx.getImageData(0, 0, width, height).data; + + const conversionFn = makeInPlaceColorConversion({ + srcPremultiplied: false, + dstPremultiplied: false, + srcColorSpace, + dstColorSpace + }); + + // Convert the data via our conversion functions + const convertedData = new Uint8ClampedArray( + kTestColors. + map((color) => { + const [R, G, B] = color.map((v) => v / 255); + const floatColor = { R, G, B, A: 1 }; + conversionFn(floatColor); + return [ + floatToU8(floatColor.R), + floatToU8(floatColor.G), + floatToU8(floatColor.B), + floatToU8(floatColor.A)]; + + }). + flat() + ); + + const subrectOrigin = [0, 0, 0]; + const subrectSize = [width, height, 1]; + const areaDesc = { + bytesPerRow: width * 4, + rowsPerImage: height, + subrectOrigin, + subrectSize + }; + + const format = 'rgba8unorm'; + const actTexelView = TexelView.fromTextureDataByReference(format, convertedData, areaDesc); + const expTexelView = TexelView.fromTextureDataByReference(format, expectedData, areaDesc); + + const failedPixelsMessage = findFailedPixels( + format, + { x: 0, y: 0, z: 0 }, + { width, height, depthOrArrayLayers: 1 }, + { actTexelView, expTexelView }, + { maxDiffULPsForNormFormat: 0 } + ); + + if (failedPixelsMessage !== undefined) { + const msg = 'Color space conversion had unexpected results:\n' + failedPixelsMessage; + t.expectOK( + new ErrorWithExtra(msg, () => ({ + expTexelView, + actTexelView + })) + ); + } +}); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.js index 602d642724..104ee0b19b 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.js @@ -1,6 +1,7 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { assert, unreachable } from '../../../common/util/util.js';import { +**/import { assert, unreachable } from '../../../common/util/util.js';import { kValue } from '../constants.js'; +import { assertInIntegerRange, float32ToFloatBits, float32ToFloat16Bits, @@ -424,6 +425,8 @@ opt) } const dataType = opt.signed ? 'snorm' : 'unorm'; + const min = opt.signed ? -1 : 0; + const max = 1; return { componentOrder, componentInfo: makePerTexelComponent(componentOrder, { @@ -438,7 +441,7 @@ opt) numberToBits, bitsToNumber, bitsToULPFromZero, - numericRange: { min: opt.signed ? -1 : 0, max: 1 } + numericRange: { min, max, finiteMin: min, finiteMax: max } }; } @@ -454,9 +457,9 @@ bitLength, opt) { assert(bitLength <= 32); - const numericRange = opt.signed ? - { min: -(2 ** (bitLength - 1)), max: 2 ** (bitLength - 1) - 1 } : - { min: 0, max: 2 ** bitLength - 1 }; + const min = opt.signed ? -(2 ** (bitLength - 1)) : 0; + const max = opt.signed ? 2 ** (bitLength - 1) - 1 : 2 ** bitLength - 1; + const numericRange = { min, max, finiteMin: min, finiteMax: max }; const maxUnsignedValue = 2 ** bitLength; const encode = applyEach( (n) => (assertInIntegerRange(n, bitLength, opt.signed), n), @@ -576,8 +579,13 @@ bitLength, bitsToNumber, bitsToULPFromZero, numericRange: restrictedDepth ? - { min: 0, max: 1 } : - { min: Number.NEGATIVE_INFINITY, max: Number.POSITIVE_INFINITY } + { min: 0, max: 1, finiteMin: 0, finiteMax: 1 } : + { + min: Number.NEGATIVE_INFINITY, + max: Number.POSITIVE_INFINITY, + finiteMin: bitLength === 32 ? kValue.f32.negative.min : kValue.f16.negative.min, + finiteMax: bitLength === 32 ? kValue.f32.positive.max : kValue.f16.positive.max + } }; } @@ -616,6 +624,12 @@ const kFloat10Format = { signed: 0, exponentBits: 5, mantissaBits: 5, bias: 15 } + + + + + + @@ -765,7 +779,7 @@ export const kTexelRepresentationInfo = A: normalizedIntegerAsFloat(components.A, 2, false) }), bitsToULPFromZero: (components) => components, - numericRange: { min: 0, max: 1 } + numericRange: { min: 0, max: 1, finiteMin: 0, finiteMax: 1 } }, rg11b10ufloat: { componentOrder: kRGB, @@ -809,7 +823,16 @@ export const kTexelRepresentationInfo = G: floatBitsToNormalULPFromZero(components.G, kFloat11Format), B: floatBitsToNormalULPFromZero(components.B, kFloat10Format) }), - numericRange: { min: 0, max: Number.POSITIVE_INFINITY } + numericRange: { + min: 0, + max: Number.POSITIVE_INFINITY, + finiteMin: 0, + finiteMax: { + R: floatBitsToNumber(0b111_1011_1111, kFloat11Format), + G: floatBitsToNumber(0b111_1011_1111, kFloat11Format), + B: floatBitsToNumber(0b11_1101_1111, kFloat10Format) + } + } }, rgb9e5ufloat: { componentOrder: kRGB, @@ -854,7 +877,12 @@ export const kTexelRepresentationInfo = G: floatBitsToNormalULPFromZero(components.G, kUFloat9e5Format), B: floatBitsToNormalULPFromZero(components.B, kUFloat9e5Format) }), - numericRange: { min: 0, max: Number.POSITIVE_INFINITY } + numericRange: { + min: 0, + max: Number.POSITIVE_INFINITY, + finiteMin: 0, + finiteMax: ufloatM9E5BitsToNumber(0b11_1111_1111_1111, kUFloat9e5Format) + } }, depth32float: makeFloatInfo([TexelComponent.Depth], 32, { restrictedDepth: true }), depth16unorm: makeNormalizedInfo([TexelComponent.Depth], 16, { signed: false, sRGB: false }), @@ -868,7 +896,7 @@ export const kTexelRepresentationInfo = numberToBits: () => unreachable('depth24plus has no representation'), bitsToNumber: () => unreachable('depth24plus has no representation'), bitsToULPFromZero: () => unreachable('depth24plus has no representation'), - numericRange: { min: 0, max: 1 } + numericRange: { min: 0, max: 1, finiteMin: 0, finiteMax: 1 } }, stencil8: makeIntegerInfo([TexelComponent.Stencil], 8, { signed: false }), 'depth32float-stencil8': { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.spec.js index d3d0d86fc2..ae985b0e84 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.spec.js @@ -297,7 +297,9 @@ fn(doTest); g.test('ufloat_texel_data_in_shader'). desc( ` -TODO: Test NaN, Infinity [1]` +Note: this uses values that are representable by both rg11b10ufloat and rgb9e5ufloat. + +TODO: Test NaN, Infinity` ). params((u) => u. @@ -312,21 +314,19 @@ expand('componentData', ({ format }) => { // Test extrema makeParam(format, () => 0), - // [2]: Test NaN, Infinity - // Test some values - makeParam(format, () => 0.119140625), - makeParam(format, () => 1.40625), - makeParam(format, () => 24896), + makeParam(format, () => 128), + makeParam(format, () => 1984), + makeParam(format, () => 3968), // Test scattered mixed values makeParam(format, (bitLength, i) => { - return [24896, 1.40625, 0.119140625, 0.23095703125][i]; + return [128, 1984, 3968][i]; }), // Test mixed values that are close in magnitude. makeParam(format, (bitLength, i) => { - return [0.1337890625, 0.17919921875, 0.119140625, 0.125][i]; + return [0.05859375, 0.03125, 0.03515625][i]; })]; }) diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_view.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_view.js index d5b0bd4b2a..e61baf99e4 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_view.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_view.js @@ -1,6 +1,6 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { assert, memcpy } from '../../../common/util/util.js';import { kTextureFormatInfo } from '../../format_info.js';import { generatePrettyTable } from '../pretty_diff_tables.js'; +**/import { assert, memcpy } from '../../../common/util/util.js';import { kTextureFormatInfo } from '../../format_info.js';import { generatePrettyTable, numericToStringBuilder } from '../pretty_diff_tables.js'; import { reifyExtent3D, reifyOrigin3D } from '../unions.js'; import { fullSubrectCoordinates } from './base.js'; @@ -166,10 +166,13 @@ export class TexelView { const info = kTextureFormatInfo[this.format]; const repr = kTexelRepresentationInfo[this.format]; - const integerSampleType = info.sampleType === 'uint' || info.sampleType === 'sint'; - const numberToString = integerSampleType ? - (n) => n.toFixed() : - (n) => n.toPrecision(6); + // MAINTENANCE_TODO: Print depth-stencil formats as float+int instead of float+float. + const printAsInteger = info.color ? + // For color, pick the type based on the format type + ['uint', 'sint'].includes(info.color.type) : + // Print depth as "float", depth-stencil as "float,float", stencil as "int". + !info.depth; + const numericToString = numericToStringBuilder(printAsInteger); const componentOrderStr = repr.componentOrder.join(',') + ':'; const subrectCoords = [...fullSubrectCoordinates(subrectOrigin, subrectSize)]; @@ -188,13 +191,13 @@ export class TexelView { yield* [' act. colors', '==', componentOrderStr]; for (const coords of subrectCoords) { const pixel = t.color(coords); - yield `${repr.componentOrder.map((ch) => numberToString(pixel[ch])).join(',')}`; + yield `${repr.componentOrder.map((ch) => numericToString(pixel[ch])).join(',')}`; } }(this); const opts = { fillToWidth: 120, - numberToString + numericToString }; return `${generatePrettyTable(opts, [printCoords, printActualBytes, printActualColors])}`; } diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.js index c2047df878..1c9428a602 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.js @@ -2,7 +2,7 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { assert, ErrorWithExtra, unreachable } from '../../../common/util/util.js';import { kTextureFormatInfo } from '../../format_info.js'; import { numbersApproximatelyEqual } from '../conversion.js'; -import { generatePrettyTable } from '../pretty_diff_tables.js'; +import { generatePrettyTable, numericToStringBuilder } from '../pretty_diff_tables.js'; import { reifyExtent3D, reifyOrigin3D } from '../unions.js'; import { fullSubrectCoordinates } from './base.js'; @@ -223,11 +223,13 @@ coords) const info = kTextureFormatInfo[format]; const repr = kTexelRepresentationInfo[format]; - - const integerSampleType = info.sampleType === 'uint' || info.sampleType === 'sint'; - const numberToString = integerSampleType ? - (n) => n.toFixed() : - (n) => n.toPrecision(6); + // MAINTENANCE_TODO: Print depth-stencil formats as float+int instead of float+float. + const printAsInteger = info.color ? + // For color, pick the type based on the format type + ['uint', 'sint'].includes(info.color.type) : + // Print depth as "float", depth-stencil as "float,float", stencil as "int". + !info.depth; + const numericToString = numericToStringBuilder(printAsInteger); const componentOrderStr = repr.componentOrder.join(',') + ':'; @@ -245,14 +247,14 @@ coords) yield* [' act. colors', '==', componentOrderStr]; for (const coords of failedPixels) { const pixel = actTexelView.color(coords); - yield `${repr.componentOrder.map((ch) => numberToString(pixel[ch])).join(',')}`; + yield `${repr.componentOrder.map((ch) => numericToString(pixel[ch])).join(',')}`; } }(); const printExpectedColors = function* () { yield* [' exp. colors', '==', componentOrderStr]; for (const coords of failedPixels) { const pixel = expTexelView.color(coords); - yield `${repr.componentOrder.map((ch) => numberToString(pixel[ch])).join(',')}`; + yield `${repr.componentOrder.map((ch) => numericToString(pixel[ch])).join(',')}`; } }(); const printActualULPs = function* () { @@ -272,7 +274,7 @@ coords) const opts = { fillToWidth: 120, - numberToString + numericToString }; return `\ between ${lowerCorner} and ${upperCorner} inclusive: diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/configure.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/configure.spec.js index 30acc8c9a7..32f979b6c1 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/configure.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/configure.spec.js @@ -13,7 +13,6 @@ import { GPUConst } from '../../constants.js'; import { kAllTextureFormats, kFeaturesForFormats, - kTextureFormats, filterFormatsByFeature, viewCompatible } from '../../format_info.js'; @@ -387,7 +386,7 @@ combine('format', kCanvasTextureFormats). combine('viewFormatFeature', kFeaturesForFormats). beginSubcases(). expand('viewFormat', ({ viewFormatFeature }) => -filterFormatsByFeature(viewFormatFeature, kTextureFormats) +filterFormatsByFeature(viewFormatFeature, kAllTextureFormats) ) ). beforeAllSubcases((t) => { @@ -402,7 +401,7 @@ fn((t) => { const ctx = canvas.getContext('webgpu'); assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas'); - const compatible = viewCompatible(format, viewFormat); + const compatible = viewCompatible(t.isCompatibility, format, viewFormat); // Test configure() produces an error if the formats aren't compatible. t.expectValidationError(() => { diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getCurrentTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getCurrentTexture.spec.js index 00e8c3ec24..729a7cdfaf 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getCurrentTexture.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getCurrentTexture.spec.js @@ -40,6 +40,27 @@ class GPUContextTest extends GPUTest { return ctx; } + + expectTextureDestroyed(texture, expectDestroyed = true) { + this.expectValidationError(() => { + // Try using the texture in a render pass. Because it's a canvas texture + // it should have RENDER_ATTACHMENT usage. + assert((texture.usage & GPUTextureUsage.RENDER_ATTACHMENT) !== 0); + const encoder = this.device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ + colorAttachments: [ + { + view: texture.createView(), + loadOp: 'clear', + storeOp: 'store' + }] + + }); + pass.end(); + // Submitting should generate a validation error if the texture is destroyed. + this.queue.submit([encoder.finish()]); + }, expectDestroyed); + } } export const g = makeTestGroup(GPUContextTest); @@ -170,7 +191,7 @@ fn((t) => { // Ensure that each frame a new texture object is returned. t.expect(currentTexture !== prevTexture); - // Ensure that texture contents are transparent black. + // Ensure that the texture's initial contents are transparent black. t.expectSingleColor(currentTexture, currentTexture.format, { size: [currentTexture.width, currentTexture.height, 1], exp: { R: 0, G: 0, B: 0, A: 0 } @@ -178,7 +199,8 @@ fn((t) => { } if (clearTexture) { - // Clear the texture to test that texture contents don't carry over from frame to frame. + // Fill the texture with a non-zero color, to test that texture + // contents don't carry over from frame to frame. const encoder = t.device.createCommandEncoder(); const pass = encoder.beginRenderPass({ colorAttachments: [ @@ -215,10 +237,8 @@ fn((t) => { } } - // Call frameCheck for the first time from requestAnimationFrame - // To make sure two frameChecks are run in different frames for onscreen canvas. - // offscreen canvas doesn't care. - requestAnimationFrame(frameCheck); + // Render the first frame immediately. The rest will be triggered recursively. + frameCheck(); }); }); @@ -235,6 +255,8 @@ fn((t) => { // Trigger a resize by changing the width. ctx.canvas.width = 4; + t.expectTextureDestroyed(prevTexture); + // When the canvas resizes the texture returned by getCurrentTexture should immediately begin // returning a new texture matching the update dimensions. let currentTexture = ctx.getCurrentTexture(); @@ -263,7 +285,6 @@ fn((t) => { t.expect(currentTexture.height === ctx.canvas.height); t.expect(prevTexture.width === 4); t.expect(prevTexture.height === 2); - prevTexture = currentTexture; // Ensure that texture contents are transparent black. t.expectSingleColor(currentTexture, currentTexture.format, { @@ -271,13 +292,31 @@ fn((t) => { exp: { R: 0, G: 0, B: 0, A: 0 } }); - // Simply setting the canvas width and height values to their current values should not trigger - // a change in the texture. - ctx.canvas.width = 4; - ctx.canvas.height = 4; - - currentTexture = ctx.getCurrentTexture(); - t.expect(prevTexture === currentTexture); + // HTMLCanvasElement behaves differently than OffscreenCanvas + if (t.params.canvasType === 'onscreen') { + // Ensure canvas goes back to defaults when set to negative numbers. + ctx.canvas.width = -1; + currentTexture = ctx.getCurrentTexture(); + t.expect(currentTexture.width === 300); + t.expect(currentTexture.height === 4); + + ctx.canvas.height = -1; + currentTexture = ctx.getCurrentTexture(); + t.expect(currentTexture.width === 300); + t.expect(currentTexture.height === 150); + + // Setting the canvas width and height values to their current values should + // still trigger a change in the texture. + prevTexture = ctx.getCurrentTexture(); + const { width, height } = ctx.canvas; + ctx.canvas.width = width; + ctx.canvas.height = height; + + t.expectTextureDestroyed(prevTexture); + + currentTexture = ctx.getCurrentTexture(); + t.expect(prevTexture !== currentTexture); + } }); g.test('expiry'). @@ -307,6 +346,14 @@ u // combine('prevFrameCallsite', ['runInNewCanvasFrame', 'requestAnimationFrame']). combine('getCurrentTextureAgain', [true, false]) ). +beforeAllSubcases((t) => { + if ( + t.params.prevFrameCallsite === 'requestAnimationFrame' && + typeof requestAnimationFrame === 'undefined') + { + throw new SkipTestCase('requestAnimationFrame not available'); + } +}). fn((t) => { const { canvasType, prevFrameCallsite, getCurrentTextureAgain } = t.params; const ctx = t.initCanvasContext(t.params.canvasType); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js index 05b422f8ea..e88d9d807a 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js @@ -14,7 +14,12 @@ The contents of A and B should match. TODO: implement all canvas types, see TODO on kCanvasTypes. `;import { makeTestGroup } from '../../../common/framework/test_group.js'; -import { assert, raceWithRejectOnTimeout, unreachable } from '../../../common/util/util.js'; +import { + ErrorWithExtra, + assert, + raceWithRejectOnTimeout, + unreachable } from +'../../../common/util/util.js'; import { kCanvasAlphaModes, kCanvasColorSpaces, @@ -26,8 +31,11 @@ import { kAllCanvasTypes, createCanvas, - createOnscreenCanvas } from + createOnscreenCanvas, + createOffscreenCanvas } from '../../util/create_elements.js'; +import { TexelView } from '../../util/texture/texel_view.js'; +import { findFailedPixels } from '../../util/texture/texture_ok.js'; export const g = makeTestGroup(GPUTest); @@ -61,6 +69,26 @@ const expect = { ]) }; +/** + * Given 4 pixels in rgba8unorm format, puts them into an ImageData + * of the specified color space and then puts them into an srgb color space + * canvas (the default). If the color space is different there will be a + * conversion. Returns the resulting 4 pixels in rgba8unorm format. + */ +function convertRGBA8UnormBytesToColorSpace( +expected, +srcColorSpace, +dstColorSpace) +{ + const srcImgData = new ImageData(2, 2, { colorSpace: srcColorSpace }); + srcImgData.data.set(expected); + const dstCanvas = new OffscreenCanvas(2, 2); + const dstCtx = dstCanvas.getContext('2d', { colorSpace: dstColorSpace }); + assert(dstCtx !== null); + dstCtx.putImageData(srcImgData, 0, 0); + return dstCtx.getImageData(0, 0, 2, 2).data; +} + function initWebGPUCanvasContent( t, format, @@ -119,7 +147,7 @@ t, image, colorSpace) { - const canvas = createOnscreenCanvas(t, 2, 2); + const canvas = createOffscreenCanvas(t, 2, 2); const ctx = canvas.getContext('2d', { colorSpace }); assert(ctx !== null); ctx.drawImage(image, 0, 0); @@ -147,22 +175,13 @@ sourceData) // draw the WebGPU derived data into a canvas const fromWebGPUCtx = drawImageSourceIntoCanvas(t, image, destinationColorSpace); - // create a 2D canvas with the same source data in the same color space as the WebGPU - // canvas - const source2DCanvas = createOnscreenCanvas(t, 2, 2); - const source2DCtx = source2DCanvas.getContext('2d', { colorSpace: sourceColorSpace }); - assert(source2DCtx !== null); - const imgData = source2DCtx.getImageData(0, 0, 2, 2); - imgData.data.set(sourceData); - source2DCtx.putImageData(imgData, 0, 0); - - // draw the source 2D canvas into another 2D canvas with the destination color space and - // then pull out the data. This result should be the same as the WebGPU derived data - // written to a 2D canvas of the same destination color space. - const from2DCtx = drawImageSourceIntoCanvas(t, source2DCanvas, destinationColorSpace); - const expect = from2DCtx.getImageData(0, 0, 2, 2).data; - - readPixelsFrom2DCanvasAndCompare(t, fromWebGPUCtx, expect); + const expect = convertRGBA8UnormBytesToColorSpace( + sourceData, + sourceColorSpace, + destinationColorSpace + ); + + readPixelsFrom2DCanvasAndCompare(t, fromWebGPUCtx, expect, 2); } function checkImageResult( @@ -171,18 +190,55 @@ image, sourceColorSpace, expect) { + // canvas(colorSpace)->img(colorSpace)->canvas(colorSpace).drawImage->canvas(colorSpace).getImageData->actual + // hard coded data->expected checkImageResultWithSameColorSpaceCanvas(t, image, sourceColorSpace, expect); + + // canvas(colorSpace)->img(colorSpace)->canvas(diffColorSpace).drawImage->canvas(diffColorSpace).getImageData->actual + // hard coded data->ImageData(colorSpace)->canvas(diffColorSpace).putImageData->canvas(diffColorSpace).getImageData->expected checkImageResultWithDifferentColorSpaceCanvas(t, image, sourceColorSpace, expect); } function readPixelsFrom2DCanvasAndCompare( t, ctx, -expect) +expect, +maxDiffULPsForNormFormat = 0) { - const actual = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height).data; + const { width, height } = ctx.canvas; + const actual = ctx.getImageData(0, 0, width, height).data; + + const subrectOrigin = [0, 0, 0]; + const subrectSize = [width, height, 1]; + + const areaDesc = { + bytesPerRow: width * 4, + rowsPerImage: height, + subrectOrigin, + subrectSize + }; + + const format = 'rgba8unorm'; + const actTexelView = TexelView.fromTextureDataByReference(format, actual, areaDesc); + const expTexelView = TexelView.fromTextureDataByReference(format, expect, areaDesc); + + const failedPixelsMessage = findFailedPixels( + format, + { x: 0, y: 0, z: 0 }, + { width, height, depthOrArrayLayers: 1 }, + { actTexelView, expTexelView }, + { maxDiffULPsForNormFormat } + ); - t.expectOK(checkElementsEqual(actual, expect)); + if (failedPixelsMessage !== undefined) { + const msg = 'Canvas had unexpected contents:\n' + failedPixelsMessage; + t.expectOK( + new ErrorWithExtra(msg, () => ({ + expTexelView, + actTexelView + })) + ); + } } g.test('onscreenCanvas,snapshot'). @@ -284,11 +340,7 @@ fn(async (t) => { return; } const blob = await offscreenCanvas.convertToBlob(); - const url = URL.createObjectURL(blob); - const img = new Image(offscreenCanvas.width, offscreenCanvas.height); - img.src = url; - await raceWithRejectOnTimeout(img.decode(), 5000, 'load image timeout'); - snapshot = img; + snapshot = await createImageBitmap(blob); break; } case 'transferToImageBitmap':{ @@ -383,6 +435,19 @@ desc( - colorSpace = {"srgb", "display-p3"} - WebGPU canvas type = {"onscreen", "offscreen"} - 2d canvas type = {"onscreen", "offscreen"} + + + * makes a webgpu canvas with the given colorSpace and puts data in via copy convoluted + copy process + * makes a 2d canvas with 'srgb' colorSpace (the default) + * draws the webgpu canvas into the 2d canvas so if the color spaces do not match + there will be a conversion. + * gets the pixels from the 2d canvas via getImageData + * compares them to hard coded values that are converted to expected values by copying + to an ImageData of the given color space, and then using putImageData into an srgb canvas. + + canvas(colorSpace) -> canvas(srgb).drawImage -> canvas(srgb).getImageData -> actual + ImageData(colorSpace) -> canvas(srgb).putImageData -> canvas(srgb).getImageData -> expected ` ). params((u) => @@ -396,35 +461,47 @@ combine('canvas2DType', kAllCanvasTypes) fn((t) => { const { format, webgpuCanvasType, alphaMode, colorSpace, canvas2DType } = t.params; - const canvas = initWebGPUCanvasContent(t, format, alphaMode, colorSpace, webgpuCanvasType); + const webgpuCanvas = initWebGPUCanvasContent( + t, + format, + alphaMode, + colorSpace, + webgpuCanvasType + ); - const expectCanvas = createCanvas(t, canvas2DType, canvas.width, canvas.height); - const ctx = expectCanvas.getContext('2d'); + const actualCanvas = createCanvas(t, canvas2DType, webgpuCanvas.width, webgpuCanvas.height); + const ctx = actualCanvas.getContext('2d'); if (ctx === null) { t.skip(canvas2DType + ' canvas cannot get 2d context'); return; } - ctx.drawImage(canvas, 0, 0); - readPixelsFrom2DCanvasAndCompare(t, ctx, expect[t.params.alphaMode]); + ctx.drawImage(webgpuCanvas, 0, 0); + + readPixelsFrom2DCanvasAndCompare( + t, + ctx, + convertRGBA8UnormBytesToColorSpace(expect[t.params.alphaMode], colorSpace, 'srgb') + ); }); g.test('transferToImageBitmap_unconfigured_nonzero_size'). desc( `Regression test for a crash when calling transferImageBitmap on an unconfigured. Case where the canvas is not empty` ). +params((u) => u.combine('readbackCanvasType', ['onscreen', 'offscreen'])). fn((t) => { - const canvas = createCanvas(t, 'offscreen', 2, 3); + const kWidth = 2; + const kHeight = 3; + const canvas = createCanvas(t, 'offscreen', kWidth, kHeight); canvas.getContext('webgpu'); // Transferring gives an ImageBitmap of the correct size filled with transparent black. const ib = canvas.transferToImageBitmap(); - t.expect(ib.width === canvas.width); - t.expect(ib.height === canvas.height); + t.expect(ib.width === kWidth); + t.expect(ib.height === kHeight); - const readbackCanvas = document.createElement('canvas'); - readbackCanvas.width = canvas.width; - readbackCanvas.height = canvas.height; + const readbackCanvas = createCanvas(t, t.params.readbackCanvasType, kWidth, kHeight); const readbackContext = readbackCanvas.getContext('2d', { alpha: true }); @@ -434,7 +511,7 @@ fn((t) => { } // Since there isn't a configuration we expect the ImageBitmap to have the default alphaMode of "opaque". - const expected = new Uint8ClampedArray(canvas.width * canvas.height * 4); + const expected = new Uint8ClampedArray(kWidth * kHeight * 4); for (let i = 0; i < expected.byteLength; i += 4) { expected[i + 0] = 0; expected[i + 1] = 0; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/canvas.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/canvas.spec.js index a8176f0613..16133fb8f9 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/canvas.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/canvas.spec.js @@ -97,8 +97,6 @@ class F extends CopyToTextureUtils { } const imageData = new ImageData(imagePixels, width, height, { colorSpace }); - // MAINTENANCE_TODO: Remove as any when tsc support imageData.colorSpace - if (typeof imageData.colorSpace === 'undefined') { this.skip('color space attr is not supported for ImageData'); } @@ -762,7 +760,7 @@ desc( params((u) => u. combine('srcColorSpace', ['srgb', 'display-p3']). -combine('dstColorSpace', ['srgb']). +combine('dstColorSpace', ['srgb', 'display-p3']). combine('dstColorFormat', kValidTextureFormatsForCopyE2T). combine('dstPremultiplied', [true, false]). combine('srcDoFlipYDuringCopy', [true, false]). diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/video.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/video.spec.js index 9df16bf5ef..e156a6170d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/video.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/video.spec.js @@ -3,15 +3,21 @@ **/export const description = ` copyToTexture with HTMLVideoElement and VideoFrame. -- videos with various encodings/formats (webm vp8, webm vp9, ogg theora, mp4), color spaces - (bt.601, bt.709, bt.2020) +- videos with various encodings/formats (webm vp8, webm vp9, ogg theora, mp4), video color spaces + (bt.601, bt.709, bt.2020) and dst color spaces(display-p3, srgb). + + TODO: Test video in BT.2020 color space `;import { makeTestGroup } from '../../../common/framework/test_group.js'; import { GPUTest, TextureTestMixin } from '../../gpu_test.js'; import { startPlayingAndWaitForVideo, getVideoElement, getVideoFrameFromVideoElement, - kVideoExpectations } from + convertToUnorm8, + kPredefinedColorSpace, + kVideoNames, + kVideoInfo, + kVideoExpectedColors } from '../../web_platform/util.js'; const kFormat = 'rgba8unorm'; @@ -36,17 +42,17 @@ It creates HTMLVideoElement with videos under Resource folder. - Valid 'flipY' config in 'GPUImageCopyExternalImage' (named 'srcDoFlipYDuringCopy' in cases) - TODO: partial copy tests should be added - TODO: all valid dstColorFormat tests should be added. - - TODO: dst color space tests need to be added ` ). params((u) => u // -.combineWithParams(kVideoExpectations). +.combine('videoName', kVideoNames). combine('sourceType', ['VideoElement', 'VideoFrame']). -combine('srcDoFlipYDuringCopy', [true, false]) +combine('srcDoFlipYDuringCopy', [true, false]). +combine('dstColorSpace', kPredefinedColorSpace) ). fn(async (t) => { - const { videoName, sourceType, srcDoFlipYDuringCopy } = t.params; + const { videoName, sourceType, srcDoFlipYDuringCopy, dstColorSpace } = t.params; if (sourceType === 'VideoFrame' && typeof VideoFrame === 'undefined') { t.skip('WebCodec is not supported'); @@ -58,8 +64,8 @@ fn(async (t) => { let source, width, height; if (sourceType === 'VideoFrame') { source = await getVideoFrameFromVideoElement(t, videoElement); - width = source.codedWidth; - height = source.codedHeight; + width = source.displayWidth; + height = source.displayHeight; } else { source = videoElement; width = source.videoWidth; @@ -82,33 +88,63 @@ fn(async (t) => { { texture: dstTexture, origin: { x: 0, y: 0 }, - colorSpace: 'srgb', + colorSpace: dstColorSpace, premultipliedAlpha: true }, { width, height, depthOrArrayLayers: 1 } ); + const srcColorSpace = kVideoInfo[videoName].colorSpace; + const presentColors = kVideoExpectedColors[srcColorSpace][dstColorSpace]; + + // visible rect is whole frame, no clipping. + const expect = kVideoInfo[videoName].display; + if (srcDoFlipYDuringCopy) { t.expectSinglePixelComparisonsAreOkInTexture({ texture: dstTexture }, [ - // Top-left should be blue. - { coord: { x: width * 0.25, y: height * 0.25 }, exp: t.params._blueExpectation }, - // Top-right should be green. - { coord: { x: width * 0.75, y: height * 0.25 }, exp: t.params._greenExpectation }, - // Bottom-left should be yellow. - { coord: { x: width * 0.25, y: height * 0.75 }, exp: t.params._yellowExpectation }, - // Bottom-right should be red. - { coord: { x: width * 0.75, y: height * 0.75 }, exp: t.params._redExpectation }] + // Flipped top-left. + { + coord: { x: width * 0.25, y: height * 0.25 }, + exp: convertToUnorm8(presentColors[expect.bottomLeftColor]) + }, + // Flipped top-right. + { + coord: { x: width * 0.75, y: height * 0.25 }, + exp: convertToUnorm8(presentColors[expect.bottomRightColor]) + }, + // Flipped bottom-left. + { + coord: { x: width * 0.25, y: height * 0.75 }, + exp: convertToUnorm8(presentColors[expect.topLeftColor]) + }, + // Flipped bottom-right. + { + coord: { x: width * 0.75, y: height * 0.75 }, + exp: convertToUnorm8(presentColors[expect.topRightColor]) + }] ); } else { t.expectSinglePixelComparisonsAreOkInTexture({ texture: dstTexture }, [ - // Top-left should be yellow. - { coord: { x: width * 0.25, y: height * 0.25 }, exp: t.params._yellowExpectation }, - // Top-right should be red. - { coord: { x: width * 0.75, y: height * 0.25 }, exp: t.params._redExpectation }, - // Bottom-left should be blue. - { coord: { x: width * 0.25, y: height * 0.75 }, exp: t.params._blueExpectation }, - // Bottom-right should be green. - { coord: { x: width * 0.75, y: height * 0.75 }, exp: t.params._greenExpectation }] + // Top-left. + { + coord: { x: width * 0.25, y: height * 0.25 }, + exp: convertToUnorm8(presentColors[expect.topLeftColor]) + }, + // Top-right. + { + coord: { x: width * 0.75, y: height * 0.25 }, + exp: convertToUnorm8(presentColors[expect.topRightColor]) + }, + // Bottom-left. + { + coord: { x: width * 0.25, y: height * 0.75 }, + exp: convertToUnorm8(presentColors[expect.bottomLeftColor]) + }, + // Bottom-right. + { + coord: { x: width * 0.75, y: height * 0.75 }, + exp: convertToUnorm8(presentColors[expect.bottomRightColor]) + }] ); } diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/external_texture/video.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/external_texture/video.spec.js index 80acbb5d5e..54434898e9 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/external_texture/video.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/external_texture/video.spec.js @@ -3,18 +3,23 @@ **/export const description = ` Tests for external textures from HTMLVideoElement (and other video-type sources?). -- videos with various encodings/formats (webm vp8, webm vp9, ogg theora, mp4), color spaces - (bt.601, bt.709, bt.2020) +- videos with various encodings/formats (webm vp8, webm vp9, ogg theora, mp4), video color spaces + (bt.601, bt.709, bt.2020) and dst color spaces(display-p3, srgb) TODO: consider whether external_texture and copyToTexture video tests should be in the same file +TODO(#3193): Test video in BT.2020 color space `;import { makeTestGroup } from '../../../common/framework/test_group.js'; import { GPUTest, TextureTestMixin } from '../../gpu_test.js'; +import { createCanvas } from '../../util/create_elements.js'; import { startPlayingAndWaitForVideo, getVideoFrameFromVideoElement, getVideoElement, - kVideoExpectations, - kVideoRotationExpectations } from + convertToUnorm8, + kPredefinedColorSpace, + kVideoNames, + kVideoInfo, + kVideoExpectedColors } from '../../web_platform/util.js'; const kHeight = 16; @@ -23,7 +28,10 @@ const kFormat = 'rgba8unorm'; export const g = makeTestGroup(TextureTestMixin(GPUTest)); -function createExternalTextureSamplingTestPipeline(t) { +function createExternalTextureSamplingTestPipeline( +t, +colorAttachmentFormat = kFormat) +{ const pipeline = t.device.createRenderPipeline({ layout: 'auto', vertex: { @@ -59,7 +67,7 @@ function createExternalTextureSamplingTestPipeline(t) { entryPoint: 'main', targets: [ { - format: kFormat + format: colorAttachmentFormat }] }, @@ -73,13 +81,14 @@ function createExternalTextureSamplingTestBindGroup( t, checkNonStandardIsZeroCopy, source, -pipeline) +pipeline, +dstColorSpace) { const linearSampler = t.device.createSampler(); const externalTexture = t.device.importExternalTexture({ - - source: source + source, + colorSpace: dstColorSpace }); if (checkNonStandardIsZeroCopy) { @@ -133,22 +142,24 @@ g.test('importExternalTexture,sample'). desc( ` Tests that we can import an HTMLVideoElement/VideoFrame into a GPUExternalTexture, sample from it -for several combinations of video format and color space. +for several combinations of video format, video color spaces and dst color spaces. ` ). params((u) => u // .combineWithParams(checkNonStandardIsZeroCopyIfAvailable()). +combine('videoName', kVideoNames). combine('sourceType', ['VideoElement', 'VideoFrame']). -combineWithParams(kVideoExpectations) +combine('dstColorSpace', kPredefinedColorSpace) ). fn(async (t) => { - const sourceType = t.params.sourceType; + const { videoName, sourceType, dstColorSpace } = t.params; + if (sourceType === 'VideoFrame' && typeof VideoFrame === 'undefined') { t.skip('WebCodec is not supported'); } - const videoElement = getVideoElement(t, t.params.videoName); + const videoElement = getVideoElement(t, videoName); await startPlayingAndWaitForVideo(videoElement, async () => { const source = @@ -167,7 +178,8 @@ fn(async (t) => { t, t.params.checkNonStandardIsZeroCopy, source, - pipeline + pipeline, + dstColorSpace ); const commandEncoder = t.device.createCommandEncoder(); @@ -187,88 +199,162 @@ fn(async (t) => { passEncoder.end(); t.device.queue.submit([commandEncoder.finish()]); + const srcColorSpace = kVideoInfo[videoName].colorSpace; + const presentColors = kVideoExpectedColors[srcColorSpace][dstColorSpace]; + + // visible rect is whole frame, no clipping. + const expect = kVideoInfo[videoName].display; + // For validation, we sample a few pixels away from the edges to avoid compression // artifacts. t.expectSinglePixelComparisonsAreOkInTexture({ texture: colorAttachment }, [ - // Top-left should be yellow. - { coord: { x: kWidth * 0.25, y: kHeight * 0.25 }, exp: t.params._yellowExpectation }, - // Top-right should be red. - { coord: { x: kWidth * 0.75, y: kHeight * 0.25 }, exp: t.params._redExpectation }, - // Bottom-left should be blue. - { coord: { x: kWidth * 0.25, y: kHeight * 0.75 }, exp: t.params._blueExpectation }, - // Bottom-right should be green. - { coord: { x: kWidth * 0.75, y: kHeight * 0.75 }, exp: t.params._greenExpectation }] + // Top-left. + { + coord: { x: kWidth * 0.25, y: kHeight * 0.25 }, + exp: convertToUnorm8(presentColors[expect.topLeftColor]) + }, + // Top-right. + { + coord: { x: kWidth * 0.75, y: kHeight * 0.25 }, + exp: convertToUnorm8(presentColors[expect.topRightColor]) + }, + // Bottom-left. + { + coord: { x: kWidth * 0.25, y: kHeight * 0.75 }, + exp: convertToUnorm8(presentColors[expect.bottomLeftColor]) + }, + // Bottom-right. + { + coord: { x: kWidth * 0.75, y: kHeight * 0.75 }, + exp: convertToUnorm8(presentColors[expect.bottomRightColor]) + }] ); - - if (sourceType === 'VideoFrame') source.close(); }); }); -g.test('importExternalTexture,sampleWithRotationMetadata'). +g.test('importExternalTexture,sample_non_YUV_video_frame'). desc( ` -Tests that when importing an HTMLVideoElement/VideoFrame into a GPUExternalTexture, sampling from -it will honor rotation metadata. +Tests that we can import an VideoFrame with non-YUV pixel format into a GPUExternalTexture and sample it. ` ). params((u) => u // -.combineWithParams(checkNonStandardIsZeroCopyIfAvailable()). -combine('sourceType', ['VideoElement', 'VideoFrame']). -combineWithParams(kVideoRotationExpectations) +.combine('videoFrameFormat', ['RGBA', 'RGBX', 'BGRA', 'BGRX']) ). -fn(async (t) => { - const sourceType = t.params.sourceType; - const videoElement = getVideoElement(t, t.params.videoName); +fn((t) => { + const { videoFrameFormat } = t.params; - await startPlayingAndWaitForVideo(videoElement, async () => { - const source = - sourceType === 'VideoFrame' ? - await getVideoFrameFromVideoElement(t, videoElement) : - videoElement; + if (typeof VideoFrame === 'undefined') { + t.skip('WebCodec is not supported'); + } - const colorAttachment = t.device.createTexture({ - format: kFormat, - size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 }, - usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT - }); + const canvas = createCanvas(t, 'onscreen', kWidth, kHeight); - const pipeline = createExternalTextureSamplingTestPipeline(t); - const bindGroup = createExternalTextureSamplingTestBindGroup( - t, - t.params.checkNonStandardIsZeroCopy, - source, - pipeline - ); + const canvasContext = canvas.getContext('2d'); - const commandEncoder = t.device.createCommandEncoder(); - const passEncoder = commandEncoder.beginRenderPass({ - colorAttachments: [ - { - view: colorAttachment.createView(), - clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }, - loadOp: 'clear', - storeOp: 'store' - }] + if (canvasContext === null) { + t.skip(' onscreen canvas 2d context not available'); + } - }); - passEncoder.setPipeline(pipeline); - passEncoder.setBindGroup(0, bindGroup); - passEncoder.draw(6); - passEncoder.end(); - t.device.queue.submit([commandEncoder.finish()]); + const ctx = canvasContext; + + const rectWidth = Math.floor(kWidth / 2); + const rectHeight = Math.floor(kHeight / 2); + + // Red + ctx.fillStyle = `rgba(255, 0, 0, 1.0)`; + ctx.fillRect(0, 0, rectWidth, rectHeight); + // Lime + ctx.fillStyle = `rgba(0, 255, 0, 1.0)`; + ctx.fillRect(rectWidth, 0, kWidth - rectWidth, rectHeight); + // Blue + ctx.fillStyle = `rgba(0, 0, 255, 1.0)`; + ctx.fillRect(0, rectHeight, rectWidth, kHeight - rectHeight); + // Fuchsia + ctx.fillStyle = `rgba(255, 0, 255, 1.0)`; + ctx.fillRect(rectWidth, rectHeight, kWidth - rectWidth, kHeight - rectHeight); + + const imageData = ctx.getImageData(0, 0, kWidth, kHeight); + + // Create video frame with default color space 'srgb' + const frameInit = { + format: videoFrameFormat, + codedWidth: kWidth, + codedHeight: kHeight, + timestamp: 0 + }; + + const frame = new VideoFrame(imageData.data.buffer, frameInit); + let textureFormat = 'rgba8unorm'; + + if (videoFrameFormat === 'BGRA' || videoFrameFormat === 'BGRX') { + textureFormat = 'bgra8unorm'; + } - // For validation, we sample a few pixels away from the edges to avoid compression - // artifacts. - t.expectSinglePixelComparisonsAreOkInTexture({ texture: colorAttachment }, [ - { coord: { x: kWidth * 0.25, y: kHeight * 0.25 }, exp: t.params._topLeftExpectation }, - { coord: { x: kWidth * 0.75, y: kHeight * 0.25 }, exp: t.params._topRightExpectation }, - { coord: { x: kWidth * 0.25, y: kHeight * 0.75 }, exp: t.params._bottomLeftExpectation }, - { coord: { x: kWidth * 0.75, y: kHeight * 0.75 }, exp: t.params._bottomRightExpectation }] - ); + const colorAttachment = t.device.createTexture({ + format: textureFormat, + size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 }, + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT + }); + + const pipeline = createExternalTextureSamplingTestPipeline(t, textureFormat); + const bindGroup = createExternalTextureSamplingTestBindGroup( + t, + undefined /* checkNonStandardIsZeroCopy */, + frame, + pipeline, + 'srgb' + ); + + const commandEncoder = t.device.createCommandEncoder(); + const passEncoder = commandEncoder.beginRenderPass({ + colorAttachments: [ + { + view: colorAttachment.createView(), + clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }, + loadOp: 'clear', + storeOp: 'store' + }] - if (sourceType === 'VideoFrame') source.close(); }); + passEncoder.setPipeline(pipeline); + passEncoder.setBindGroup(0, bindGroup); + passEncoder.draw(6); + passEncoder.end(); + t.device.queue.submit([commandEncoder.finish()]); + + const expected = { + topLeft: new Uint8Array([255, 0, 0, 255]), + topRight: new Uint8Array([0, 255, 0, 255]), + bottomLeft: new Uint8Array([0, 0, 255, 255]), + bottomRight: new Uint8Array([255, 0, 255, 255]) + }; + + // For validation, we sample a few pixels away from the edges to avoid compression + // artifacts. + t.expectSinglePixelComparisonsAreOkInTexture({ texture: colorAttachment }, [ + // Top-left. + { + coord: { x: kWidth * 0.25, y: kHeight * 0.25 }, + exp: expected.topLeft + }, + // Top-right. + { + coord: { x: kWidth * 0.75, y: kHeight * 0.25 }, + exp: expected.topRight + }, + // Bottom-left. + { + coord: { x: kWidth * 0.25, y: kHeight * 0.75 }, + exp: expected.bottomLeft + }, + // Bottom-right. + { + coord: { x: kWidth * 0.75, y: kHeight * 0.75 }, + exp: expected.bottomRight + }] + ); }); g.test('importExternalTexture,sampleWithVideoFrameWithVisibleRectParam'). @@ -281,10 +367,13 @@ parameters are present. params((u) => u // .combineWithParams(checkNonStandardIsZeroCopyIfAvailable()). -combineWithParams(kVideoExpectations) +combine('videoName', kVideoNames). +combine('dstColorSpace', kPredefinedColorSpace) ). fn(async (t) => { - const videoElement = getVideoElement(t, t.params.videoName); + const { videoName, dstColorSpace } = t.params; + + const videoElement = getVideoElement(t, videoName); await startPlayingAndWaitForVideo(videoElement, async () => { const source = await getVideoFrameFromVideoElement(t, videoElement); @@ -292,15 +381,24 @@ fn(async (t) => { // All tested videos are derived from an image showing yellow, red, blue or green in each // quadrant. In this test we crop the video to each quadrant and check that desired color // is sampled from each corner of the cropped image. - const srcVideoHeight = 240; - const srcVideoWidth = 320; + // visible rect clip applies on raw decoded frame, which defines based on video frame coded size. + const srcVideoHeight = source.codedHeight; + const srcVideoWidth = source.codedWidth; + + const srcColorSpace = kVideoInfo[videoName].colorSpace; + const presentColors = kVideoExpectedColors[srcColorSpace][dstColorSpace]; + + // The test crops raw decoded videos first and then apply transform. Expectation should + // use coded colors as reference. + const expect = kVideoInfo[videoName].coded; + const cropParams = [ - // Top left (yellow) + // Top left { subRect: { x: 0, y: 0, width: srcVideoWidth / 2, height: srcVideoHeight / 2 }, - color: t.params._yellowExpectation + color: convertToUnorm8(presentColors[expect.topLeftColor]) }, - // Top right (red) + // Top right { subRect: { x: srcVideoWidth / 2, @@ -308,9 +406,9 @@ fn(async (t) => { width: srcVideoWidth / 2, height: srcVideoHeight / 2 }, - color: t.params._redExpectation + color: convertToUnorm8(presentColors[expect.topRightColor]) }, - // Bottom left (blue) + // Bottom left { subRect: { x: 0, @@ -318,9 +416,9 @@ fn(async (t) => { width: srcVideoWidth / 2, height: srcVideoHeight / 2 }, - color: t.params._blueExpectation + color: convertToUnorm8(presentColors[expect.bottomLeftColor]) }, - // Bottom right (green) + // Bottom right { subRect: { x: srcVideoWidth / 2, @@ -328,13 +426,11 @@ fn(async (t) => { width: srcVideoWidth / 2, height: srcVideoHeight / 2 }, - color: t.params._greenExpectation + color: convertToUnorm8(presentColors[expect.bottomRightColor]) }]; for (const cropParam of cropParams) { - // MAINTENANCE_TODO: remove cast with TypeScript 4.9.6+. - const subRect = new VideoFrame(source, { visibleRect: cropParam.subRect }); const colorAttachment = t.device.createTexture({ @@ -348,7 +444,8 @@ fn(async (t) => { t, t.params.checkNonStandardIsZeroCopy, subRect, - pipeline + pipeline, + dstColorSpace ); const commandEncoder = t.device.createCommandEncoder(); @@ -387,22 +484,24 @@ g.test('importExternalTexture,compute'). desc( ` Tests that we can import an HTMLVideoElement/VideoFrame into a GPUExternalTexture and use it in a -compute shader, for several combinations of video format and color space. +compute shader, for several combinations of video format, video color spaces and dst color spaces. ` ). params((u) => u // .combineWithParams(checkNonStandardIsZeroCopyIfAvailable()). +combine('videoName', kVideoNames). combine('sourceType', ['VideoElement', 'VideoFrame']). -combineWithParams(kVideoExpectations) +combine('dstColorSpace', kPredefinedColorSpace) ). fn(async (t) => { - const sourceType = t.params.sourceType; + const { videoName, sourceType, dstColorSpace } = t.params; + if (sourceType === 'VideoFrame' && typeof VideoFrame === 'undefined') { t.skip('WebCodec is not supported'); } - const videoElement = getVideoElement(t, t.params.videoName); + const videoElement = getVideoElement(t, videoName); await startPlayingAndWaitForVideo(videoElement, async () => { const source = @@ -410,8 +509,8 @@ fn(async (t) => { await getVideoFrameFromVideoElement(t, videoElement) : videoElement; const externalTexture = t.device.importExternalTexture({ - - source: source + source, + colorSpace: dstColorSpace }); if (t.params.checkNonStandardIsZeroCopy) { expectZeroCopyNonStandard(t, externalTexture); @@ -422,29 +521,51 @@ fn(async (t) => { usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.STORAGE_BINDING }); + // Use display size of VideoFrame and video size of HTMLVideoElement as frame size. These sizes are presenting size which + // apply transformation in video metadata if any. + const pipeline = t.device.createComputePipeline({ layout: 'auto', compute: { - // Shader loads 4 pixels near each corner, and then store them in a storage texture. + // Shader loads 4 pixels, and then store them in a storage texture. module: t.device.createShaderModule({ code: ` + override frameWidth : i32 = 0; + override frameHeight : i32 = 0; @group(0) @binding(0) var t : texture_external; @group(0) @binding(1) var outImage : texture_storage_2d; @compute @workgroup_size(1) fn main() { - var yellow : vec4 = textureLoad(t, vec2(80, 60)); + let coordTopLeft = vec2(frameWidth / 4, frameHeight / 4); + let coordTopRight = vec2(frameWidth / 4 * 3, frameHeight / 4); + let coordBottomLeft = vec2(frameWidth / 4, frameHeight / 4 * 3); + let coordBottomRight = vec2(frameWidth / 4 * 3, frameHeight / 4 * 3); + var yellow : vec4 = textureLoad(t, coordTopLeft); textureStore(outImage, vec2(0, 0), yellow); - var red : vec4 = textureLoad(t, vec2(240, 60)); + var red : vec4 = textureLoad(t, coordTopRight); textureStore(outImage, vec2(0, 1), red); - var blue : vec4 = textureLoad(t, vec2(80, 180)); + var blue : vec4 = textureLoad(t, coordBottomLeft); textureStore(outImage, vec2(1, 0), blue); - var green : vec4 = textureLoad(t, vec2(240, 180)); + var green : vec4 = textureLoad(t, coordBottomRight); textureStore(outImage, vec2(1, 1), green); return; } ` }), - entryPoint: 'main' + entryPoint: 'main', + + // Use display size of VideoFrame and video size of HTMLVideoElement as frame size. These sizes are presenting size which + // apply transformation in video metadata if any. + constants: { + frameWidth: + sourceType === 'VideoFrame' ? + source.displayWidth : + source.videoWidth, + frameHeight: + sourceType === 'VideoFrame' ? + source.displayHeight : + source.videoHeight + } } }); @@ -464,17 +585,21 @@ fn(async (t) => { pass.end(); t.device.queue.submit([encoder.finish()]); + const srcColorSpace = kVideoInfo[videoName].colorSpace; + const presentColors = kVideoExpectedColors[srcColorSpace][dstColorSpace]; + + // visible rect is whole frame, no clipping. + const expect = kVideoInfo[videoName].display; + t.expectSinglePixelComparisonsAreOkInTexture({ texture: outputTexture }, [ - // Top-left should be yellow. - { coord: { x: 0, y: 0 }, exp: t.params._yellowExpectation }, - // Top-right should be red. - { coord: { x: 0, y: 1 }, exp: t.params._redExpectation }, - // Bottom-left should be blue. - { coord: { x: 1, y: 0 }, exp: t.params._blueExpectation }, - // Bottom-right should be green. - { coord: { x: 1, y: 1 }, exp: t.params._greenExpectation }] + // Top-left. + { coord: { x: 0, y: 0 }, exp: convertToUnorm8(presentColors[expect.topLeftColor]) }, + // Top-right. + { coord: { x: 0, y: 1 }, exp: convertToUnorm8(presentColors[expect.topRightColor]) }, + // Bottom-left. + { coord: { x: 1, y: 0 }, exp: convertToUnorm8(presentColors[expect.bottomLeftColor]) }, + // Bottom-right. + { coord: { x: 1, y: 1 }, exp: convertToUnorm8(presentColors[expect.bottomRightColor]) }] ); - - if (sourceType === 'VideoFrame') source.close(); }); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html deleted file mode 100644 index 3639d3ca82..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html +++ /dev/null @@ -1,12 +0,0 @@ - - - WebGPU canvas_clear - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html deleted file mode 100644 index c910c97b1d..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html +++ /dev/null @@ -1,22 +0,0 @@ - - - WebGPU canvas_colorspace_bgra8unorm - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html deleted file mode 100644 index 7f57858e49..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html +++ /dev/null @@ -1,23 +0,0 @@ - - - WebGPU canvas_colorspace_rgba16float - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html deleted file mode 100644 index e57e04ef5c..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html +++ /dev/null @@ -1,22 +0,0 @@ - - - WebGPU canvas_colorspace_rgba8unorm - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html deleted file mode 100644 index d378bdfcf5..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html +++ /dev/null @@ -1,24 +0,0 @@ - - - WebGPU canvas_complex_bgra8unorm_copy - - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html deleted file mode 100644 index 99049e6e32..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html +++ /dev/null @@ -1,24 +0,0 @@ - - - WebGPU canvas_complex_bgra8unorm_draw - - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html deleted file mode 100644 index 400afa121b..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html +++ /dev/null @@ -1,24 +0,0 @@ - - - WebGPU canvas_complex_rgba16float_copy - - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html deleted file mode 100644 index a647fc2956..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html +++ /dev/null @@ -1,24 +0,0 @@ - - - WebGPU canvas_complex_rgba16float_draw - - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html deleted file mode 100644 index b812129b0b..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html +++ /dev/null @@ -1,24 +0,0 @@ - - - WebGPU canvas_complex_rgba16float_store - - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html deleted file mode 100644 index d2570a3bdf..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html +++ /dev/null @@ -1,24 +0,0 @@ - - - WebGPU canvas_complex_rgba8unorm_copy - - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html deleted file mode 100644 index 647a829259..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html +++ /dev/null @@ -1,24 +0,0 @@ - - - WebGPU canvas_complex_rgba8unorm_draw - - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html deleted file mode 100644 index b82745658e..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html +++ /dev/null @@ -1,24 +0,0 @@ - - - WebGPU canvas_complex_rgba8unorm_store - - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html deleted file mode 100644 index 60e8417c16..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html +++ /dev/null @@ -1,21 +0,0 @@ - - - WebGPU canvas_composite_alpha_bgra8unorm_opaque - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html deleted file mode 100644 index c0280a2a99..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html +++ /dev/null @@ -1,21 +0,0 @@ - - - WebGPU canvas_composite_alpha_bgra8unorm_opaque - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html deleted file mode 100644 index 70920dc0e6..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html +++ /dev/null @@ -1,22 +0,0 @@ - - - WebGPU canvas_composite_alpha_bgra8unorm_premultiplied - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html deleted file mode 100644 index d12751fac2..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html +++ /dev/null @@ -1,22 +0,0 @@ - - - WebGPU canvas_composite_alpha_bgra8unorm_premultiplied - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html deleted file mode 100644 index 4471f08480..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html +++ /dev/null @@ -1,21 +0,0 @@ - - - WebGPU canvas_composite_alpha_rgba16float_opaque - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html deleted file mode 100644 index 11f0e73ec2..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html +++ /dev/null @@ -1,21 +0,0 @@ - - - WebGPU canvas_composite_alpha_rgba16float_opaque - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html deleted file mode 100644 index ed722013c1..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html +++ /dev/null @@ -1,22 +0,0 @@ - - - WebGPU canvas_composite_alpha_rgba16float_premultiplied - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html deleted file mode 100644 index 8a028b168e..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html +++ /dev/null @@ -1,22 +0,0 @@ - - - WebGPU canvas_composite_alpha_rgba16float_premultiplied - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html deleted file mode 100644 index 7147631d19..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html +++ /dev/null @@ -1,21 +0,0 @@ - - - WebGPU canvas_composite_alpha_rgba8unorm_opaque - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html deleted file mode 100644 index ec2bb05ed3..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html +++ /dev/null @@ -1,21 +0,0 @@ - - - WebGPU canvas_composite_alpha_rgba8unorm_opaque - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html deleted file mode 100644 index fa938aba41..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html +++ /dev/null @@ -1,22 +0,0 @@ - - - WebGPU canvas_composite_alpha_rgba8unorm_premultiplied - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html deleted file mode 100644 index b62e71054c..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html +++ /dev/null @@ -1,22 +0,0 @@ - - - WebGPU canvas_composite_alpha_rgba8unorm_premultiplied - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html deleted file mode 100644 index f51145645b..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html +++ /dev/null @@ -1,15 +0,0 @@ - - - WebGPU canvas_image_rendering - - - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/delay_get_texture.html.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/delay_get_texture.html.js new file mode 100644 index 0000000000..84b667ad14 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/delay_get_texture.html.js @@ -0,0 +1,46 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { timeout } from '../../../common/util/timeout.js';import { takeScreenshotDelayed } from '../../../common/util/wpt_reftest_wait.js'; +function assert(condition, msg) { + if (!condition) { + throw new Error(msg && (typeof msg === 'string' ? msg : msg())); + } +} + +void (async () => { + assert( + typeof navigator !== 'undefined' && navigator.gpu !== undefined, + 'No WebGPU implementation found' + ); + + const adapter = await navigator.gpu.requestAdapter(); + assert(adapter !== null); + const device = await adapter.requestDevice(); + assert(device !== null); + + const canvas = document.getElementById('cvs0'); + const ctx = canvas.getContext('webgpu'); + ctx.configure({ + device, + format: navigator.gpu.getPreferredCanvasFormat(), + alphaMode: 'premultiplied' + }); + + timeout(() => { + const encoder = device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ + colorAttachments: [ + { + view: ctx.getCurrentTexture().createView(), + clearValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 }, + loadOp: 'clear', + storeOp: 'store' + }] + + }); + pass.end(); + device.queue.submit([encoder.finish()]); + + takeScreenshotDelayed(50); + }, 100); +})(); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_clear-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_clear-ref.html deleted file mode 100644 index e37b78c3a6..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_clear-ref.html +++ /dev/null @@ -1,22 +0,0 @@ - - - WebGPU canvas_clear (ref) - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html deleted file mode 100644 index a6da9f6748..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html +++ /dev/null @@ -1,17 +0,0 @@ - - - WebGPU canvas_colorspace (ref) - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_complex-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_complex-ref.html deleted file mode 100644 index b1d46c108a..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_complex-ref.html +++ /dev/null @@ -1,26 +0,0 @@ - - - WebGPU canvas_complex (ref) - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html deleted file mode 100644 index 94b9486514..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html +++ /dev/null @@ -1,26 +0,0 @@ - - - WebGPU canvas_composite_alpha_premultiplied (ref) - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html deleted file mode 100644 index 635625ecc7..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html +++ /dev/null @@ -1,26 +0,0 @@ - - - WebGPU canvas_composite_alpha_premultiplied (ref) - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_image_rendering-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_image_rendering-ref.html deleted file mode 100644 index f9eca704e8..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_image_rendering-ref.html +++ /dev/null @@ -1,25 +0,0 @@ - - - WebGPU canvas_image_rendering (ref) - - - - - - - - - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/resize_observer-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/resize_observer-ref.html deleted file mode 100644 index 5259a25c27..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/resize_observer-ref.html +++ /dev/null @@ -1,90 +0,0 @@ - - - WebGPU ResizeObserver test (ref) - - - - -
-
- - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.https.html deleted file mode 100644 index 2845cc29eb..0000000000 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.https.html +++ /dev/null @@ -1,24 +0,0 @@ - - - WebGPU resize_observer - - - - - - -
-
- - - diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/util.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/util.js index df4b02447f..dc66e3c70d 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/util.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/util.js @@ -1,9 +1,10 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { SkipTestCase } from '../../common/framework/fixture.js';import { getResourcePath } from '../../common/framework/resources.js';import { makeTable } from '../../common/util/data_tables.js'; +**/import { SkipTestCase } from '../../common/framework/fixture.js';import { getResourcePath } from '../../common/framework/resources.js';import { keysOf } from '../../common/util/data_tables.js'; import { timeout } from '../../common/util/timeout.js'; import { ErrorWithExtra, raceWithRejectOnTimeout } from '../../common/util/util.js'; +import { srgbToDisplayP3 } from '../util/color_space_conversion.js'; @@ -13,105 +14,342 @@ import { ErrorWithExtra, raceWithRejectOnTimeout } from '../../common/util/util. -export const kVideoInfo = -makeTable( - ['mimeType'], - [undefined], { - // All video names - 'four-colors-vp8-bt601.webm': ['video/webm; codecs=vp8'], - 'four-colors-h264-bt601.mp4': ['video/mp4; codecs=avc1.4d400c'], - 'four-colors-vp9-bt601.webm': ['video/webm; codecs=vp9'], - 'four-colors-vp9-bt709.webm': ['video/webm; codecs=vp9'], - 'four-colors-vp9-bt2020.webm': ['video/webm; codecs=vp9'], - 'four-colors-h264-bt601-rotate-90.mp4': ['video/mp4; codecs=avc1.4d400c'], - 'four-colors-h264-bt601-rotate-180.mp4': ['video/mp4; codecs=avc1.4d400c'], - 'four-colors-h264-bt601-rotate-270.mp4': ['video/mp4; codecs=avc1.4d400c'] - }); +// MAINTENANCE_TODO: Uses raw floats as expectation in external_texture related cases has some diffs. +// Remove this conversion utils and uses raw float data as expectation in external_textrue +// related cases when resolve this. +export function convertToUnorm8(expectation) { + const rgba8Unorm = new Uint8ClampedArray(4); + rgba8Unorm[0] = Math.round(expectation.R * 255.0); + rgba8Unorm[1] = Math.round(expectation.G * 255.0); + rgba8Unorm[2] = Math.round(expectation.B * 255.0); + rgba8Unorm[3] = Math.round(expectation.A * 255.0); + return new Uint8Array(rgba8Unorm.buffer); +} +// MAINTENANCE_TODO: Add helper function for BT.601 and BT.709 to remove all magic numbers. // Expectation values about converting video contents to sRGB color space. // Source video color space affects expected values. // The process to calculate these expected pixel values can be found: // https://github.com/gpuweb/cts/pull/2242#issuecomment-1430382811 // and https://github.com/gpuweb/cts/pull/2242#issuecomment-1463273434 const kBt601PixelValue = { - red: new Float32Array([0.972945567233341, 0.141794376683341, -0.0209589916711088, 1.0]), - green: new Float32Array([0.248234279433399, 0.984810378661784, -0.0564701319494314, 1.0]), - blue: new Float32Array([0.10159735826538, 0.135451122863674, 1.00262982899724, 1.0]), - yellow: new Float32Array([0.995470750775951, 0.992742114518355, -0.0774291236205402, 1.0]) + srgb: { + red: { R: 0.972945567233341, G: 0.141794376683341, B: -0.0209589916711088, A: 1.0 }, + green: { R: 0.248234279433399, G: 0.984810378661784, B: -0.0564701319494314, A: 1.0 }, + blue: { R: 0.10159735826538, G: 0.135451122863674, B: 1.00262982899724, A: 1.0 }, + yellow: { R: 0.995470750775951, G: 0.992742114518355, B: -0.0701036235167653, A: 1.0 } + } }; -function convertToUnorm8(expectation) { - const unorm8 = new Uint8ClampedArray(expectation.length); - - for (let i = 0; i < expectation.length; ++i) { - unorm8[i] = Math.round(expectation[i] * 255.0); +const kBt709PixelValue = { + srgb: { + red: { R: 1.0, G: 0.0, B: 0.0, A: 1.0 }, + green: { R: 0.0, G: 1.0, B: 0.0, A: 1.0 }, + blue: { R: 0.0, G: 0.0, B: 1.0, A: 1.0 }, + yellow: { R: 1.0, G: 1.0, B: 0.0, A: 1.0 } } +}; - return new Uint8Array(unorm8.buffer); -} +function makeTable({ + table -// kVideoExpectations uses unorm8 results -const kBt601Red = convertToUnorm8(kBt601PixelValue.red); -const kBt601Green = convertToUnorm8(kBt601PixelValue.green); -const kBt601Blue = convertToUnorm8(kBt601PixelValue.blue); -const kBt601Yellow = convertToUnorm8(kBt601PixelValue.yellow); -export const kVideoExpectations = [ -{ - videoName: 'four-colors-vp8-bt601.webm', - _redExpectation: kBt601Red, - _greenExpectation: kBt601Green, - _blueExpectation: kBt601Blue, - _yellowExpectation: kBt601Yellow -}, -{ - videoName: 'four-colors-h264-bt601.mp4', - _redExpectation: kBt601Red, - _greenExpectation: kBt601Green, - _blueExpectation: kBt601Blue, - _yellowExpectation: kBt601Yellow -}, -{ - videoName: 'four-colors-vp9-bt601.webm', - _redExpectation: kBt601Red, - _greenExpectation: kBt601Green, - _blueExpectation: kBt601Blue, - _yellowExpectation: kBt601Yellow -}, -{ - videoName: 'four-colors-vp9-bt709.webm', - _redExpectation: new Uint8Array([255, 0, 0, 255]), - _greenExpectation: new Uint8Array([0, 255, 0, 255]), - _blueExpectation: new Uint8Array([0, 0, 255, 255]), - _yellowExpectation: new Uint8Array([255, 255, 0, 255]) -}]; +}) + -export const kVideoRotationExpectations = [ -{ - videoName: 'four-colors-h264-bt601-rotate-90.mp4', - _topLeftExpectation: kBt601Red, - _topRightExpectation: kBt601Green, - _bottomLeftExpectation: kBt601Yellow, - _bottomRightExpectation: kBt601Blue -}, -{ - videoName: 'four-colors-h264-bt601-rotate-180.mp4', - _topLeftExpectation: kBt601Green, - _topRightExpectation: kBt601Blue, - _bottomLeftExpectation: kBt601Red, - _bottomRightExpectation: kBt601Yellow -}, { - videoName: 'four-colors-h264-bt601-rotate-270.mp4', - _topLeftExpectation: kBt601Blue, - _topRightExpectation: kBt601Yellow, - _bottomLeftExpectation: kBt601Green, - _bottomRightExpectation: kBt601Red -}]; + return Object.fromEntries( + Object.entries(table).map(([k, row]) => [k, { ...row }]) + ); +} +// Video expected pixel value table. Finding expected pixel value +// with video color space and dst color space. +export const kVideoExpectedColors = makeTable({ + table: { + bt601: { + 'display-p3': { + yellow: srgbToDisplayP3(kBt601PixelValue.srgb.yellow), + red: srgbToDisplayP3(kBt601PixelValue.srgb.red), + blue: srgbToDisplayP3(kBt601PixelValue.srgb.blue), + green: srgbToDisplayP3(kBt601PixelValue.srgb.green) + }, + srgb: { + yellow: kBt601PixelValue.srgb.yellow, + red: kBt601PixelValue.srgb.red, + blue: kBt601PixelValue.srgb.blue, + green: kBt601PixelValue.srgb.green + } + }, + bt709: { + 'display-p3': { + yellow: srgbToDisplayP3(kBt709PixelValue.srgb.yellow), + red: srgbToDisplayP3(kBt709PixelValue.srgb.red), + blue: srgbToDisplayP3(kBt709PixelValue.srgb.blue), + green: srgbToDisplayP3(kBt709PixelValue.srgb.green) + }, + srgb: { + yellow: kBt709PixelValue.srgb.yellow, + red: kBt709PixelValue.srgb.red, + blue: kBt709PixelValue.srgb.blue, + green: kBt709PixelValue.srgb.green + } + } + } +}); + +// MAINTENANCE_TODO: Add BT.2020 video in table. +// Video container and codec defines several transform ops to apply to raw decoded frame to display. +// Our test cases covers 'visible rect' and 'rotation'. +// 'visible rect' is associated with the +// video bitstream and should apply to the raw decoded frames before any transformation. +// 'rotation' is associated with the track or presentation and should transform +// the whole visible rect (e.g. 90-degree rotate makes visible rect of vertical video to horizontal) +// The order to apply these transformations is below: + +// [raw decoded frame] ----visible rect clipping ---->[visible frame] ---rotation ---> present +// ^ ^ +// | | +// coded size display size +// The table holds test videos meta infos, including mimeType to check browser compatibility +// video color space, raw frame content layout and the frame displayed layout. +export const kVideoInfo = makeTable({ + table: { + 'four-colors-vp8-bt601.webm': { + mimeType: 'video/webm; codecs=vp8', + colorSpace: 'bt601', + coded: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + }, + display: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + } + }, + 'four-colors-h264-bt601.mp4': { + mimeType: 'video/mp4; codecs=avc1.4d400c', + colorSpace: 'bt601', + coded: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + }, + display: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + } + }, + 'four-colors-vp9-bt601.webm': { + mimeType: 'video/webm; codecs=vp9', + colorSpace: 'bt601', + coded: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + }, + display: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + } + }, + 'four-colors-vp9-bt709.webm': { + mimeType: 'video/webm; codecs=vp9', + colorSpace: 'bt709', + coded: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + }, + display: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + } + }, + // video coded content has been rotate + 'four-colors-h264-bt601-rotate-90.mp4': { + mimeType: 'video/mp4; codecs=avc1.4d400c', + colorSpace: 'bt601', + coded: { + topLeftColor: 'red', + topRightColor: 'green', + bottomLeftColor: 'yellow', + bottomRightColor: 'blue' + }, + display: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + } + }, + 'four-colors-h264-bt601-rotate-180.mp4': { + mimeType: 'video/mp4; codecs=avc1.4d400c', + colorSpace: 'bt601', + coded: { + topLeftColor: 'green', + topRightColor: 'blue', + bottomLeftColor: 'red', + bottomRightColor: 'yellow' + }, + display: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + } + }, + 'four-colors-h264-bt601-rotate-270.mp4': { + mimeType: 'video/mp4; codecs=avc1.4d400c', + colorSpace: 'bt601', + coded: { + topLeftColor: 'blue', + topRightColor: 'yellow', + bottomLeftColor: 'green', + bottomRightColor: 'red' + }, + display: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + } + }, + 'four-colors-vp9-bt601-rotate-90.mp4': { + mimeType: 'video/mp4; codecs=vp09.00.10.08', + colorSpace: 'bt601', + coded: { + topLeftColor: 'red', + topRightColor: 'green', + bottomLeftColor: 'yellow', + bottomRightColor: 'blue' + }, + display: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + } + }, + 'four-colors-vp9-bt601-rotate-180.mp4': { + mimeType: 'video/mp4; codecs=vp09.00.10.08', + colorSpace: 'bt601', + coded: { + topLeftColor: 'green', + topRightColor: 'blue', + bottomLeftColor: 'red', + bottomRightColor: 'yellow' + }, + display: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + } + }, + 'four-colors-vp9-bt601-rotate-270.mp4': { + mimeType: 'video/mp4; codecs=vp09.00.10.08', + colorSpace: 'bt601', + coded: { + topLeftColor: 'blue', + topRightColor: 'yellow', + bottomLeftColor: 'green', + bottomRightColor: 'red' + }, + display: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + } + }, + 'four-colors-h264-bt601-hflip.mp4': { + mimeType: 'video/mp4; codecs=avc1.4d400c', + colorSpace: 'bt601', + coded: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + }, + display: { + topLeftColor: 'red', + topRightColor: 'yellow', + bottomLeftColor: 'green', + bottomRightColor: 'blue' + } + }, + 'four-colors-h264-bt601-vflip.mp4': { + mimeType: 'video/mp4; codecs=avc1.4d400c', + colorSpace: 'bt601', + coded: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + }, + display: { + topLeftColor: 'blue', + topRightColor: 'green', + bottomLeftColor: 'yellow', + bottomRightColor: 'red' + } + }, + 'four-colors-vp9-bt601-hflip.mp4': { + mimeType: 'video/mp4; codecs=vp09.00.10.08', + colorSpace: 'bt601', + coded: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + }, + display: { + topLeftColor: 'red', + topRightColor: 'yellow', + bottomLeftColor: 'green', + bottomRightColor: 'blue' + } + }, + 'four-colors-vp9-bt601-vflip.mp4': { + mimeType: 'video/mp4; codecs=vp09.00.10.08', + colorSpace: 'bt601', + coded: { + topLeftColor: 'yellow', + topRightColor: 'red', + bottomLeftColor: 'blue', + bottomRightColor: 'green' + }, + display: { + topLeftColor: 'blue', + topRightColor: 'green', + bottomLeftColor: 'yellow', + bottomRightColor: 'red' + } + } + } +}); + + +export const kVideoNames = keysOf(kVideoInfo); + +export const kPredefinedColorSpace = ['display-p3', 'srgb']; /** * Starts playing a video and waits for it to be consumable. * Returns a promise which resolves after `callback` (which may be async) completes. @@ -145,7 +383,12 @@ callback) video.addEventListener( 'error', - (event) => reject(new ErrorWithExtra('Video received "error" event', () => ({ event }))), + (event) => + reject( + new ErrorWithExtra('Video received "error" event, message: ' + event.message, () => ({ + event + })) + ), true ); @@ -230,6 +473,7 @@ video) const transformer = new TransformStream({ transform(videoFrame, _controller) { videoTrack.stop(); + test.trackForCleanup(videoFrame); resolve(videoFrame); }, flush(controller) { @@ -259,6 +503,10 @@ video) * */ export function getVideoElement(t, videoName) { + if (typeof HTMLVideoElement === 'undefined') { + t.skip('HTMLVideoElement not available'); + } + const videoElement = document.createElement('video'); const videoInfo = kVideoInfo[videoName]; @@ -269,6 +517,8 @@ export function getVideoElement(t, videoName) { const videoUrl = getResourcePath(videoName); videoElement.src = videoUrl; + t.trackForCleanup(videoElement); + return videoElement; } @@ -296,4 +546,4 @@ timeoutMessage) }); const promise = raceWithRejectOnTimeout(promiseWithoutTimeout, 2000, timeoutMessage); return { promise, callbackAndResolve: callbackAndResolve }; -} +} \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.js index 8eff1ae8cd..f90a4db02e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.js @@ -1,6 +1,10 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/import { getGPU, setDefaultRequestAdapterOptions } from '../../../common/util/navigator_gpu.js';import { assert, objectEquals, iterRange } from '../../../common/util/util.js'; +// Should be WorkerGlobalScope, but importing lib "webworker" conflicts with lib "dom". + + + async function basicTest() { const adapter = await getGPU(null).requestAdapter(); assert(adapter !== null, 'Failed to get adapter.'); @@ -68,7 +72,7 @@ async function basicTest() { device.destroy(); } -self.onmessage = async (ev) => { +async function reportTestResults(ev) { const defaultRequestAdapterOptions = ev.data.defaultRequestAdapterOptions; setDefaultRequestAdapterOptions(defaultRequestAdapterOptions); @@ -79,5 +83,17 @@ self.onmessage = async (ev) => { } catch (err) { error = err.toString(); } - self.postMessage({ error }); + this.postMessage({ error }); +} + +self.onmessage = (ev) => { + void reportTestResults.call(ev.source || self, ev); +}; + +self.onconnect = (event) => { + const port = event.ports[0]; + + port.onmessage = (ev) => { + void reportTestResults.call(port, ev); + }; }; \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.spec.js index 56d07640e4..43d796f828 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.spec.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.spec.js @@ -1,35 +1,67 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/export const description = ` -Tests WebGPU is available in a worker. +Tests WebGPU is available in a dedicated worker and a shared worker. -Note: The CTS test can be run in a worker by passing in worker=1 as -a query parameter. This test is specifically to check that WebGPU -is available in a worker. +Note: Any CTS test can be run in a worker by passing ?worker=dedicated, ?worker=shared, +?worker=service as a query parameter. The tests in this file are specifically to check +that WebGPU is available in each worker type. When run in combination with a ?worker flag, +they will test workers created from other workers (where APIs exist to do so). + +TODO[2]: Figure out how to make these tests run in service workers (not actually +important unless service workers gain the ability to launch other workers). `;import { Fixture } from '../../../common/framework/fixture.js'; import { makeTestGroup } from '../../../common/framework/test_group.js'; import { assert } from '../../../common/util/util.js'; export const g = makeTestGroup(Fixture); -function isNode() { - return typeof process !== 'undefined' && process?.versions?.node !== undefined; -} +const isNode = typeof process !== 'undefined' && process?.versions?.node !== undefined; + +// [1]: we load worker_launcher dynamically because ts-node support +// is using commonjs which doesn't support import.meta. Further, +// we need to put the url in a string and pass the string to import +// otherwise typescript tries to parse the file which again, fails. +// worker_launcher.js is excluded in node.tsconfig.json. + +// [2]: That hack does not work in Service Workers. +const isServiceWorker = globalThis.constructor.name === 'ServiceWorkerGlobalScope'; -g.test('worker'). -desc(`test WebGPU is available in DedicatedWorkers and check for basic functionality`). +g.test('dedicated_worker'). +desc(`test WebGPU is available in dedicated workers and check for basic functionality`). fn(async (t) => { - if (isNode()) { - t.skip('node does not support 100% compatible workers'); - return; - } - // Note: we load worker_launcher dynamically because ts-node support - // is using commonjs which doesn't support import.meta. Further, - // we need to put the url in a string add pass the string to import - // otherwise typescript tries to parse the file which again, fails. - // worker_launcher.js is excluded in node.tsconfig.json. + t.skipIf(isNode, 'node does not support 100% compatible workers'); + + t.skipIf(isServiceWorker, 'Service workers do not support this import() hack'); // [2] const url = './worker_launcher.js'; - const { launchWorker } = await import(url); - const result = await launchWorker(); + const { launchDedicatedWorker } = await import(url); // [1] + + const result = await launchDedicatedWorker(); + assert(result.error === undefined, `should be no error from worker but was: ${result.error}`); +}); + +g.test('shared_worker'). +desc(`test WebGPU is available in shared workers and check for basic functionality`). +fn(async (t) => { + t.skipIf(isNode, 'node does not support 100% compatible workers'); + + t.skipIf(isServiceWorker, 'Service workers do not support this import() hack'); // [2] + const url = './worker_launcher.js'; + const { launchSharedWorker } = await import(url); // [1] + + const result = await launchSharedWorker(); + assert(result.error === undefined, `should be no error from worker but was: ${result.error}`); +}); + +g.test('service_worker'). +desc(`test WebGPU is available in service workers and check for basic functionality`). +fn(async (t) => { + t.skipIf(isNode, 'node does not support 100% compatible workers'); + + t.skipIf(isServiceWorker, 'Service workers do not support this import() hack'); // [2] + const url = './worker_launcher.js'; + const { launchServiceWorker } = await import(url); // [1] + + const result = await launchServiceWorker(); assert(result.error === undefined, `should be no error from worker but was: ${result.error}`); }); \ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker_launcher.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker_launcher.js index 11c4a4e7e3..2024a96f8e 100644 --- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker_launcher.js +++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker_launcher.js @@ -1,10 +1,15 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts -**/import { getDefaultRequestAdapterOptions } from '../../../common/util/navigator_gpu.js'; +**/import { SkipTestCase } from '../../../common/framework/fixture.js';import { getDefaultRequestAdapterOptions } from '../../../common/util/navigator_gpu.js'; -export async function launchWorker() { + +export async function launchDedicatedWorker() { + if (typeof Worker === 'undefined') { + throw new SkipTestCase(`Worker undefined in context ${globalThis.constructor.name}`); + } + const selfPath = import.meta.url; const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/')); const workerPath = selfPathDir + '/worker.js'; @@ -15,4 +20,56 @@ export async function launchWorker() { }); worker.postMessage({ defaultRequestAdapterOptions: getDefaultRequestAdapterOptions() }); return await promise; +} + +export async function launchSharedWorker() { + if (typeof SharedWorker === 'undefined') { + throw new SkipTestCase(`SharedWorker undefined in context ${globalThis.constructor.name}`); + } + + const selfPath = import.meta.url; + const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/')); + const workerPath = selfPathDir + '/worker.js'; + const worker = new SharedWorker(workerPath, { type: 'module' }); + + const port = worker.port; + const promise = new Promise((resolve) => { + port.addEventListener('message', (ev) => resolve(ev.data), { once: true }); + }); + port.start(); + port.postMessage({ + defaultRequestAdapterOptions: getDefaultRequestAdapterOptions() + }); + return await promise; +} + +export async function launchServiceWorker() { + if (typeof navigator === 'undefined' || typeof navigator.serviceWorker === 'undefined') { + throw new SkipTestCase( + `navigator.serviceWorker undefined in context ${globalThis.constructor.name}` + ); + } + + const selfPath = import.meta.url; + const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/')); + const serviceWorkerPath = selfPathDir + '/worker.js'; + const registration = await navigator.serviceWorker.register(serviceWorkerPath, { + type: 'module' + }); + await registration.update(); + + const promise = new Promise((resolve) => { + navigator.serviceWorker.addEventListener( + 'message', + (ev) => { + resolve(ev.data); + void registration.unregister(); + }, + { once: true } + ); + }); + registration.active?.postMessage({ + defaultRequestAdapterOptions: getDefaultRequestAdapterOptions() + }); + return await promise; } \ No newline at end of file -- cgit v1.2.3