1//go:build linux
2
3// Package session is the Wayland-free presentation core: Vulkan rendering into
4// DMA-BUF buffers, DRM syncobj timelines and buffer ownership.
5package session
6
7import (
8 "fmt"
9
10 "github.com/bnema/nefergui/internal/presentation/buffers"
11 "github.com/bnema/nefergui/internal/presentation/vkdevice"
12)
13
14// Slot is the GPU side of one pool buffer. Descriptors are -1 when unset.
15type Slot struct {
16 Buffer *buffers.Buffer
17 Image *vkdevice.Image
18 Frame *vkdevice.Frame
19 First bool
20 Wait *vkdevice.BinaryFence
21 PendingWait *vkdevice.BinaryFence
22 WaitInFlight bool
23 ReleaseHandle uint32
24 ReleaseFD int // eventfd armed on each commit's release point
25 ReleaseExport int // exported syncobj fd of the release timeline
26 Presented bool // the caller has been told to import this buffer
27}
28
29// beginReady does not change Pool ownership until the previous GPU submission
30// has completed. An unready available buffer is retried on a bounded wakeup.
31func beginReady(pool *buffers.Pool, slots map[uint64]*Slot, ready func(*Slot) (bool, error)) (*buffers.Buffer, *Slot, bool, error) {
32 waiting := false
33 for _, b := range pool.Buffers {
34 if b.Generation != pool.Generation || b.State != buffers.Available {
35 continue
36 }
37 slot := slots[b.ID]
38 if slot == nil {
39 return nil, nil, false, fmt.Errorf("missing slot %d", b.ID)
40 }
41 ok, err := ready(slot)
42 if err != nil {
43 return nil, nil, false, err
44 }
45 if !ok {
46 waiting = true
47 continue
48 }
49 b.State = buffers.Rendering
50 b.WlReleased, b.PointSignaled = false, false
51 return b, slot, false, nil
52 }
53 return nil, nil, waiting, nil
54}
55
56// installReleaseWait holds the new semaphore until the old submission is done.
57// Only the state owner calls it. On an unready fence it leaves Pool Released.
58func installReleaseWait(slot *Slot, next *vkdevice.BinaryFence, ready func() (bool, error)) (bool, error) {
59 if slot.Wait != nil && slot.WaitInFlight {
60 ok, err := ready()
61 if err != nil {
62 return false, err
63 }
64 if !ok {
65 slot.PendingWait = next
66 return false, nil
67 }
68 }
69 if slot.Wait != nil {
70 slot.Wait.Close()
71 }
72 slot.Wait, slot.PendingWait, slot.WaitInFlight = next, nil, false
73 return true, nil
74}
75
76type retiredPipelines struct {
77 generation uint64
78 list *vkdevice.Pipeline
79}