| { |
| "domain": "com.microsoft", |
| "name": "FusedGemm", |
| "sinceVersion": 1, |
| "inputs": { |
| "A": { "dtype": "T", "rank": 2 }, |
| "B": { "dtype": "T", "rank": 2 }, |
| "C": { "dtype": "T", "optional": true } |
| }, |
| "outputs": { "Y": { "dtype": "T", "rank": 2, "shape": "[gemmM, gemmN]" } }, |
| "attributes": { |
| "alpha": { "default": 1 }, |
| "beta": { "default": 1 }, |
| "transA": { "default": 0 }, |
| "transB": { "default": 0 }, |
| "activation": {}, |
| "activation_alpha": {}, |
| "activation_beta": {} |
| }, |
| "attributeConstraints": { "activation": { "values": ["Relu", "LeakyRelu", "Sigmoid", "Tanh", "HardSigmoid"] } }, |
| "typeConstraints": { "T": ["float32", "float16"] }, |
| "derive": { |
| "deviceWorkgroupCap": "min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX)", |
| "wave32Adapter": "has(device.adapterInfo, \"subgroupMinSize\") and has(device.adapterInfo, \"subgroupMaxSize\") and device.adapterInfo.subgroupMinSize == 32 and device.adapterInfo.subgroupMaxSize == 32", |
| "canPinSubgroupSize32": "device.features.has(\"subgroups\") and device.features.has(\"subgroup-size-control\") and has(device.adapterInfo, \"subgroupMinSize\") and has(device.adapterInfo, \"subgroupMaxSize\") and device.adapterInfo.subgroupMinSize <= 32 and device.adapterInfo.subgroupMaxSize >= 32", |
| "pinSubgroupSize32": "canPinSubgroupSize32 and not wave32Adapter", |
| "wave32Effective": "wave32Adapter or pinSubgroupSize32", |
| "transAFlag": "has(attrs, \"transA\") and attrs.transA != 0", |
| "transBFlag": "has(attrs, \"transB\") and attrs.transB != 0", |
| "gemmM": "dim(shapes.A, 1) if transAFlag else dim(shapes.A, 0)", |
| "gemmK": "dim(shapes.A, 0) if transAFlag else dim(shapes.A, 1)", |
| "gemmN": "dim(shapes.B, 0) if transBFlag else dim(shapes.B, 1)", |
| "gemmKB": "dim(shapes.B, 1) if transBFlag else dim(shapes.B, 0)", |
| "shapeOk": "ranks.A == 2 and ranks.B == 2 and ranks.Y == 2 and gemmK == gemmKB and dim(shapes.Y, 0) == gemmM and dim(shapes.Y, 1) == gemmN", |
| "dtypeOk": "(tensorDtypes.A == \"float32\" or tensorDtypes.A == \"float16\") and tensorDtypes.B == tensorDtypes.A and tensorDtypes.Y == tensorDtypes.A and f16Ok(dtypes.T)", |
| "rowBiasOk": "present.C and ((ranks.C == 1 and dim(shapes.C, 0) == gemmN) or (ranks.C == 2 and dim(shapes.C, 0) == 1 and dim(shapes.C, 1) == gemmN))", |
| "scalarBiasOk": "present.C and (ranks.C == 0 or (ranks.C == 1 and dim(shapes.C, 0) == 1) or (ranks.C == 2 and dim(shapes.C, 0) == 1 and dim(shapes.C, 1) == 1))", |
| "columnBiasOk": "present.C and ranks.C == 2 and dim(shapes.C, 0) == gemmM and dim(shapes.C, 1) == 1", |
| "matrixBiasOk": "present.C and ranks.C == 2 and dim(shapes.C, 0) == gemmM and dim(shapes.C, 1) == gemmN", |
| "cOk": "tensorDtypes.C == tensorDtypes.A and (rowBiasOk or scalarBiasOk or columnBiasOk or matrixBiasOk)", |
| "hasActivation": "has(attrs, \"activation\")", |
| "activationName": "attrs.activation if hasActivation else \"\"", |
| "activationOk": "not hasActivation or activationName == \"Relu\" or activationName == \"LeakyRelu\" or activationName == \"Sigmoid\" or activationName == \"Tanh\" or activationName == \"HardSigmoid\"", |
| "activationAlpha": "attrs.activation_alpha if has(attrs, \"activation_alpha\") else (0.2 if activationName == \"HardSigmoid\" else (0.01 if activationName == \"LeakyRelu\" else 0.0))", |
| "activationBeta": "attrs.activation_beta if has(attrs, \"activation_beta\") else (0.5 if activationName == \"HardSigmoid\" else 0.0)", |
| "baseContract": "shapeOk and dtypeOk and activationOk", |
| "noBiasContract": "baseContract and not present.C", |
| "biasContract": "baseContract and present.C and cOk", |
| "sgmatOperandBytes": "2 if tensorDtypes.A == \"float16\" and tensorDtypes.B == \"float16\" else 4", |
| "sgmatTileM": "32", |
| "sgmatTileN": "64", |
| "sgmatTileK": "32", |
| "sgmatDirectA": "tensorDtypes.A == \"float32\" and not transAFlag and gemmK > 0 and gemmM % sgmatTileM == 0", |
| "sgmatStorageBytes": "((0 if sgmatDirectA else sgmatTileM) + sgmatTileN) * sgmatTileK * sgmatOperandBytes + sgmatTileM * sgmatTileN * 4", |
| "sgmatResourcesFit": "128 <= deviceWorkgroupCap and sgmatStorageBytes <= device.limits.maxComputeWorkgroupStorageSize", |
| "sgmatScalingOk": "(attrs.alpha if has(attrs, \"alpha\") else 1) == 1 and (attrs.beta if has(attrs, \"beta\") else 1) == 1", |
| "sgmatLayoutOk": "gemmM > 0 and gemmK % sgmatTileK == 0 and gemmN % sgmatTileN == 0 and ((tensorDtypes.A == \"float16\" and device.features.has(\"shader-f16\") and (gemmM >= 2 or (not transAFlag and transBFlag))) or (tensorDtypes.A == \"float32\" and gemmM >= sgmatTileM)) and ceilDiv(gemmM, sgmatTileM) <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535) and ceilDiv(gemmN, sgmatTileN) <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535)", |
| "sgmatContract": "wave32Effective and sgmatLayoutOk and sgmatScalingOk and sgmatResourcesFit", |
| "sgmatRowBiasContract": "sgmatContract and rowBiasOk and ranks.C == 1", |
| "usesF16": "tensorDtypes.A == \"float16\"", |
| "gemmActivation": "activationName", |
| "gemmActAlpha": "activationAlpha", |
| "gemmActBeta": "activationBeta", |
| "gemmEpilogue": "\"activation\" if hasActivation else \"none\"", |
| "gemvColumns": "4 if gemmN % 4 == 0 else 1", |
| "gemvWorkgroup": "min(pow(2, log2ceil(deviceWorkgroupCap + 1) - 1), pow2ceil(max(gemmK, 1)), 64)" |
| }, |
| "bindings": { |
| "x": { "arg": "A", "buffer": "read-only-storage", "elementType": "$T" }, |
| "w": { "arg": "B", "buffer": "read-only-storage", "elementType": "$T" }, |
| "bias": { "arg": "C", "buffer": "read-only-storage", "elementType": "$T" }, |
| "y": { "arg": "Y", "buffer": "storage", "elementType": "$T" }, |
| "params": { "buffer": "uniform", "struct": [{ "name": "M", "type": "u32", "value": "gemmM" }] }, |
| "a": { "arg": "A", "buffer": "read-only-storage", "elementType": "$T" }, |
| "b": { "arg": "B", "buffer": "read-only-storage", "elementType": "$T" } |
| }, |
| "variants": [ |
| { |
| "id": "gemv_plain", |
| "priority": 200, |
| "when": ["noBiasContract", "gemmM == 1 and gemmN > 0 and gemmK > 0 and transBFlag", "gemvWorkgroup * gemvColumns * 4 <= device.limits.maxComputeWorkgroupStorageSize"], |
| "derive": { |
| "hasBias": false, |
| "workgroupSize": "gemvWorkgroup", |
| "gemvFused": true, |
| "inFeatures": "gemmK", |
| "outFeatures": "gemmN", |
| "xScalar": "\"f16\" if usesF16 else \"f32\"", |
| "wScalar": "\"f16\" if usesF16 else \"f32\"", |
| "yScalar": "\"f16\" if usesF16 else \"f32\"" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.Gemv", |
| "shader": "gemv-contiguous.wgsl.jinja", |
| "bindings": [ |
| "x", |
| "w", |
| "y", |
| { |
| "name": "params", |
| "struct": [{ "name": "alpha", "type": "f32", "value": "attrs.alpha if has(attrs, \"alpha\") else 1" }] |
| } |
| ], |
| "dispatch": { |
| "x": "min(ceilDiv(gemmN, gemvColumns), DISPATCH_FOLD_WIDTH)", |
| "y": "1", |
| "z": "ceilDiv(ceilDiv(gemmN, gemvColumns), DISPATCH_FOLD_WIDTH)" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "gemv_bias", |
| "priority": 200, |
| "when": ["biasContract", "gemmM == 1 and gemmN > 0 and gemmK > 0 and transBFlag", "gemvWorkgroup * gemvColumns * 4 <= device.limits.maxComputeWorkgroupStorageSize"], |
| "derive": { |
| "hasBias": true, |
| "workgroupSize": "gemvWorkgroup", |
| "gemvFused": true, |
| "inFeatures": "gemmK", |
| "outFeatures": "gemmN", |
| "xScalar": "\"f16\" if usesF16 else \"f32\"", |
| "wScalar": "\"f16\" if usesF16 else \"f32\"", |
| "yScalar": "\"f16\" if usesF16 else \"f32\"" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.Gemv", |
| "shader": "gemv-contiguous.wgsl.jinja", |
| "bindings": [ |
| "x", |
| "w", |
| "bias", |
| "y", |
| { |
| "name": "params", |
| "struct": [ |
| { "name": "alpha", "type": "f32", "value": "attrs.alpha if has(attrs, \"alpha\") else 1" }, |
| { "name": "beta", "type": "f32", "value": "attrs.beta if has(attrs, \"beta\") else 1" } |
| ] |
| } |
| ], |
| "dispatch": { |
| "x": "min(ceilDiv(gemmN, gemvColumns), DISPATCH_FOLD_WIDTH)", |
| "y": "1", |
| "z": "ceilDiv(ceilDiv(gemmN, gemvColumns), DISPATCH_FOLD_WIDTH)" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "notrans_sgmat_bias", |
| "priority": 100, |
| "when": ["sgmatRowBiasContract", "transAFlag == false", "transBFlag == false"], |
| "requires": { |
| "features": ["subgroups", "chromium-experimental-subgroup-matrix"], |
| "subgroupMatrixConfigs": [ |
| { "componentType": "f16", "M": 8, "N": 8, "K": 8 }, |
| { "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 } |
| ] |
| }, |
| "derive": { |
| "hasBias": true, |
| "aTransposedStorage": false, |
| "bTransposedStorage": "not false", |
| "yScalar": "\"f16\" if tensorDtypes.Y == \"float16\" else \"f32\"", |
| "mmaScalar": "\"f16\" if tensorDtypes.A == \"float16\" and tensorDtypes.B == \"float16\" else \"f32\"", |
| "inFeatures": "gemmK", |
| "outFeatures": "gemmN", |
| "tileM": "sgmatTileM", |
| "tileN": "sgmatTileN", |
| "tileK": "sgmatTileK", |
| "directAStorage": "sgmatDirectA", |
| "compensatedMatrixChunkTiles": "2 if sgmatDirectA and gemmK >= 8 * sgmatTileK else 0" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.SubgroupMatrixBias", |
| "shader": "gemm-subgroup-matrix.wgsl.jinja", |
| "bindings": ["x", "w", "bias", "y", "params"], |
| "dispatch": { |
| "x": "ceilDiv(gemmN, sgmatTileN)", |
| "y": "min(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)", |
| "z": "ceilDiv(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "notrans_sgmat", |
| "priority": 100, |
| "when": ["noBiasContract and sgmatContract", "transAFlag == false", "transBFlag == false"], |
| "requires": { |
| "features": ["subgroups", "chromium-experimental-subgroup-matrix"], |
| "subgroupMatrixConfigs": [ |
| { "componentType": "f16", "M": 8, "N": 8, "K": 8 }, |
| { "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 } |
| ] |
| }, |
| "derive": { |
| "hasBias": false, |
| "aTransposedStorage": false, |
| "bTransposedStorage": "not false", |
| "yScalar": "\"f16\" if tensorDtypes.Y == \"float16\" else \"f32\"", |
| "mmaScalar": "\"f16\" if tensorDtypes.A == \"float16\" and tensorDtypes.B == \"float16\" else \"f32\"", |
| "inFeatures": "gemmK", |
| "outFeatures": "gemmN", |
| "tileM": "sgmatTileM", |
| "tileN": "sgmatTileN", |
| "tileK": "sgmatTileK", |
| "directAStorage": "sgmatDirectA", |
| "compensatedMatrixChunkTiles": "2 if sgmatDirectA and gemmK >= 8 * sgmatTileK else 0" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.SubgroupMatrix", |
| "shader": "gemm-subgroup-matrix.wgsl.jinja", |
| "bindings": ["x", "w", "y", "params"], |
| "dispatch": { |
| "x": "ceilDiv(gemmN, sgmatTileN)", |
| "y": "min(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)", |
| "z": "ceilDiv(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transA_sgmat_bias", |
| "priority": 100, |
| "when": ["sgmatRowBiasContract", "transAFlag == true", "transBFlag == false"], |
| "requires": { |
| "features": ["subgroups", "chromium-experimental-subgroup-matrix"], |
| "subgroupMatrixConfigs": [ |
| { "componentType": "f16", "M": 8, "N": 8, "K": 8 }, |
| { "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 } |
| ] |
| }, |
| "derive": { |
| "hasBias": true, |
| "aTransposedStorage": true, |
| "bTransposedStorage": "not false", |
| "yScalar": "\"f16\" if tensorDtypes.Y == \"float16\" else \"f32\"", |
| "mmaScalar": "\"f16\" if tensorDtypes.A == \"float16\" and tensorDtypes.B == \"float16\" else \"f32\"", |
| "inFeatures": "gemmK", |
| "outFeatures": "gemmN", |
| "tileM": "sgmatTileM", |
| "tileN": "sgmatTileN", |
| "tileK": "sgmatTileK", |
| "directAStorage": "sgmatDirectA", |
| "compensatedMatrixChunkTiles": "2 if sgmatDirectA and gemmK >= 8 * sgmatTileK else 0" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.SubgroupMatrixBias", |
| "shader": "gemm-subgroup-matrix.wgsl.jinja", |
| "bindings": ["x", "w", "bias", "y", "params"], |
| "dispatch": { |
| "x": "ceilDiv(gemmN, sgmatTileN)", |
| "y": "min(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)", |
| "z": "ceilDiv(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transA_sgmat", |
| "priority": 100, |
| "when": ["noBiasContract and sgmatContract", "transAFlag == true", "transBFlag == false"], |
| "requires": { |
| "features": ["subgroups", "chromium-experimental-subgroup-matrix"], |
| "subgroupMatrixConfigs": [ |
| { "componentType": "f16", "M": 8, "N": 8, "K": 8 }, |
| { "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 } |
| ] |
| }, |
| "derive": { |
| "hasBias": false, |
| "aTransposedStorage": true, |
| "bTransposedStorage": "not false", |
| "yScalar": "\"f16\" if tensorDtypes.Y == \"float16\" else \"f32\"", |
| "mmaScalar": "\"f16\" if tensorDtypes.A == \"float16\" and tensorDtypes.B == \"float16\" else \"f32\"", |
| "inFeatures": "gemmK", |
| "outFeatures": "gemmN", |
| "tileM": "sgmatTileM", |
| "tileN": "sgmatTileN", |
| "tileK": "sgmatTileK", |
| "directAStorage": "sgmatDirectA", |
| "compensatedMatrixChunkTiles": "2 if sgmatDirectA and gemmK >= 8 * sgmatTileK else 0" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.SubgroupMatrix", |
| "shader": "gemm-subgroup-matrix.wgsl.jinja", |
| "bindings": ["x", "w", "y", "params"], |
| "dispatch": { |
| "x": "ceilDiv(gemmN, sgmatTileN)", |
| "y": "min(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)", |
| "z": "ceilDiv(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transB_sgmat_bias", |
| "priority": 100, |
| "when": ["sgmatRowBiasContract", "transAFlag == false", "transBFlag == true"], |
| "requires": { |
| "features": ["subgroups", "chromium-experimental-subgroup-matrix"], |
| "subgroupMatrixConfigs": [ |
| { "componentType": "f16", "M": 8, "N": 8, "K": 8 }, |
| { "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 } |
| ] |
| }, |
| "derive": { |
| "hasBias": true, |
| "aTransposedStorage": false, |
| "bTransposedStorage": "not true", |
| "yScalar": "\"f16\" if tensorDtypes.Y == \"float16\" else \"f32\"", |
| "mmaScalar": "\"f16\" if tensorDtypes.A == \"float16\" and tensorDtypes.B == \"float16\" else \"f32\"", |
| "inFeatures": "gemmK", |
| "outFeatures": "gemmN", |
| "tileM": "sgmatTileM", |
| "tileN": "sgmatTileN", |
| "tileK": "sgmatTileK", |
| "directAStorage": "sgmatDirectA", |
| "compensatedMatrixChunkTiles": "2 if sgmatDirectA and gemmK >= 8 * sgmatTileK else 0" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.SubgroupMatrixBias", |
| "shader": "gemm-subgroup-matrix.wgsl.jinja", |
| "bindings": ["x", "w", "bias", "y", "params"], |
| "dispatch": { |
| "x": "ceilDiv(gemmN, sgmatTileN)", |
| "y": "min(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)", |
| "z": "ceilDiv(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transB_sgmat", |
| "priority": 100, |
| "when": ["noBiasContract and sgmatContract", "transAFlag == false", "transBFlag == true"], |
| "requires": { |
| "features": ["subgroups", "chromium-experimental-subgroup-matrix"], |
| "subgroupMatrixConfigs": [ |
| { "componentType": "f16", "M": 8, "N": 8, "K": 8 }, |
| { "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 } |
| ] |
| }, |
| "derive": { |
| "hasBias": false, |
| "aTransposedStorage": false, |
| "bTransposedStorage": "not true", |
| "yScalar": "\"f16\" if tensorDtypes.Y == \"float16\" else \"f32\"", |
| "mmaScalar": "\"f16\" if tensorDtypes.A == \"float16\" and tensorDtypes.B == \"float16\" else \"f32\"", |
| "inFeatures": "gemmK", |
| "outFeatures": "gemmN", |
| "tileM": "sgmatTileM", |
| "tileN": "sgmatTileN", |
| "tileK": "sgmatTileK", |
| "directAStorage": "sgmatDirectA", |
| "compensatedMatrixChunkTiles": "2 if sgmatDirectA and gemmK >= 8 * sgmatTileK else 0" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.SubgroupMatrix", |
| "shader": "gemm-subgroup-matrix.wgsl.jinja", |
| "bindings": ["x", "w", "y", "params"], |
| "dispatch": { |
| "x": "ceilDiv(gemmN, sgmatTileN)", |
| "y": "min(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)", |
| "z": "ceilDiv(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transAB_sgmat_bias", |
| "priority": 100, |
| "when": ["sgmatRowBiasContract", "transAFlag == true", "transBFlag == true"], |
| "requires": { |
| "features": ["subgroups", "chromium-experimental-subgroup-matrix"], |
| "subgroupMatrixConfigs": [ |
| { "componentType": "f16", "M": 8, "N": 8, "K": 8 }, |
| { "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 } |
| ] |
| }, |
| "derive": { |
| "hasBias": true, |
| "aTransposedStorage": true, |
| "bTransposedStorage": "not true", |
| "yScalar": "\"f16\" if tensorDtypes.Y == \"float16\" else \"f32\"", |
| "mmaScalar": "\"f16\" if tensorDtypes.A == \"float16\" and tensorDtypes.B == \"float16\" else \"f32\"", |
| "inFeatures": "gemmK", |
| "outFeatures": "gemmN", |
| "tileM": "sgmatTileM", |
| "tileN": "sgmatTileN", |
| "tileK": "sgmatTileK", |
| "directAStorage": "sgmatDirectA", |
| "compensatedMatrixChunkTiles": "2 if sgmatDirectA and gemmK >= 8 * sgmatTileK else 0" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.SubgroupMatrixBias", |
| "shader": "gemm-subgroup-matrix.wgsl.jinja", |
| "bindings": ["x", "w", "bias", "y", "params"], |
| "dispatch": { |
| "x": "ceilDiv(gemmN, sgmatTileN)", |
| "y": "min(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)", |
| "z": "ceilDiv(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transAB_sgmat", |
| "priority": 100, |
| "when": ["noBiasContract and sgmatContract", "transAFlag == true", "transBFlag == true"], |
| "requires": { |
| "features": ["subgroups", "chromium-experimental-subgroup-matrix"], |
| "subgroupMatrixConfigs": [ |
| { "componentType": "f16", "M": 8, "N": 8, "K": 8 }, |
| { "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 } |
| ] |
| }, |
| "derive": { |
| "hasBias": false, |
| "aTransposedStorage": true, |
| "bTransposedStorage": "not true", |
| "yScalar": "\"f16\" if tensorDtypes.Y == \"float16\" else \"f32\"", |
| "mmaScalar": "\"f16\" if tensorDtypes.A == \"float16\" and tensorDtypes.B == \"float16\" else \"f32\"", |
| "inFeatures": "gemmK", |
| "outFeatures": "gemmN", |
| "tileM": "sgmatTileM", |
| "tileN": "sgmatTileN", |
| "tileK": "sgmatTileK", |
| "directAStorage": "sgmatDirectA", |
| "compensatedMatrixChunkTiles": "2 if sgmatDirectA and gemmK >= 8 * sgmatTileK else 0" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.SubgroupMatrix", |
| "shader": "gemm-subgroup-matrix.wgsl.jinja", |
| "bindings": ["x", "w", "y", "params"], |
| "dispatch": { |
| "x": "ceilDiv(gemmN, sgmatTileN)", |
| "y": "min(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)", |
| "z": "ceilDiv(ceilDiv(gemmM, sgmatTileM), DISPATCH_FOLD_WIDTH)" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "notrans_bias", |
| "priority": 0, |
| "when": ["biasContract", "transAFlag == false", "transBFlag == false"], |
| "derive": { |
| "transA": false, |
| "transB": false, |
| "hasBias": true, |
| "rowBias": "rowBiasOk", |
| "scalarBias": "scalarBiasOk", |
| "columnBias": "columnBiasOk" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.Bias", |
| "shader": "fused-gemm.wgsl.jinja", |
| "bindings": [ |
| "a", |
| "b", |
| "bias", |
| "y", |
| { |
| "name": "params", |
| "struct": [ |
| { "name": "M", "type": "u32", "value": "gemmM" }, |
| { "name": "N", "type": "u32", "value": "gemmN" }, |
| { "name": "K", "type": "u32", "value": "gemmK" }, |
| { "name": "alpha", "type": "f32", "value": "attrs.alpha if has(attrs, \"alpha\") else 1" }, |
| { "name": "beta", "type": "f32", "value": "attrs.beta if has(attrs, \"beta\") else 1" } |
| ] |
| } |
| ], |
| "dispatch": { |
| "x": "min(ceilDiv(gemmN, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))", |
| "y": "min(ceilDiv(gemmM, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "notrans", |
| "priority": 0, |
| "when": ["noBiasContract", "transAFlag == false", "transBFlag == false"], |
| "derive": { "transA": false, "transB": false, "hasBias": false }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm", |
| "shader": "fused-gemm.wgsl.jinja", |
| "bindings": [ |
| "a", |
| "b", |
| "y", |
| { |
| "name": "params", |
| "struct": [ |
| { "name": "M", "type": "u32", "value": "gemmM" }, |
| { "name": "N", "type": "u32", "value": "gemmN" }, |
| { "name": "K", "type": "u32", "value": "gemmK" }, |
| { "name": "alpha", "type": "f32", "value": "attrs.alpha if has(attrs, \"alpha\") else 1" } |
| ] |
| } |
| ], |
| "dispatch": { |
| "x": "min(ceilDiv(gemmN, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))", |
| "y": "min(ceilDiv(gemmM, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transA_bias", |
| "priority": 0, |
| "when": ["biasContract", "transAFlag == true", "transBFlag == false"], |
| "derive": { |
| "transA": true, |
| "transB": false, |
| "hasBias": true, |
| "rowBias": "rowBiasOk", |
| "scalarBias": "scalarBiasOk", |
| "columnBias": "columnBiasOk" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.Bias", |
| "shader": "fused-gemm.wgsl.jinja", |
| "bindings": [ |
| "a", |
| "b", |
| "bias", |
| "y", |
| { |
| "name": "params", |
| "struct": [ |
| { "name": "M", "type": "u32", "value": "gemmM" }, |
| { "name": "N", "type": "u32", "value": "gemmN" }, |
| { "name": "K", "type": "u32", "value": "gemmK" }, |
| { "name": "alpha", "type": "f32", "value": "attrs.alpha if has(attrs, \"alpha\") else 1" }, |
| { "name": "beta", "type": "f32", "value": "attrs.beta if has(attrs, \"beta\") else 1" } |
| ] |
| } |
| ], |
| "dispatch": { |
| "x": "min(ceilDiv(gemmN, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))", |
| "y": "min(ceilDiv(gemmM, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transA", |
| "priority": 0, |
| "when": ["noBiasContract", "transAFlag == true", "transBFlag == false"], |
| "derive": { "transA": true, "transB": false, "hasBias": false }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm", |
| "shader": "fused-gemm.wgsl.jinja", |
| "bindings": [ |
| "a", |
| "b", |
| "y", |
| { |
| "name": "params", |
| "struct": [ |
| { "name": "M", "type": "u32", "value": "gemmM" }, |
| { "name": "N", "type": "u32", "value": "gemmN" }, |
| { "name": "K", "type": "u32", "value": "gemmK" }, |
| { "name": "alpha", "type": "f32", "value": "attrs.alpha if has(attrs, \"alpha\") else 1" } |
| ] |
| } |
| ], |
| "dispatch": { |
| "x": "min(ceilDiv(gemmN, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))", |
| "y": "min(ceilDiv(gemmM, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transB_bias", |
| "priority": 0, |
| "when": ["biasContract", "transAFlag == false", "transBFlag == true"], |
| "derive": { |
| "transA": false, |
| "transB": true, |
| "hasBias": true, |
| "rowBias": "rowBiasOk", |
| "scalarBias": "scalarBiasOk", |
| "columnBias": "columnBiasOk" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.Bias", |
| "shader": "fused-gemm.wgsl.jinja", |
| "bindings": [ |
| "a", |
| "b", |
| "bias", |
| "y", |
| { |
| "name": "params", |
| "struct": [ |
| { "name": "M", "type": "u32", "value": "gemmM" }, |
| { "name": "N", "type": "u32", "value": "gemmN" }, |
| { "name": "K", "type": "u32", "value": "gemmK" }, |
| { "name": "alpha", "type": "f32", "value": "attrs.alpha if has(attrs, \"alpha\") else 1" }, |
| { "name": "beta", "type": "f32", "value": "attrs.beta if has(attrs, \"beta\") else 1" } |
| ] |
| } |
| ], |
| "dispatch": { |
| "x": "min(ceilDiv(gemmN, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))", |
| "y": "min(ceilDiv(gemmM, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transB", |
| "priority": 0, |
| "when": ["noBiasContract", "transAFlag == false", "transBFlag == true"], |
| "derive": { "transA": false, "transB": true, "hasBias": false }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm", |
| "shader": "fused-gemm.wgsl.jinja", |
| "bindings": [ |
| "a", |
| "b", |
| "y", |
| { |
| "name": "params", |
| "struct": [ |
| { "name": "M", "type": "u32", "value": "gemmM" }, |
| { "name": "N", "type": "u32", "value": "gemmN" }, |
| { "name": "K", "type": "u32", "value": "gemmK" }, |
| { "name": "alpha", "type": "f32", "value": "attrs.alpha if has(attrs, \"alpha\") else 1" } |
| ] |
| } |
| ], |
| "dispatch": { |
| "x": "min(ceilDiv(gemmN, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))", |
| "y": "min(ceilDiv(gemmM, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transAB_bias", |
| "priority": 0, |
| "when": ["biasContract", "transAFlag == true", "transBFlag == true"], |
| "derive": { |
| "transA": true, |
| "transB": true, |
| "hasBias": true, |
| "rowBias": "rowBiasOk", |
| "scalarBias": "scalarBiasOk", |
| "columnBias": "columnBiasOk" |
| }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm.Bias", |
| "shader": "fused-gemm.wgsl.jinja", |
| "bindings": [ |
| "a", |
| "b", |
| "bias", |
| "y", |
| { |
| "name": "params", |
| "struct": [ |
| { "name": "M", "type": "u32", "value": "gemmM" }, |
| { "name": "N", "type": "u32", "value": "gemmN" }, |
| { "name": "K", "type": "u32", "value": "gemmK" }, |
| { "name": "alpha", "type": "f32", "value": "attrs.alpha if has(attrs, \"alpha\") else 1" }, |
| { "name": "beta", "type": "f32", "value": "attrs.beta if has(attrs, \"beta\") else 1" } |
| ] |
| } |
| ], |
| "dispatch": { |
| "x": "min(ceilDiv(gemmN, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))", |
| "y": "min(ceilDiv(gemmM, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))" |
| } |
| } |
| ] |
| }, |
| { |
| "id": "transAB", |
| "priority": 0, |
| "when": ["noBiasContract", "transAFlag == true", "transBFlag == true"], |
| "derive": { "transA": true, "transB": true, "hasBias": false }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "FusedGemm", |
| "shader": "fused-gemm.wgsl.jinja", |
| "bindings": [ |
| "a", |
| "b", |
| "y", |
| { |
| "name": "params", |
| "struct": [ |
| { "name": "M", "type": "u32", "value": "gemmM" }, |
| { "name": "N", "type": "u32", "value": "gemmN" }, |
| { "name": "K", "type": "u32", "value": "gemmK" }, |
| { "name": "alpha", "type": "f32", "value": "attrs.alpha if has(attrs, \"alpha\") else 1" } |
| ] |
| } |
| ], |
| "dispatch": { |
| "x": "min(ceilDiv(gemmN, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))", |
| "y": "min(ceilDiv(gemmM, 64), min(device.limits.maxComputeWorkgroupsPerDimension, 65535))" |
| } |
| } |
| ] |
| } |
| ] |
| } |
|
|