1package vulkan
2
3import (
4 "fmt"
5 "image/color"
6 "testing"
7 "time"
8
9 "github.com/bnema/neferwl/internal/ports"
10)
11
12// BenchmarkComposeFullTarget composes a full-redraw frame (three windows
13// covering the output, moved every frame as a workspace swipe does) into an
14// exported target of each modifier the device offers for B8G8R8A8, and waits
15// for the GPU after every frame: the time per frame is the GPU cost of the
16// target's tiling/compression layout (DCC retile passes included). Select the
17// GPU with NEFERWL_VK_DEVICE; the size is 2560x1600.
18func BenchmarkComposeFullTarget(b *testing.B) {
19 const w, h = 2560, 1600
20 probe, err := New(w, h)
21 if err != nil {
22 b.Skipf("Vulkan unavailable: %v", err)
23 }
24 mods := append([]uint64(nil), probe.renderMods...)
25 planes := probe.modPlanes
26 probe.Close()
27 if len(mods) == 0 {
28 b.Skip("device exports no render modifier")
29 }
30 for _, m := range mods {
31 b.Run(fmt.Sprintf("%#x/planes=%d", m, planes[m]), func(b *testing.B) {
32 r, err := New(w, h)
33 if err != nil {
34 b.Skipf("Vulkan unavailable: %v", err)
35 }
36 defer r.Close()
37 bufs, err := r.ExportTargets(2, []uint64{m}, false)
38 if err != nil {
39 b.Skipf("modifier %#x not exportable: %v", m, err)
40 }
41 defer func() {
42 for _, buf := range bufs {
43 for _, p := range buf.Planes {
44 p.File.Close()
45 }
46 }
47 }()
48 ww := w / 2
49 contents := map[ports.WindowID]ports.SurfaceContent{}
50 for i, c := range []color.RGBA{{R: 200, A: 255}, {G: 200, A: 255}, {B: 200, A: 255}} {
51 content := solidContent(b, ww, h, c)
52 content.ID, content.Surface, content.Seq, content.Version = ports.WindowID(i+1), uint64(i+1), 1, 1
53 contents[content.ID] = content
54 }
55 scene := func(i int) ports.Scene {
56 x := i % 64
57 return ports.Scene{Seq: uint64(i + 1), Scale: 1, Background: "#101010", Windows: []ports.SceneWindow{
58 {ID: 1, Rect: ports.Rect{X: x - ww, W: ww, H: h}},
59 {ID: 2, Rect: ports.Rect{X: x, W: ww, H: h}},
60 {ID: 3, Rect: ports.Rect{X: x + ww, W: ww, H: h}},
61 }}
62 }
63 frame := func(i int) {
64 r.UseTarget(i % 2)
65 if err := render(r, scene(i), contents); err != nil {
66 b.Fatal(err)
67 }
68 if err := r.waitFrame(r.submitted); err != nil {
69 b.Fatal(err)
70 }
71 }
72 for i := range 8 {
73 frame(i)
74 }
75 b.ResetTimer()
76 start := time.Now()
77 for i := range b.N {
78 frame(i + 8)
79 }
80 b.ReportMetric(float64(time.Since(start).Microseconds())/1000/float64(b.N), "ms/frame")
81 })
82 }
83}