1212#include < executorch/backends/webgpu/runtime/ops/sdpa/sdpa_compute_attn_weights_wgsl.h>
1313#include < executorch/backends/webgpu/runtime/ops/sdpa/sdpa_compute_out_wgsl.h>
1414#include < executorch/backends/webgpu/runtime/ops/sdpa/sdpa_softmax_wgsl.h>
15+ #include < executorch/backends/webgpu/runtime/ops/sdpa_fd_decode/SdpaFdDecode.h>
1516#include < executorch/backends/webgpu/runtime/ops/update_cache/update_cache_wgsl.h>
1617
1718#include < webgpu/webgpu.h>
1819
1920#include < cmath>
2021#include < cstdint>
21- #include < cstring>
2222#include < stdexcept>
2323#include < string>
2424
@@ -128,22 +128,6 @@ static ComputeOutParams make_compute_out_params(
128128 return p;
129129}
130130
131- // Create a uniform buffer initialized with the given bytes.
132- WGPUBuffer
133- make_uniform_buffer (WebGPUGraph& graph, const void * data, size_t size) {
134- WGPUDevice device = graph.device ();
135- WGPUBufferDescriptor desc = {};
136- desc.size = size;
137- desc.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst;
138- desc.mappedAtCreation = true ;
139- WGPUBuffer buffer = wgpuDeviceCreateBuffer (device, &desc);
140- void * mapped = wgpuBufferGetMappedRange (buffer, 0 , size);
141- std::memcpy (mapped, data, size);
142- wgpuBufferUnmap (buffer);
143- graph.add_uniform_buffer_bytes (size);
144- return buffer;
145- }
146-
147131// A buffer + its byte size, for binding.
148132struct BufferBinding {
149133 WGPUBuffer buffer;
@@ -262,7 +246,7 @@ static WGPUBuffer record_update_cache_dispatch(
262246 device, static_cast <uint32_t >(kv_numel), uc_wg, label);
263247 UpdateCacheParams uc =
264248 make_update_cache_params (kv_numel, kv_dst_offset, cache_numel);
265- WGPUBuffer ubuf = make_uniform_buffer (graph, &uc, sizeof (uc));
249+ WGPUBuffer ubuf = graph. make_uniform_buffer (&uc, sizeof (uc));
266250 BufferBinding bindings[2 ] = {
267251 {cache.buffer , cache.nbytes }, {src.buffer , src.nbytes }};
268252 build_dispatch (
@@ -429,9 +413,6 @@ void sdpa_with_kv_cache_impl(WebGPUGraph& graph, const std::vector<int>& args) {
429413 static_cast <uint64_t >(S) *
430414 static_cast <uint64_t >(dynamic_pos ? Cmax : context_len);
431415 const uint64_t aw_bytes = aw_cap_floats * sizeof (float );
432- // Prefill scratch scales as Hq·S·Cmax; can be large for long-context prefill.
433- WGPUBuffer attn_weights = graph.create_scratch_buffer (aw_bytes);
434- WGPUBuffer attn_weights_softmax = graph.create_scratch_buffer (aw_bytes);
435416
436417 // Dynamic input_pos: the resize hook rewrites these per step.
437418 WGPUBuffer uc_k_buf = nullptr , uc_v_buf = nullptr , qk_buf = nullptr ,
@@ -475,6 +456,18 @@ void sdpa_with_kv_cache_impl(WebGPUGraph& graph, const std::vector<int>& args) {
475456 dynamic_pos,
476457 " update_cache(V)" );
477458
459+ // FlashDecoding decode (S==1, static pos). Shapes FD can't handle (head dim
460+ // > kSdpaFdMaxHeadDim) fall through to the materialized path below.
461+ if (S == 1 && !dynamic_pos && D <= kSdpaFdMaxHeadDim ) {
462+ sdpa_fd_decode_dispatch (
463+ graph, q, k_cache, v_cache, out, Hq, Hkv, D, context_len, g, scale);
464+ return ;
465+ }
466+
467+ // QK/softmax scratch — allocated only on the non-FD path (Hq*S*Cmax prefill).
468+ WGPUBuffer attn_weights = graph.create_scratch_buffer (aw_bytes);
469+ WGPUBuffer attn_weights_softmax = graph.create_scratch_buffer (aw_bytes);
470+
478471 // --- Dispatch 3: QK -> attn_weights. One thread per TM x TN tile.
479472 {
480473 if (aw_floats > UINT32_MAX ) {
@@ -487,7 +480,7 @@ void sdpa_with_kv_cache_impl(WebGPUGraph& graph, const std::vector<int>& args) {
487480 device, static_cast <uint32_t >(qk_tiles), qk_wg, " QK" );
488481 AttnWeightsParams p = make_attn_weights_params (
489482 S, Hq, Hkv, D, context_len, input_pos, g, scale);
490- WGPUBuffer ubuf = make_uniform_buffer (graph, &p, sizeof (p));
483+ WGPUBuffer ubuf = graph. make_uniform_buffer (&p, sizeof (p));
491484 BufferBinding bindings[3 ] = {
492485 {attn_weights, aw_bytes},
493486 {q.buffer , q.nbytes },
@@ -513,7 +506,7 @@ void sdpa_with_kv_cache_impl(WebGPUGraph& graph, const std::vector<int>& args) {
513506 const uint32_t wgc = utils::compute_1d_workgroup_count (
514507 device, static_cast <uint32_t >(Hq * S), 1 , " softmax" );
515508 SoftmaxParams p = make_softmax_params (Hq, S, context_len);
516- WGPUBuffer ubuf = make_uniform_buffer (graph, &p, sizeof (p));
509+ WGPUBuffer ubuf = graph. make_uniform_buffer (&p, sizeof (p));
517510 BufferBinding bindings[2 ] = {
518511 {attn_weights_softmax, aw_bytes}, {attn_weights, aw_bytes}};
519512 build_dispatch (
@@ -537,7 +530,7 @@ void sdpa_with_kv_cache_impl(WebGPUGraph& graph, const std::vector<int>& args) {
537530 const uint32_t wgc = utils::compute_1d_workgroup_count (
538531 device, static_cast <uint32_t >(av_tiles), av_wg, " AV" );
539532 ComputeOutParams p = make_compute_out_params (S, Hq, Hkv, D, context_len, g);
540- WGPUBuffer ubuf = make_uniform_buffer (graph, &p, sizeof (p));
533+ WGPUBuffer ubuf = graph. make_uniform_buffer (&p, sizeof (p));
541534 BufferBinding bindings[3 ] = {
542535 {out.buffer , out.nbytes },
543536 {attn_weights_softmax, aw_bytes},
0 commit comments