Files
aego/render/gpuprof/gpuprof_test.go
sanspie 5eb1832907
ci-platforms / darwin amd64 smoke (push) Skipped
ci / build (amd64, linux, ubuntu-24.04) (push) Failing after 15m28s
ci / release (push) Skipped
ci-platforms / windows amd64 smoke (push) Skipped
ci-platforms / darwin arm64 smoke (push) Skipped
ci / checks (push) Successful in 7m47s
Complete Stage 12 for v0.12.0
2026-11-05 11:46:53 +03:00

85 lines
2.1 KiB
Go

package gpuprof
import (
"testing"
"aego/gpu"
"aego/gpu/null"
)
type sampleFrame struct {
gpu.Frame
ns uint64
ready bool
polls int
}
func (f *sampleFrame) QueryResult(gpu.QueryHandle) (uint64, bool) { f.polls++; return f.ns, f.ready }
type samplePass struct {
gpu.Pass
begins, ends int
}
func (p *samplePass) BeginQuery(gpu.QueryHandle) { p.begins++ }
func (p *samplePass) EndQuery() { p.ends++ }
type contextDevice struct {
*null.Device
generation uint64
lost bool
}
func (d *contextDevice) ContextGeneration() uint64 { return d.generation }
func (d *contextDevice) ContextLost() bool { return d.lost }
func TestCompletedDisjointSampleIsNotReportedAsGPUTime(t *testing.T) {
p := &Profiler{dev: null.New(), enabled: true, valid: true, last: 100}
p.pending[0] = true
f := &sampleFrame{ready: true, ns: 0}
p.Collect(f)
if _, valid := p.LastNS(); valid || p.pending[0] {
t.Fatal("disjoint sample was displayed or its slot was not recycled")
}
p.pending[1] = true
f.ns = 200
p.Collect(f)
if ns, valid := p.LastNS(); !valid || ns != 200 {
t.Fatal("valid asynchronous sample was lost")
}
}
func TestBusyQueryDoesNotEndAnUnstartedInterval(t *testing.T) {
p := &Profiler{enabled: true}
p.pending[p.head] = true
pass := &samplePass{}
p.Begin(pass)
p.End(pass)
if pass.begins != 0 || pass.ends != 0 {
t.Fatal("busy slot ended another interval")
}
p.pending[p.head] = false
p.Begin(pass)
p.End(pass)
p.End(pass)
if pass.begins != 1 || pass.ends != 1 {
t.Fatal("interval begin/end must be paired exactly once")
}
}
func TestContextLossInvalidatesSamplesAndPendingSlots(t *testing.T) {
d := &contextDevice{Device: null.New(), generation: 2, lost: true}
p := &Profiler{dev: d, enabled: true, generation: 1, valid: true, last: 10, active: true}
p.pending[0] = true
f := &sampleFrame{ns: 999, ready: true}
p.Collect(f)
if p.valid || p.active || f.polls != 0 {
t.Fatal("lost context exposed or polled GPU time")
}
d.lost = false
p.Collect(f)
if p.valid || p.pending[0] || f.polls != 0 {
t.Fatal("old-device query survived restore")
}
}