@@ -71,12 +71,21 @@ class EpCapabilities:
7171 quantization (0 = highest accuracy, 4 = fastest).
7272 provider_options: Default ORT GenAI provider options dict for this EP.
7373 enable_graph_capture: Whether this EP defaults to GPU graph capture.
74- supports_past_present_share_buffer: Whether this EP requires past and present
75- KV-cache tensors to share the same pre-allocated backing buffer.
76- ``True`` for WebGPU, which allocates the full KV-cache at model
77- load time and maps both past and present views into it. ``False``
78- for all other EPs where the runtime manages KV-cache memory
79- dynamically.
74+ supports_past_present_share_buffer: Whether past and present KV-cache
75+ tensors alias the same pre-allocated buffer. When ``True``, the
76+ ORT GenAI runtime allocates a single KV-cache buffer at model load
77+ and maps both past and present as views into it, avoiding a
78+ per-step copy. This is the recommended setting for every EP that
79+ supports ``GroupQueryAttention`` (CPU, CUDA, DML, WebGPU,
80+ TRT-RTX). Set to ``False`` only for EPs that do not support GQA
81+ or cannot handle aliased KV-cache buffers.
82+ cap_kv_buffer_max_length: When ``True`` **and**
83+ ``supports_past_present_share_buffer`` is also ``True``, the
84+ generated ``max_length`` in genai_config is capped to avoid
85+ pre-allocating huge KV-cache buffers on memory-constrained
86+ devices. ``True`` only for WebGPU (consumer GPU); ``False`` for
87+ CUDA / CPU / DML / TRT-RTX where the runtime can handle large
88+ pre-allocations.
8089 """
8190
8291 name : str
@@ -90,6 +99,7 @@ class EpCapabilities:
9099 provider_options : dict [str , str ] = dataclasses .field (default_factory = dict )
91100 enable_graph_capture : bool = False
92101 supports_past_present_share_buffer : bool = False
102+ cap_kv_buffer_max_length : bool = False
93103
94104 def __post_init__ (self ) -> None :
95105 if not self .supports_fused_rope and self .qkv_pack_dtypes :
@@ -98,6 +108,13 @@ def __post_init__(self) -> None:
98108 f"supports_fused_rope=False — UnpackQKV lowering always fires for "
99109 f"this EP, so packing would be immediately undone."
100110 )
111+ if self .cap_kv_buffer_max_length and not self .supports_past_present_share_buffer :
112+ raise ValueError (
113+ f"EP '{ self .name } ': cap_kv_buffer_max_length=True requires "
114+ f"supports_past_present_share_buffer=True — the cap only matters "
115+ f"when the runtime pre-allocates the full KV-cache buffer at load "
116+ f"time, which is what buffer sharing enables."
117+ )
101118
102119
103120class EpRegistry :
@@ -199,6 +216,7 @@ def _register_builtins() -> None:
199216 gqa_dtypes = frozenset ({ir .DataType .FLOAT }),
200217 qkv_pack_dtypes = frozenset ({ir .DataType .FLOAT }),
201218 default_int4_accuracy_level = 4 ,
219+ supports_past_present_share_buffer = True ,
202220 ),
203221 EpCapabilities (
204222 name = "cuda" ,
@@ -211,6 +229,7 @@ def _register_builtins() -> None:
211229 "enable_cuda_graph" : "0" ,
212230 "enable_skip_layer_norm_strict_mode" : "1" ,
213231 },
232+ supports_past_present_share_buffer = True ,
214233 ),
215234 EpCapabilities (
216235 name = "dml" ,
@@ -221,6 +240,7 @@ def _register_builtins() -> None:
221240 qkv_pack_dtypes = frozenset (),
222241 supports_packed_multi_head_attention = True ,
223242 supports_fused_rope = False ,
243+ supports_past_present_share_buffer = True ,
224244 ),
225245 EpCapabilities (
226246 name = "webgpu" ,
@@ -229,6 +249,7 @@ def _register_builtins() -> None:
229249 default_int4_accuracy_level = 4 ,
230250 provider_options = {"enableGraphCapture" : "0" , "validationMode" : "basic" },
231251 supports_past_present_share_buffer = True ,
252+ cap_kv_buffer_max_length = True ,
232253 ),
233254 EpCapabilities (
234255 name = "trt-rtx" ,
@@ -239,12 +260,15 @@ def _register_builtins() -> None:
239260 supports_skip_layer_norm = False ,
240261 enable_graph_capture = True ,
241262 provider_options = {"enable_cuda_graph" : "1" },
263+ supports_past_present_share_buffer = True ,
242264 ),
243265 # onnx-standard: ONNX-only runtime — emits zero custom-domain ops.
244266 # All com.microsoft ops (SkipLayerNorm, PackedMHA) are expanded via
245267 # InlinePass to their standard-ONNX function bodies. No GQA or QKV
246268 # packing fusion is applied. Use this EP to produce models that run
247269 # on any conformant ONNX runtime without ORT extensions.
270+ # KV buffer sharing is unsupported here: GQA isn't emitted, so
271+ # standard Attention's concat-grow semantics handle the cache.
248272 EpCapabilities (
249273 name = "onnx-standard" ,
250274 gqa_dtypes = frozenset (), # no GroupQueryAttention
0 commit comments