internal/graphics: reland: change the definition of MaxVerticesCount

Updates #2612
This commit is contained in:
Hajime Hoshi 2023-11-04 14:08:46 +09:00
parent 3a632be0c7
commit 1f95c98969
4 changed files with 16 additions and 80 deletions

View File

@ -438,9 +438,6 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
if int(idx) >= len(vertices) { if int(idx) >= len(vertices) {
panic(fmt.Sprintf("ebiten: indices[%d] must be less than len(vertices) (%d) but was %d", i, len(vertices), idx)) panic(fmt.Sprintf("ebiten: indices[%d] must be less than len(vertices) (%d) but was %d", i, len(vertices), idx))
} }
if idx >= MaxVerticesCount {
panic(fmt.Sprintf("ebiten: indices[%d] must be less than MaxVerticesCount %d but was %d", i, MaxVerticesCount, idx))
}
} }
if options == nil { if options == nil {
@ -603,9 +600,6 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
if int(idx) >= len(vertices) { if int(idx) >= len(vertices) {
panic(fmt.Sprintf("ebiten: indices[%d] must be less than len(vertices) (%d) but was %d", i, len(vertices), idx)) panic(fmt.Sprintf("ebiten: indices[%d] must be less than len(vertices) (%d) but was %d", i, len(vertices), idx))
} }
if idx >= MaxVerticesCount {
panic(fmt.Sprintf("ebiten: indices[%d] must be less than MaxVerticesCount %d but was %d", i, MaxVerticesCount, idx))
}
} }
if options == nil { if options == nil {

View File

@ -2805,7 +2805,7 @@ func BenchmarkColorMScale(b *testing.B) {
} }
} }
func TestIndicesOverflow(t *testing.T) { func TestImageMoreIndicesThanMaxUint16(t *testing.T) {
const ( const (
w = 16 w = 16
h = 16 h = 16
@ -2817,10 +2817,10 @@ func TestIndicesOverflow(t *testing.T) {
op := &ebiten.DrawTrianglesOptions{} op := &ebiten.DrawTrianglesOptions{}
vs := make([]ebiten.Vertex, 3) vs := make([]ebiten.Vertex, 3)
is := make([]uint16, graphics.MaxVerticesCount/3*3) is := make([]uint16, 65538)
dst.DrawTriangles(vs, is, src, op) dst.DrawTriangles(vs, is, src, op)
// Cause an overflow for indices. // The next draw call should work well (and this is likely batched).
vs = []ebiten.Vertex{ vs = []ebiten.Vertex{
{ {
DstX: 0, DstX: 0,
@ -2877,7 +2877,7 @@ func TestIndicesOverflow(t *testing.T) {
} }
} }
func TestVerticesOverflow(t *testing.T) { func TestImageMoreVerticesThanMaxUint16(t *testing.T) {
const ( const (
w = 16 w = 16
h = 16 h = 16
@ -2888,11 +2888,11 @@ func TestVerticesOverflow(t *testing.T) {
src.Fill(color.White) src.Fill(color.White)
op := &ebiten.DrawTrianglesOptions{} op := &ebiten.DrawTrianglesOptions{}
vs := make([]ebiten.Vertex, graphics.MaxVerticesCount-1) vs := make([]ebiten.Vertex, math.MaxUint16+1)
is := make([]uint16, 3) is := make([]uint16, 3)
dst.DrawTriangles(vs, is, src, op) dst.DrawTriangles(vs, is, src, op)
// Cause an overflow for vertices. // The next draw call should work well (and this is likely batched).
vs = []ebiten.Vertex{ vs = []ebiten.Vertex{
{ {
DstX: 0, DstX: 0,
@ -2949,26 +2949,6 @@ func TestVerticesOverflow(t *testing.T) {
} }
} }
func TestTooManyVertices(t *testing.T) {
const (
w = 16
h = 16
)
dst := ebiten.NewImage(w, h)
src := ebiten.NewImage(w, h)
src.Fill(color.White)
op := &ebiten.DrawTrianglesOptions{}
vs := make([]ebiten.Vertex, graphics.MaxVerticesCount+1)
is := make([]uint16, 3)
dst.DrawTriangles(vs, is, src, op)
// Force to cause flushing the graphics commands.
// Confirm this doesn't freeze.
dst.At(0, 0)
}
func TestImageNewImageFromEbitenImage(t *testing.T) { func TestImageNewImageFromEbitenImage(t *testing.T) {
const ( const (
w = 16 w = 16
@ -4318,48 +4298,6 @@ func TestImageDrawTrianglesShaderWithGreaterIndexThanVerticesCount(t *testing.T)
dst.DrawTrianglesShader(vs, is, shader, nil) dst.DrawTrianglesShader(vs, is, shader, nil)
} }
// Issue #2611
func TestImageDrawTrianglesWithTooBigIndex(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("DrawTriangles must panic but not")
}
}()
const w, h = 16, 16
dst := ebiten.NewImage(w, h)
src := ebiten.NewImage(w, h)
vs := make([]ebiten.Vertex, ebiten.MaxVerticesCount+1)
is := []uint16{0, 1, 2, 1, 2, ebiten.MaxVerticesCount}
dst.DrawTriangles(vs, is, src, nil)
}
// Issue #2611
func TestImageDrawTrianglesShaderWithTooBigIndex(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("DrawTrianglesShader must panic but not")
}
}()
const w, h = 16, 16
dst := ebiten.NewImage(w, h)
vs := make([]ebiten.Vertex, ebiten.MaxVerticesCount+1)
is := []uint16{0, 1, 2, 1, 2, ebiten.MaxVerticesCount}
shader, err := ebiten.NewShader([]byte(`
package main
func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
return color
}
`))
if err != nil {
t.Fatalf("could not compile shader: %v", err)
}
dst.DrawTrianglesShader(vs, is, shader, nil)
}
// Issue #2733 // Issue #2733
func TestImageGeoMAfterDraw(t *testing.T) { func TestImageGeoMAfterDraw(t *testing.T) {
src := ebiten.NewImage(1, 1) src := ebiten.NewImage(1, 1)

View File

@ -45,13 +45,18 @@ const (
const ( const (
VertexFloatCount = 8 VertexFloatCount = 8
is32bit = 1 >> (^uint(0) >> 63)
is64bit = 1 - is32bit
// MaxVerticesCount is the maximum number of vertices for one draw call. // MaxVerticesCount is the maximum number of vertices for one draw call.
// This value is 2^16 - 1 = 65535, as the index type is uint16. //
// This value cannot be exactly 2^16 == 65536 especially with WebGL 2, as 65536th vertex is not rendered correctly. // On 64bit architectures, this value is 2^32-1, as the index type is uint32.
// This value cannot be exactly 2^32 especially with WebGL 2, as 2^32th vertex is not rendered correctly.
// See https://registry.khronos.org/webgl/specs/latest/2.0/#5.18 . // See https://registry.khronos.org/webgl/specs/latest/2.0/#5.18 .
// //
// TODO: Use MaxUint32 and move these values to internal/graphicscommand (#2612) // On 32bit architectures, this value is an adjusted number so that MaxVertexFloatsCount doesn't overflow int.
MaxVerticesCount = math.MaxUint16 MaxVerticesCount = is64bit*math.MaxUint32 + is32bit*(math.MaxInt32/VertexFloatCount)
MaxVertexFloatsCount = MaxVerticesCount * VertexFloatCount MaxVertexFloatsCount = MaxVerticesCount * VertexFloatCount
) )

View File

@ -139,8 +139,7 @@ func (i *Image) WritePixels(pix []byte, region image.Rectangle) {
copy(clr[:], pix) copy(clr[:], pix)
i.dotsBuffer[region.Min] = clr i.dotsBuffer[region.Min] = clr
// One square requires 6 indices (= 2 triangles). if len(i.dotsBuffer) >= 10000 {
if len(i.dotsBuffer) >= graphics.MaxVerticesCount/6 {
i.flushDotsBufferIfNeeded() i.flushDotsBufferIfNeeded()
} }
return return