From 6f2a98c667f993a247c1202f3012322f5f3177db Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 30 Dec 2020 18:02:18 +0100 Subject: [PATCH] gpu: make GPU an interface to prepare for second implementation While here, merge BeginFrame and EndFrame; the split was done for performance reasons, yet never measured. Signed-off-by: Elias Naur --- app/headless/headless.go | 6 ++---- app/loop.go | 7 ++++--- gpu/gpu.go | 38 +++++++++++++++++++++++++++----------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/app/headless/headless.go b/app/headless/headless.go index 67544664..9a9ad25b 100644 --- a/app/headless/headless.go +++ b/app/headless/headless.go @@ -18,7 +18,7 @@ type Window struct { size image.Point ctx context backend backend.Device - gpu *gpu.GPU + gpu gpu.GPU fboTex backend.Texture fbo backend.Framebuffer } @@ -109,9 +109,7 @@ func (w *Window) Release() { func (w *Window) Frame(frame *op.Ops) error { return contextDo(w.ctx, func() error { w.gpu.Collect(w.size, frame) - w.gpu.BeginFrame() - w.gpu.EndFrame() - return nil + return w.gpu.Frame() }) } diff --git a/app/loop.go b/app/loop.go index e0da75a0..c6c9b2ef 100644 --- a/app/loop.go +++ b/app/loop.go @@ -88,10 +88,11 @@ func (l *renderLoop) renderLoop(ctx window.Context) error { g.Collect(frame.viewport, frame.ops) // Signal that we're done with the frame ops. l.ack <- struct{}{} - g.BeginFrame() var res frameResult - res.err = ctx.Present() - g.EndFrame() + res.err = g.Frame() + if res.err == nil { + res.err = ctx.Present() + } res.profile = g.Profile() ctx.Unlock() l.results <- res diff --git a/gpu/gpu.go b/gpu/gpu.go index 547fefce..067c7c22 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -9,6 +9,7 @@ package gpu import ( "encoding/binary" + "errors" "fmt" "image" "image/color" @@ -28,7 +29,14 @@ import ( "gioui.org/op/clip" ) -type GPU struct { +type GPU interface { + Release() + Collect(viewport image.Point, frameOps *op.Ops) + Frame() error + Profile() string +} + +type gpu struct { cache *resourceCache defFBO backend.Framebuffer @@ -363,9 +371,19 @@ const ( materialTexture ) -func New(ctx backend.Device) (*GPU, error) { +func New(ctx backend.Device) (GPU, error) { + feats := ctx.Caps().Features + switch { + case feats.Has(backend.FeatureFloatRenderTargets): + return newGPU(ctx) + default: + return nil, errors.New("gpu: no support for float render targets nor compute") + } +} + +func newGPU(ctx backend.Device) (*gpu, error) { defFBO := ctx.CurrentFramebuffer() - g := &GPU{ + g := &gpu{ defFBO: defFBO, cache: newResourceCache(), } @@ -376,13 +394,13 @@ func New(ctx backend.Device) (*GPU, error) { return g, nil } -func (g *GPU) init(ctx backend.Device) error { +func (g *gpu) init(ctx backend.Device) error { g.ctx = ctx g.renderer = newRenderer(ctx) return nil } -func (g *GPU) Release() { +func (g *gpu) Release() { g.renderer.release() g.drawOps.pathCache.release() g.cache.release() @@ -391,7 +409,7 @@ func (g *GPU) Release() { } } -func (g *GPU) Collect(viewport image.Point, frameOps *op.Ops) { +func (g *gpu) Collect(viewport image.Point, frameOps *op.Ops) { g.renderer.blitter.viewport = viewport g.renderer.pather.viewport = viewport g.drawOps.reset(g.cache, viewport) @@ -406,7 +424,7 @@ func (g *GPU) Collect(viewport image.Point, frameOps *op.Ops) { } } -func (g *GPU) BeginFrame() { +func (g *gpu) Frame() error { g.ctx.BeginFrame() defer g.ctx.EndFrame() viewport := g.renderer.blitter.viewport @@ -440,9 +458,6 @@ func (g *GPU) BeginFrame() { g.renderer.pather.stenciler.invalidateFBO() g.coverTimer.end() g.ctx.BindFramebuffer(g.defFBO) -} - -func (g *GPU) EndFrame() { g.cleanupTimer.begin() g.cache.frame() g.drawOps.pathCache.frame() @@ -456,9 +471,10 @@ func (g *GPU) EndFrame() { ft = ft.Round(q) g.profile = fmt.Sprintf("draw:%7s gpu:%7s zt:%7s st:%7s cov:%7s", frameDur, ft, zt, st, covt) } + return nil } -func (g *GPU) Profile() string { +func (g *gpu) Profile() string { return g.profile }