D731 - Window-space positions are drawn through a fixed viewport

Status: decided Date: 2026-09-27

A draw whose PA_CL_VTE_CNTL is the value radeonsi gives a window-space shader - no viewport scale or offset, x, y and z already divided, the fourth component 1/W taken as is (si_state_shaders.cpp:1321-1322; Gallium's VS_WINDOW_SPACE_POSITION, docs/gallium/tgsi.rst:3705-3711) - runs its primitive shader as a module that writes (x W / S, y W / S, z W, W) for W = 1/q, under a viewport of scale S and offset zero on both axes, S being WINDOW_SPACE_SCALE, 8192. Vulkan's divide and viewport take that back to the pixel the guest named. Any other value with the x/y terms off is refused by name, as before.

Why: radeonsi's blits write pixel positions; Vulkan has no window-space position, only clip space, so the translation and the viewport between them have to cancel. A power of two makes the scaling exact, and one fixed transform means one module per shader rather than one per target size. The window-space form belongs to the shader in radeonsi, so a module per (shader, position space) costs nothing where it is not used.

Limits: a position more than S pixels from the origin falls outside the clip volume and is clipped; so is a depth outside [0, 1], which the hardware, with clipping disabled, would not clip. A device whose maxViewportDimensions or viewportBoundsRange cannot take the viewport refuses the draw by name.

Rejected: