diff --git a/internal/buffered/image.go b/internal/buffered/image.go index 9224095dc..fcf763058 100644 --- a/internal/buffered/image.go +++ b/internal/buffered/image.go @@ -229,12 +229,32 @@ type Shader struct { } func NewShader(ir *shaderir.Program) *Shader { - return &Shader{ - shader: atlas.NewShader(ir), + s := &Shader{} + s.initialize(ir) + return s +} + +func (s *Shader) initialize(ir *shaderir.Program) { + if maybeCanAddDelayedCommand() { + if tryAddDelayedCommand(func() error { + s.initialize(ir) + return nil + }) { + return + } } + s.shader = atlas.NewShader(ir) } func (s *Shader) MarkDisposed() { + if maybeCanAddDelayedCommand() { + if tryAddDelayedCommand(func() error { + s.MarkDisposed() + return nil + }) { + return + } + } s.shader.MarkDisposed() s.shader = nil } diff --git a/internal/processtest/testdata/issue2162.go b/internal/processtest/testdata/issue2162.go new file mode 100644 index 000000000..619f1d9c2 --- /dev/null +++ b/internal/processtest/testdata/issue2162.go @@ -0,0 +1,65 @@ +// Copyright 2022 The Ebitengine Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build ignore +// +build ignore + +package main + +import ( + "errors" + + "github.com/hajimehoshi/ebiten/v2" +) + +func init() { + s, err := ebiten.NewShader([]byte(` +package main + +func Fragment(position vec4, texCoord vec2, color vec4) vec4 { + return vec4(1) +}`)) + if err != nil { + panic(err) + } + s.Dispose() +} + +var regularTermination = errors.New("regular termination") + +type Game struct { + counter int +} + +func (g *Game) Update() error { + g.counter++ + if g.counter > 1 { + return regularTermination + } + return nil +} + +func (g *Game) Draw(screen *ebiten.Image) { +} + +func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { + return outsideWidth, outsideHeight +} + +func main() { + // Run a game loop at least for one frame to ensure the shader disposed. + if err := ebiten.RunGame(&Game{}); err != nil && err != regularTermination { + panic(err) + } +}