gpu/internal,internal/gl: add support for strided texture uploads

The CPU fallback of the compute renderer needs to upload subtextures
from a larger image.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-07-19 19:01:51 +02:00
parent abfbeb87cc
commit 60a47e7de5
8 changed files with 41 additions and 27 deletions
+2 -2
View File
@@ -557,9 +557,9 @@ restart:
size := img.Bounds().Size()
driver.UploadImage(a.tex, pos, img)
rightPadding := image.Pt(padding, size.Y)
a.tex.Upload(image.Pt(pos.X+size.X, pos.Y), rightPadding, g.zeros(rightPadding.X*rightPadding.Y*4))
a.tex.Upload(image.Pt(pos.X+size.X, pos.Y), rightPadding, g.zeros(rightPadding.X*rightPadding.Y*4), 0)
bottomPadding := image.Pt(size.X, padding)
a.tex.Upload(image.Pt(pos.X, pos.Y+size.Y), bottomPadding, g.zeros(bottomPadding.X*bottomPadding.Y*4))
a.tex.Upload(image.Pt(pos.X, pos.Y+size.Y), bottomPadding, g.zeros(bottomPadding.X*bottomPadding.Y*4), 0)
}
return nil
}
+4 -2
View File
@@ -556,8 +556,10 @@ func (b *Backend) DispatchCompute(x, y, z int) {
panic("not implemented")
}
func (t *Texture) Upload(offset, size image.Point, pixels []byte) {
stride := size.X * 4
func (t *Texture) Upload(offset, size image.Point, pixels []byte, stride int) {
if stride == 0 {
stride = size.X * 4
}
dst := &d3d11.BOX{
Left: uint32(offset.X),
Top: uint32(offset.Y),
+2 -5
View File
@@ -167,7 +167,7 @@ type Timer interface {
}
type Texture interface {
Upload(offset, size image.Point, pixels []byte)
Upload(offset, size image.Point, pixels []byte, stride int)
Release()
}
@@ -261,11 +261,8 @@ func flipImageY(stride, height int, pixels []byte) {
func UploadImage(t Texture, offset image.Point, img *image.RGBA) {
var pixels []byte
size := img.Bounds().Size()
if img.Stride != size.X*4 {
panic("unsupported stride")
}
start := img.PixOffset(0, 0)
end := img.PixOffset(size.X, size.Y-1)
pixels = img.Pix[start:end]
t.Upload(offset, size, pixels)
t.Upload(offset, size, pixels, img.Stride)
}
+29 -15
View File
@@ -75,10 +75,11 @@ type glState struct {
srcRGB, dstRGB gl.Enum
srcA, dstA gl.Enum
}
depthTest bool
clearColor [4]float32
clearDepth float32
viewport [4]int
depthTest bool
clearColor [4]float32
clearDepth float32
viewport [4]int
unpack_row_length int
}
type state struct {
@@ -270,16 +271,17 @@ func (b *Backend) EndFrame() {
func (b *Backend) queryState() glState {
s := glState{
prog: gl.Program(b.funcs.GetBinding(gl.CURRENT_PROGRAM)),
arrayBuf: gl.Buffer(b.funcs.GetBinding(gl.ARRAY_BUFFER_BINDING)),
elemBuf: gl.Buffer(b.funcs.GetBinding(gl.ELEMENT_ARRAY_BUFFER_BINDING)),
drawFBO: gl.Framebuffer(b.funcs.GetBinding(gl.FRAMEBUFFER_BINDING)),
depthMask: b.funcs.GetInteger(gl.DEPTH_WRITEMASK) != gl.FALSE,
depthTest: b.funcs.IsEnabled(gl.DEPTH_TEST),
depthFunc: gl.Enum(b.funcs.GetInteger(gl.DEPTH_FUNC)),
clearDepth: b.funcs.GetFloat(gl.DEPTH_CLEAR_VALUE),
clearColor: b.funcs.GetFloat4(gl.COLOR_CLEAR_VALUE),
viewport: b.funcs.GetInteger4(gl.VIEWPORT),
prog: gl.Program(b.funcs.GetBinding(gl.CURRENT_PROGRAM)),
arrayBuf: gl.Buffer(b.funcs.GetBinding(gl.ARRAY_BUFFER_BINDING)),
elemBuf: gl.Buffer(b.funcs.GetBinding(gl.ELEMENT_ARRAY_BUFFER_BINDING)),
drawFBO: gl.Framebuffer(b.funcs.GetBinding(gl.FRAMEBUFFER_BINDING)),
depthMask: b.funcs.GetInteger(gl.DEPTH_WRITEMASK) != gl.FALSE,
depthTest: b.funcs.IsEnabled(gl.DEPTH_TEST),
depthFunc: gl.Enum(b.funcs.GetInteger(gl.DEPTH_FUNC)),
clearDepth: b.funcs.GetFloat(gl.DEPTH_CLEAR_VALUE),
clearColor: b.funcs.GetFloat4(gl.COLOR_CLEAR_VALUE),
viewport: b.funcs.GetInteger4(gl.VIEWPORT),
unpack_row_length: b.funcs.GetInteger(gl.UNPACK_ROW_LENGTH),
}
s.blend.enable = b.funcs.IsEnabled(gl.BLEND)
s.blend.srcRGB = gl.Enum(b.funcs.GetInteger(gl.BLEND_SRC_RGB))
@@ -358,6 +360,7 @@ func (b *Backend) restoreState(dst glState) {
src.bindBuffer(f, gl.ARRAY_BUFFER, dst.arrayBuf)
v := dst.viewport
src.setViewport(f, v[0], v[1], v[2], v[3])
src.pixelStorei(f, gl.UNPACK_ROW_LENGTH, dst.unpack_row_length)
}
func (s *glState) setVertexAttribArray(f *gl.Functions, idx int, enabled bool) {
@@ -559,6 +562,16 @@ func (s *glState) bindBuffer(f *gl.Functions, target gl.Enum, buf gl.Buffer) {
f.BindBuffer(target, buf)
}
func (s *glState) pixelStorei(f *gl.Functions, pname gl.Enum, val int) {
if pname != gl.UNPACK_ROW_LENGTH {
panic("unsupported PixelStorei pname")
}
if val != s.unpack_row_length {
f.PixelStorei(pname, val)
s.unpack_row_length = val
}
}
func (s *glState) setClearDepth(f *gl.Functions, d float32) {
if d != s.clearDepth {
f.ClearDepthf(d)
@@ -1250,11 +1263,12 @@ func (t *gpuTexture) Release() {
t.backend.glstate.deleteTexture(t.backend.funcs, t.obj)
}
func (t *gpuTexture) Upload(offset, size image.Point, pixels []byte) {
func (t *gpuTexture) Upload(offset, size image.Point, pixels []byte, stride int) {
if min := size.X * size.Y * 4; min > len(pixels) {
panic(fmt.Errorf("size %d larger than data %d", min, len(pixels)))
}
t.backend.BindTexture(0, t)
t.backend.glstate.pixelStorei(t.backend.funcs, gl.UNPACK_ROW_LENGTH, stride/4)
t.backend.funcs.TexSubImage2D(gl.TEXTURE_2D, 0, offset.X, offset.Y, size.X, size.Y, t.triple.format, t.triple.typ, pixels)
}
+1
View File
@@ -106,6 +106,7 @@ const (
UNIFORM_BUFFER = 0x8A11
UNIFORM_BUFFER_BINDING = 0x8A28
UNPACK_ALIGNMENT = 0xcf5
UNPACK_ROW_LENGTH = 0x0CF2
UNSIGNED_BYTE = 0x1401
UNSIGNED_SHORT = 0x1403
VIEWPORT = 0x0BA2
+1 -1
View File
@@ -343,7 +343,7 @@ func (f *Functions) IsEnabled(cap Enum) bool {
func (f *Functions) LinkProgram(p Program) {
f.Ctx.Call("linkProgram", js.Value(p))
}
func (f *Functions) PixelStorei(pname Enum, param int32) {
func (f *Functions) PixelStorei(pname Enum, param int) {
f.Ctx.Call("pixelStorei", int(pname), param)
}
func (f *Functions) MemoryBarrier(barriers Enum) {
+1 -1
View File
@@ -1101,7 +1101,7 @@ func (f *Functions) LinkProgram(p Program) {
C.glLinkProgram(&f.f, C.GLuint(p.V))
}
func (f *Functions) PixelStorei(pname Enum, param int32) {
func (f *Functions) PixelStorei(pname Enum, param int) {
C.glPixelStorei(&f.f, C.GLenum(pname), C.GLint(param))
}
+1 -1
View File
@@ -409,7 +409,7 @@ func (f *Functions) IsEnabled(cap Enum) bool {
func (c *Functions) LinkProgram(p Program) {
syscall.Syscall(_glLinkProgram.Addr(), 1, uintptr(p.V), 0, 0)
}
func (c *Functions) PixelStorei(pname Enum, param int32) {
func (c *Functions) PixelStorei(pname Enum, param int) {
syscall.Syscall(_glPixelStorei.Addr(), 2, uintptr(pname), uintptr(param), 0)
}
func (f *Functions) MemoryBarrier(barriers Enum) {