You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
That change narrows §Graphics' parity claim from every GPU capability to every kernel kind, and records the capabilities Python cannot reach as named dispositions rather than leaving them silent. This is one of them, filed post-MVP by owner ruling.
What & why
Rust authoring can build a graphics kernel that pulls geometry from a vertex buffer and draws it indexed. Python cannot: draw takes vertex_count, instance_count, first_vertex, first_instance and no buffer argument (_engine.pyi:711-721, :474-478), so a Python author fabricates geometry from gl_VertexIndex — the fullscreen-triangle idiom, which is enough for a video effect and nothing else.
The unusual part, and the reason this is not a straight mirroring job: the Rust side has zero callers anywhere.acquire_vertex_buffer (gpu_context.rs:1846) and acquire_index_buffer (:1861) appear only in gpu_context.rs itself — the definitions plus the GpuContextLimitedAccess (:3720, :3727) and GpuContextFullAccess (:3981, :3987) mirrors. set_vertex_buffer (vulkan_graphics_kernel.rs:1361), set_index_buffer (:1374) and record_draw_indexed (vulkan_command_recorder.rs:1166) have no exercise in the tree at all; constructs_kernel_with_vertex_input_buffers (vulkan_graphics_kernel.rs:2837) only sets pipeline_state.vertex_input and never binds or draws.
So this exposes a capability nothing has ever used. That argues for designing the Python spelling on its own terms and letting the Rust surface follow, rather than mirroring an untested one — worth settling before implementation rather than during it.
Design
The missing primitive is a buffer a surface id can name. Constraints, inlined so this ticket stands alone:
No escalate op mints a vertex or index buffer. acquire_pixel_buffer lands on HostVulkanBuffer::new with usage TRANSFER_SRC | TRANSFER_DST | STORAGE_BUFFER (vulkan_buffer.rs:151-154) and no VERTEX_BUFFER bit.
The setters take &impl VulkanVertexBindable / VulkanIndexBindable, implemented only by VertexBuffer / IndexBuffer (vulkan_storage_binding.rs). A compile_fail,E0277 doctest proves PixelBuffer is rejected.
RegisteredHandle carries only PixelBuffer | Texture | Image, so a helper has no way to name a buffer today.
The wire half already ships elsewhere and is the closest precedent: build_triangles_blas hex-encodes flat Python lists (python_processor_context.rs:1068-1069), decoded and minted engine-side (subprocess_escalate.rs:2791-2798, vulkan_acceleration_structure.rs:159). But it mints AsBuffer::new_host_visible — vertex :201-207, index :223-229, usage ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR | SHADER_DEVICE_ADDRESS, host-visible by deliberate choice (:196-200) — which implements no bindable trait. The transfer shape carries over; the buffer type and usage flags do not.
An indexed draw needs the index-range check the BLAS path just gained (vulkan_acceleration_structure.rs, PR feat(engine)!: graphics and ray-tracing kernels at Python parity #1896) — except an indexed draw does have a robustness escape hatch where an acceleration-structure build does not, so the rule is not identical. State which applies.
Related but covering neither: #505 (the original graphics-kernel RHI), #658, #964 (buffer-model collapse), #503 (texel-buffer descriptor types).
Done means
An escalate op mints a vertex/index buffer and a surface id names it.
Binding resolution grows a buffer arm, so storage_buffer / uniform_buffer bindings and vertex/index buffers stop being refused for the same missing-primitive reason.
draw takes vertex buffers and an indexed variant, with _engine.pyi entries.
Four refusals retire: subprocess_escalate.rs:2492, :2504, :3512 (draw-time) and the register-time vertex_input_bindings refusal.
The §Graphics disposition naming this gap is removed from ARCHITECTURE.md in the same PR.
Validation shape
A Python processor draws indexed geometry from a vertex buffer it filled, end to end from a helper child. One test per retired refusal, asserting the capability rather than the message. An out-of-range index is refused before submission. requires_gpu tests execute on the rig only — CI green is not proof for this ticket.
Non-derivable notes
Filed post-MVP by owner ruling 2026-08-17: a fullscreen effect has no use for vertex buffers, and the MVP sentence invites editing a scaffolded processor rather than authoring geometry. Do not pull this into MVP without a plan change — the §Graphics entry names it as a known gap, and closing it silently would leave the plan claiming a gap that no longer exists.
Change:
docs/plan/changes/kernel-kind-parity-bar.md(approved 2026-08-17, PR #1897), disposition 1. Plan:[python-kernel-api]§Graphics.That change narrows §Graphics' parity claim from every GPU capability to every kernel kind, and records the capabilities Python cannot reach as named dispositions rather than leaving them silent. This is one of them, filed post-MVP by owner ruling.
What & why
Rust authoring can build a graphics kernel that pulls geometry from a vertex buffer and draws it indexed. Python cannot:
drawtakesvertex_count,instance_count,first_vertex,first_instanceand no buffer argument (_engine.pyi:711-721,:474-478), so a Python author fabricates geometry fromgl_VertexIndex— the fullscreen-triangle idiom, which is enough for a video effect and nothing else.The unusual part, and the reason this is not a straight mirroring job: the Rust side has zero callers anywhere.
acquire_vertex_buffer(gpu_context.rs:1846) andacquire_index_buffer(:1861) appear only ingpu_context.rsitself — the definitions plus theGpuContextLimitedAccess(:3720,:3727) andGpuContextFullAccess(:3981,:3987) mirrors.set_vertex_buffer(vulkan_graphics_kernel.rs:1361),set_index_buffer(:1374) andrecord_draw_indexed(vulkan_command_recorder.rs:1166) have no exercise in the tree at all;constructs_kernel_with_vertex_input_buffers(vulkan_graphics_kernel.rs:2837) only setspipeline_state.vertex_inputand never binds or draws.So this exposes a capability nothing has ever used. That argues for designing the Python spelling on its own terms and letting the Rust surface follow, rather than mirroring an untested one — worth settling before implementation rather than during it.
Design
The missing primitive is a buffer a surface id can name. Constraints, inlined so this ticket stands alone:
acquire_pixel_bufferlands onHostVulkanBuffer::newwith usageTRANSFER_SRC | TRANSFER_DST | STORAGE_BUFFER(vulkan_buffer.rs:151-154) and noVERTEX_BUFFERbit.&impl VulkanVertexBindable/VulkanIndexBindable, implemented only byVertexBuffer/IndexBuffer(vulkan_storage_binding.rs). Acompile_fail,E0277doctest provesPixelBufferis rejected.RegisteredHandlecarries onlyPixelBuffer | Texture | Image, so a helper has no way to name a buffer today.build_triangles_blashex-encodes flat Python lists (python_processor_context.rs:1068-1069), decoded and minted engine-side (subprocess_escalate.rs:2791-2798,vulkan_acceleration_structure.rs:159). But it mintsAsBuffer::new_host_visible— vertex:201-207, index:223-229, usageACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR | SHADER_DEVICE_ADDRESS, host-visible by deliberate choice (:196-200) — which implements no bindable trait. The transfer shape carries over; the buffer type and usage flags do not.vulkan_acceleration_structure.rs, PR feat(engine)!: graphics and ray-tracing kernels at Python parity #1896) — except an indexed draw does have a robustness escape hatch where an acceleration-structure build does not, so the rule is not identical. State which applies.Related but covering neither: #505 (the original graphics-kernel RHI), #658, #964 (buffer-model collapse), #503 (texel-buffer descriptor types).
Done means
storage_buffer/uniform_bufferbindings and vertex/index buffers stop being refused for the same missing-primitive reason.drawtakes vertex buffers and an indexed variant, with_engine.pyientries.subprocess_escalate.rs:2492,:2504,:3512(draw-time) and the register-timevertex_input_bindingsrefusal.ARCHITECTURE.mdin the same PR.Validation shape
A Python processor draws indexed geometry from a vertex buffer it filled, end to end from a helper child. One test per retired refusal, asserting the capability rather than the message. An out-of-range index is refused before submission.
requires_gputests execute on the rig only — CI green is not proof for this ticket.Non-derivable notes
Filed post-MVP by owner ruling 2026-08-17: a fullscreen effect has no use for vertex buffers, and the MVP sentence invites editing a scaffolded processor rather than authoring geometry. Do not pull this into MVP without a plan change — the §Graphics entry names it as a known gap, and closing it silently would leave the plan claiming a gap that no longer exists.