mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-26 02:42:02 +01:00
restorable: Add tests to dispose shaders
When a shader is disposed, all the images depending on it should become stale, i.e., discard its all the rendering history items, because they cannot be restored due to the lack of data on the GPU.
This commit is contained in:
parent
8e6f19b37a
commit
7b9cc8deb4
@ -470,6 +470,16 @@ func (i *Image) makeStaleIfDependingOn(target *Image) {
|
||||
}
|
||||
}
|
||||
|
||||
// makeStaleIfDependingOnShader makes the image stale if the image depends on shader.
|
||||
func (i *Image) makeStaleIfDependingOnShader(shader *Shader) {
|
||||
if i.stale {
|
||||
return
|
||||
}
|
||||
if i.dependsOnShader(shader) {
|
||||
i.makeStale()
|
||||
}
|
||||
}
|
||||
|
||||
// readPixelsFromGPU reads the pixels from GPU and resolves the image's 'stale' state.
|
||||
func (i *Image) readPixelsFromGPU() error {
|
||||
pix, err := i.image.Pixels()
|
||||
@ -516,6 +526,16 @@ func (i *Image) dependsOn(target *Image) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// dependsOnShader reports whether the image depends on shader.
|
||||
func (i *Image) dependsOnShader(shader *Shader) bool {
|
||||
for _, c := range i.drawTrianglesHistory {
|
||||
if c.shader == shader {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// dependingImages returns all images that is depended by the image.
|
||||
func (i *Image) dependingImages() map[*Image]struct{} {
|
||||
r := map[*Image]struct{}{}
|
||||
|
@ -126,14 +126,12 @@ func (i *images) addShader(shader *Shader) {
|
||||
|
||||
// remove removes img from the images.
|
||||
func (i *images) remove(img *Image) {
|
||||
i.makeStaleIfDependingOnImpl(img)
|
||||
i.makeStaleIfDependingOn(img)
|
||||
delete(i.images, img)
|
||||
}
|
||||
|
||||
func (i *images) removeShader(shader *Shader) {
|
||||
// TODO: Do we have to make images stale?
|
||||
// However, dependencies are determiend by uniform variables...
|
||||
// ??
|
||||
i.makeStaleIfDependingOnShader(shader)
|
||||
delete(i.shaders, shader)
|
||||
}
|
||||
|
||||
@ -153,12 +151,8 @@ func (i *images) resolveStaleImages() error {
|
||||
// When target is modified, all images depending on target can't be restored with target.
|
||||
// makeStaleIfDependingOn is called in such situation.
|
||||
func (i *images) makeStaleIfDependingOn(target *Image) {
|
||||
i.makeStaleIfDependingOnImpl(target)
|
||||
}
|
||||
|
||||
func (i *images) makeStaleIfDependingOnImpl(target *Image) {
|
||||
if target == nil {
|
||||
panic("restorable: target must not be nil at makeStaleIfDependingOnImpl")
|
||||
panic("restorable: target must not be nil at makeStaleIfDependingOn")
|
||||
}
|
||||
if i.lastTarget == target {
|
||||
return
|
||||
@ -169,6 +163,16 @@ func (i *images) makeStaleIfDependingOnImpl(target *Image) {
|
||||
}
|
||||
}
|
||||
|
||||
// makeStaleIfDependingOn makes all the images stale that depend on shader.
|
||||
func (i *images) makeStaleIfDependingOnShader(shader *Shader) {
|
||||
if shader == nil {
|
||||
panic("restorable: shader must not be nil at makeStaleIfDependingOnShader")
|
||||
}
|
||||
for img := range i.images {
|
||||
img.makeStaleIfDependingOnShader(shader)
|
||||
}
|
||||
}
|
||||
|
||||
// restore restores the images.
|
||||
//
|
||||
// Restoring means to make all *graphicscommand.Image objects have their textures and framebuffers.
|
||||
|
@ -136,3 +136,35 @@ func TestShaderMultipleSources(t *testing.T) {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShaderDispose(t *testing.T) {
|
||||
if !graphicscommand.IsShaderAvailable() {
|
||||
t.Skip("shader is not available on this environment")
|
||||
}
|
||||
|
||||
img := NewImage(1, 1, false)
|
||||
defer img.Dispose()
|
||||
|
||||
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||
s := NewShader(&ir)
|
||||
us := map[int]interface{}{
|
||||
0: []float32{1, 1},
|
||||
}
|
||||
img.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, s, us)
|
||||
|
||||
// Dispose the shader. This should invalidates (= being stale) all the images using this shader.
|
||||
s.Dispose()
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := RestoreIfNeeded(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := color.RGBA{0xff, 0, 0, 0xff}
|
||||
got := pixelsToColor(img.BasePixelsForTesting(), 0, 0)
|
||||
if !sameColors(got, want, 1) {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user