internal/graphicsdriver/directx: bug fix: too many constant buffers could be allocated

Closes #2204
This commit is contained in:
Hajime Hoshi 2022-07-15 03:40:22 +09:00
parent d4beacf27e
commit 4d93e6248d
2 changed files with 56 additions and 9 deletions

View File

@ -2889,3 +2889,47 @@ func TestImageNewImageFromEbitenImage(t *testing.T) {
}
}
}
// Issue #2204
func TestImageTooManyConstantBuffersInDirectX(t *testing.T) {
src := ebiten.NewImage(3, 3)
src.Fill(color.White)
src = src.SubImage(image.Rect(1, 1, 2, 2)).(*ebiten.Image)
vs := []ebiten.Vertex{
{
DstX: 0, DstY: 0, SrcX: 1, SrcY: 1,
ColorR: 1, ColorG: 1, ColorB: 1, ColorA: 1,
},
{
DstX: 16, DstY: 0, SrcX: 1, SrcY: 1,
ColorR: 1, ColorG: 1, ColorB: 1, ColorA: 1,
},
{
DstX: 0, DstY: 16, SrcX: 1, SrcY: 1,
ColorR: 1, ColorG: 1, ColorB: 1, ColorA: 1,
},
{
DstX: 16, DstY: 16, SrcX: 1, SrcY: 1,
ColorR: 1, ColorG: 1, ColorB: 1, ColorA: 1,
},
}
is := []uint16{0, 1, 2, 1, 2, 3}
dst0 := ebiten.NewImage(16, 16)
dst1 := ebiten.NewImage(16, 16)
op := &ebiten.DrawTrianglesOptions{
FillRule: ebiten.EvenOdd,
}
for i := 0; i < 100; i++ {
dst0.DrawTriangles(vs, is, src, op)
dst1.DrawTriangles(vs, is, src, op)
}
if got, want := dst0.At(0, 0), (color.RGBA{0xff, 0xff, 0xff, 0xff}); got != want {
t.Errorf("got: %v, want: %v", got, want)
}
if got, want := dst1.At(0, 0), (color.RGBA{0xff, 0xff, 0xff, 0xff}); got != want {
t.Errorf("got: %v, want: %v", got, want)
}
}

View File

@ -970,6 +970,18 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.Sh
return err
}
// Release constant buffers when too many ones were created.
numPipelines := 1
if evenOdd {
numPipelines = 2
}
if len(g.pipelineStates.constantBuffers[g.frameIndex])+numPipelines > numDescriptorsPerFrame {
if err := g.flushCommandList(g.drawCommandList); err != nil {
return err
}
g.pipelineStates.releaseConstantBuffers(g.frameIndex)
}
dst := g.images[dstID]
var shader *Shader
@ -1175,15 +1187,6 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.Sh
}
}
// Release constant buffers when too many ones were created.
// This is needed espciallly for testings, where present is always false.
if len(g.pipelineStates.constantBuffers[g.frameIndex]) >= 16 {
if err := g.flushCommandList(g.drawCommandList); err != nil {
return err
}
g.pipelineStates.releaseConstantBuffers(g.frameIndex)
}
return nil
}