v0.7.1 e0abc49

fence.go RawHistoryFolder

1//go:build linux
2
3package vkdevice
4
5import (
6	"fmt"
7	"unsafe"
8
9	"github.com/bnema/purego-vulkan/vulkan"
10)
11
12// BinaryFence exports a SYNC_FD after its queue submit, never an OPAQUE_FD.
13// Vulkan consumes a successfully imported SYNC_FD; a failed import leaves it
14// with the caller. Exported SYNC_FDs belong to the caller until DRM accepts.
15type BinaryFence struct {
16	Device    *Device
17	Semaphore vulkan.Semaphore
18	// Reused call arguments: the bindings heap-allocate pointer arguments, and
19	// a fence has a single owner that calls these methods one at a time.
20	getInfo    vulkan.SemaphoreGetFdInfoKHR
21	importInfo vulkan.ImportSemaphoreFdInfoKHR
22	fd         int32
23}
24
25func (d *Device) NewBinaryFence(export bool) (*BinaryFence, error) {
26	ci := vulkan.SemaphoreCreateInfo{SType: vulkan.StructureTypeSemaphoreCreateInfo}
27	if export {
28		ex := vulkan.ExportSemaphoreCreateInfo{SType: vulkan.StructureTypeExportSemaphoreCreateInfo, HandleTypes: vulkan.ExternalSemaphoreHandleTypeSyncFDBit}
29		ci.Next = unsafe.Pointer(&ex)
30		var sem vulkan.Semaphore
31		if err := vulkan.Check(d.Dispatch.CreateSemaphore(d.Logical, &ci, nil, &sem)); err != nil {
32			return nil, fmt.Errorf("create SYNC_FD semaphore: %w", err)
33		}
34		return &BinaryFence{Device: d, Semaphore: sem}, nil
35	}
36	var sem vulkan.Semaphore
37	if err := vulkan.Check(d.Dispatch.CreateSemaphore(d.Logical, &ci, nil, &sem)); err != nil {
38		return nil, err
39	}
40	return &BinaryFence{Device: d, Semaphore: sem}, nil
41}
42
43func (s *BinaryFence) Export() (int, error) {
44	s.getInfo = vulkan.SemaphoreGetFdInfoKHR{SType: vulkan.StructureTypeSemaphoreGetFDInfoKHR, Semaphore: s.Semaphore, HandleType: vulkan.ExternalSemaphoreHandleTypeSyncFDBit}
45	s.fd = -1
46	if err := vulkan.Check(s.Device.Dispatch.GetSemaphoreFdKHR(s.Device.Logical, &s.getInfo, &s.fd)); err != nil {
47		return -1, fmt.Errorf("export Vulkan SYNC_FD: %w", err)
48	}
49	return int(s.fd), nil
50}
51
52func (s *BinaryFence) ImportTemporary(fd int) error {
53	s.importInfo = vulkan.ImportSemaphoreFdInfoKHR{SType: vulkan.StructureTypeImportSemaphoreFDInfoKHR, Semaphore: s.Semaphore, Flags: vulkan.SemaphoreImportTemporaryBit, HandleType: vulkan.ExternalSemaphoreHandleTypeSyncFDBit, Fd: int32(fd)}
54	return vulkan.Check(s.Device.Dispatch.ImportSemaphoreFdKHR(s.Device.Logical, &s.importInfo))
55}
56
57func (s *BinaryFence) Close() {
58	if s == nil || s.Semaphore == 0 {
59		return
60	}
61	s.Device.Dispatch.DestroySemaphore(s.Device.Logical, s.Semaphore, nil)
62	s.Semaphore = 0
63}
64
65// SubmitEmpty is a hardware probe for the fence bridge. The production
66// renderer must submit its draw command buffer instead of an empty submit.
67// The queue is idle before exporting so this test isolates FD interop from
68// in-flight rendering; it does not authorize a CPU-wait presentation fallback.
69func (d *Device) SubmitEmpty(signal *BinaryFence, wait *BinaryFence) error {
70	info := vulkan.SubmitInfo2{SType: vulkan.StructureTypeSubmitInfo2}
71	if signal != nil {
72		s := vulkan.SemaphoreSubmitInfo{SType: vulkan.StructureTypeSemaphoreSubmitInfo, Semaphore: signal.Semaphore, StageMask: vulkan.PipelineStage2AllCommandsBit}
73		info.SignalSemaphoreInfoCount = 1
74		info.SignalSemaphoreInfos = &s
75	}
76	if wait != nil {
77		w := vulkan.SemaphoreSubmitInfo{SType: vulkan.StructureTypeSemaphoreSubmitInfo, Semaphore: wait.Semaphore, StageMask: vulkan.PipelineStage2AllCommandsBit}
78		info.WaitSemaphoreInfoCount = 1
79		info.WaitSemaphoreInfos = &w
80	}
81	if err := vulkan.Check(d.Dispatch.QueueSubmit2(d.Queue, 1, &info, 0)); err != nil {
82		return fmt.Errorf("submit SYNC_FD semaphore: %w", err)
83	}
84	return vulkan.Check(d.Dispatch.QueueWaitIdle(d.Queue))
85}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 12

↑↓ moveenter openesc close