"""Writes runtime/vk_mvobj_fs.h: the SPIR-V of the per-object motion fragment shader (vk_mvobj.c), assembled here because it must be patched at run time (the Location of its input follows the vertex shader variant) and is small. The shader, as GLSL: #version 450 layout(location = 0) in vec4 prev; // last frame's clip position (patch 0015); Location patched layout(set = 0, binding = 1, std140) uniform P { vec4 p; }; // render size xy, this frame's jitter zw (pixels) layout(location = 0) out vec4 o; void main() { vec2 win = gl_FragCoord.xy - p.zw; // this frame's window position, without the jitter vec2 pn = prev.xy / prev.w; vec2 pwin = vec2((pn.x * 0.5 + 0.5) * p.x, (0.5 - pn.y * 0.5) * p.y); o = prev.w > 1e-6 ? vec4(pwin - win, 0.0, 0.0) : vec4(0.0); } The vector is last frame's window position minus this frame's, in render pixels, as runtime/shaders/dlaa_mv.comp writes it. Its descriptor set and binding are renumbered by vk_pipeline.c like a translated shader's (the .res.json text in vk_mvobj.c names binding 1 as slot 3). python tools/make_mvobj_fs.py """ import struct from pathlib import Path ROOT = Path(__file__).resolve().parent.parent OUT = ROOT / 'runtime' / 'vk_mvobj_fs.h' class Asm: def __init__(self): self.next = 1 self.sections = {k: [] for k in ('cap', 'mem', 'entry', 'exec', 'dec', 'types', 'func')} self.loc_word = None # index of the patched Location literal in the final words def id(self): self.next += 1 return self.next - 1 def op(self, sec, code, *words): self.sections[sec].append([(len(words) + 1) << 16 | code, *words]) return self.sections[sec][-1] def words(self): out = [0x07230203, 0x00010000, 0, self.next, 0] for sec in ('cap', 'mem', 'entry', 'exec', 'dec', 'types', 'func'): for ins in self.sections[sec]: if ins is self.loc_ins: self.loc_word = len(out) + 3 out.extend(ins) return out def string(s): b = s.encode() + b'\0' b += b'\0' * (-len(b) % 4) return list(struct.unpack('<%dI' % (len(b) // 4), b)) def f32(x): return struct.unpack('