Files
sanspie a6822156cd
ci-platforms / windows amd64 smoke (push) Skipped
ci / release (push) Successful in 8m58s
ci-platforms / darwin amd64 smoke (push) Skipped
ci-platforms / darwin arm64 smoke (push) Skipped
ci / checks (push) Successful in 4m46s
ci / build (amd64, linux, ubuntu-24.04) (push) Successful in 13m28s
Finish Stage 12 editor fixes and refreshed platformer
2026-11-05 17:36:42 +03:00

56 lines
1.5 KiB
Go

// Package bufferdiff bounds comparisons of small dynamic GPU writes.
// A change in offset or length makes the next upload independent.
package bufferdiff
import "bytes"
const maximum = 16 << 10
type LastWrite struct {
at int
data []byte
}
// ReserveSmall reserves backing for a known small buffer without suppressing its first full write; larger, partially used buffers acquire bounded comparison storage from actual writes.
func (w *LastWrite) ReserveSmall(size int) {
const limit = 1024
if size > 0 && size <= limit && cap(w.data) < size {
w.data = make([]byte, 0, size)
}
}
func (w *LastWrite) Reset() { w.data = w.data[:0] }
func (w *LastWrite) Delta(at int, data []byte) (int, []byte) {
if len(data) > maximum {
w.Reset()
return at, data
}
if len(w.data) != len(data) || w.at != at {
w.at = at
w.data = append(w.data[:0], data...)
return at, data
}
if bytes.Equal(w.data, data) {
return at, nil
}
// Keep one contiguous GL command. Comparing coarse blocks avoids running
// a byte-wise WASM loop over a long unchanged sprite or vertex prefix.
const block = 32
start, end := 0, len(data)
for end-start >= block && bytes.Equal(w.data[start:start+block], data[start:start+block]) {
start += block
}
for end-start >= block && bytes.Equal(w.data[end-block:end], data[end-block:end]) {
end -= block
}
for start < end && w.data[start] == data[start] {
start++
}
for start < end && w.data[end-1] == data[end-1] {
end--
}
copy(w.data[start:end], data[start:end])
return at + start, data[start:end]
}