gpu,app,internal/glimpl: update GL backend for the compute renderer

Modern graphics APIs have immutable objects, with mutable data. For example,
a texture's dimensions are immutable, while the texture contents is not.
Change the GPU API abstraction to match.

Clearing a Texture is convenient to do with a plain []byte. Generalize
Texture.Upload to take a plain byte slice and introduce a helper function for
uploading *image.RGBA data.

Add TextureFormatRGBA8 a format for the linear RGB colorspace.

Add OpenGL ES 3.1 functions for compute programs.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2020-12-30 16:48:22 +01:00
parent 7d24b790a2
commit bfe2d04c60
11 changed files with 400 additions and 89 deletions
+22 -2
View File
@@ -8,19 +8,24 @@ type (
)
const (
ALL_BARRIER_BITS = 0xffffffff
ARRAY_BUFFER = 0x8892
BLEND = 0xbe2
CLAMP_TO_EDGE = 0x812f
COLOR_ATTACHMENT0 = 0x8ce0
COLOR_BUFFER_BIT = 0x4000
COMPILE_STATUS = 0x8b81
COMPUTE_SHADER = 0x91B9
DEPTH_BUFFER_BIT = 0x100
DEPTH_ATTACHMENT = 0x8d00
DEPTH_COMPONENT16 = 0x81a5
DEPTH_COMPONENT24 = 0x81A6
DEPTH_COMPONENT32F = 0x8CAC
DEPTH_TEST = 0xb71
DRAW_FRAMEBUFFER = 0x8CA9
DST_COLOR = 0x306
DYNAMIC_DRAW = 0x88E8
DYNAMIC_READ = 0x88E9
ELEMENT_ARRAY_BUFFER = 0x8893
EXTENSIONS = 0x1f03
FALSE = 0
@@ -39,6 +44,7 @@ const (
LINEAR = 0x2601
LINK_STATUS = 0x8b82
LUMINANCE = 0x1909
MAP_READ_BIT = 0x0001
MAX_TEXTURE_SIZE = 0xd33
NEAREST = 0x2600
NO_ERROR = 0x0
@@ -50,6 +56,8 @@ const (
R16F = 0x822d
R8 = 0x8229
READ_FRAMEBUFFER = 0x8ca8
READ_ONLY = 0x88B8
READ_WRITE = 0x88BA
RED = 0x1903
RENDERER = 0x1F01
RENDERBUFFER = 0x8d41
@@ -59,12 +67,14 @@ const (
RGB = 0x1907
RGBA = 0x1908
RGBA8 = 0x8058
SHADER_STORAGE_BUFFER = 0x90D2
SHORT = 0x1402
SRGB = 0x8c40
SRGB_ALPHA_EXT = 0x8c42
SRGB8 = 0x8c41
SRGB8_ALPHA8 = 0x8c43
STATIC_DRAW = 0x88e4
STENCIL_BUFFER_BIT = 0x00000400
TEXTURE_2D = 0xde1
TEXTURE_MAG_FILTER = 0x2800
TEXTURE_MIN_FILTER = 0x2801
@@ -81,6 +91,7 @@ const (
UNSIGNED_SHORT = 0x1403
VERSION = 0x1f02
VERTEX_SHADER = 0x8b31
WRITE_ONLY = 0x88B9
ZERO = 0x0
// EXT_disjoint_timer_query
@@ -96,11 +107,14 @@ var _ interface {
BindBuffer(target Enum, b Buffer)
BindBufferBase(target Enum, index int, buffer Buffer)
BindFramebuffer(target Enum, fb Framebuffer)
BindImageTexture(unit int, t Texture, level int, layered bool, layer int, access, format Enum)
BindRenderbuffer(target Enum, fb Renderbuffer)
BindTexture(target Enum, t Texture)
BlendEquation(mode Enum)
BlendFunc(sfactor, dfactor Enum)
BufferData(target Enum, src []byte, usage Enum)
BlitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1 int, mask Enum, filter Enum)
BufferData(target Enum, size int, usage Enum)
BufferSubData(target Enum, offset int, src []byte)
CheckFramebufferStatus(target Enum) Enum
Clear(mask Enum)
ClearColor(red, green, blue, alpha float32)
@@ -124,6 +138,7 @@ var _ interface {
DepthMask(mask bool)
DisableVertexAttribArray(a Attrib)
Disable(cap Enum)
DispatchCompute(x, y, z int)
DrawArrays(mode Enum, first, count int)
DrawElements(mode Enum, count int, ty Enum, offset int)
Enable(cap Enum)
@@ -144,11 +159,15 @@ var _ interface {
GetUniformLocation(p Program, name string) Uniform
InvalidateFramebuffer(target, attachment Enum)
LinkProgram(p Program)
MapBufferRange(target Enum, offset, length int, access Enum) []byte
MemoryBarrier(barriers Enum)
ReadPixels(x, y, width, height int, format, ty Enum, data []byte)
RenderbufferStorage(target, internalformat Enum, width, height int)
ShaderSource(s Shader, src string)
TexImage2D(target Enum, level int, internalFormat int, width, height int, format, ty Enum, data []byte)
TexImage2D(target Enum, level int, internalFormat Enum, width, height int, format, ty Enum)
TexParameteri(target, pname Enum, param int)
TexStorage2D(target Enum, levels int, internalFormat Enum, width, height int)
TexSubImage2D(target Enum, level, xoff, yoff int, width, height int, format, ty Enum, data []byte)
UniformBlockBinding(p Program, uniformBlockIndex uint, uniformBlockBinding uint)
Uniform1f(dst Uniform, v float32)
Uniform1i(dst Uniform, v int)
@@ -156,6 +175,7 @@ var _ interface {
Uniform3f(dst Uniform, v0, v1, v2 float32)
Uniform4f(dst Uniform, v0, v1, v2, v3 float32)
UseProgram(p Program)
UnmapBuffer(target Enum) bool
VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int)
Viewport(x, y, width, height int)
} = (*Functions)(nil)
+93 -8
View File
@@ -51,6 +51,13 @@ static void (*_glEndQuery)(GLenum target);
static void (*_glGenQueries)(GLsizei n, GLuint *ids);
static void (*_glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params);
static const GLubyte* (*_glGetStringi)(GLenum name, GLuint index);
static void (*_glMemoryBarrier)(GLbitfield barriers);
static void (*_glDispatchCompute)(GLuint x, GLuint y, GLuint z);
static void* (*_glMapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
static GLboolean (*_glUnmapBuffer)(GLenum target);
static void (*_glBindImageTexture)(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
static void (*_glTexStorage2D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
static void (*_glBlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
// The pointer-free version of glVertexAttribPointer, to avoid the Cgo pointer checks.
__attribute__ ((visibility ("hidden"))) void gio_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, uintptr_t offset) {
@@ -108,6 +115,34 @@ __attribute__ ((visibility ("hidden"))) void gio_glGetQueryObjectuiv(GLuint id,
_glGetQueryObjectuiv(id, pname, params);
}
__attribute__ ((visibility ("hidden"))) void gio_glMemoryBarrier(GLbitfield barriers) {
_glMemoryBarrier(barriers);
}
__attribute__ ((visibility ("hidden"))) void gio_glDispatchCompute(GLuint x, GLuint y, GLuint z) {
_glDispatchCompute(x, y, z);
}
__attribute__ ((visibility ("hidden"))) void *gio_glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
return _glMapBufferRange(target, offset, length, access);
}
__attribute__ ((visibility ("hidden"))) GLboolean gio_glUnmapBuffer(GLenum target) {
return _glUnmapBuffer(target);
}
__attribute__ ((visibility ("hidden"))) void gio_glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) {
_glBindImageTexture(unit, texture, level, layered, layer, access, format);
}
__attribute__ ((visibility ("hidden"))) void gio_glTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height) {
_glTexStorage2D(target, levels, internalFormat, width, height);
}
__attribute__ ((visibility ("hidden"))) void gio_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
_glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
__attribute__((constructor)) static void gio_loadGLFunctions() {
#ifdef __APPLE__
#if TARGET_OS_IPHONE
@@ -122,6 +157,7 @@ __attribute__((constructor)) static void gio_loadGLFunctions() {
_glGetUniformBlockIndex = glGetUniformBlockIndex;
_glUniformBlockBinding = glUniformBlockBinding;
_glGetStringi = glGetStringi;
_glTexStorage2D = glTexStorage2D;
#else
// Load libGLESv3 if available.
dlopen("libGLESv3.so", RTLD_NOW | RTLD_GLOBAL);
@@ -150,6 +186,14 @@ __attribute__((constructor)) static void gio_loadGLFunctions() {
_glGetQueryObjectuiv = dlsym(RTLD_DEFAULT, "glGetQueryObjectuiv");
if (_glGetQueryObjectuiv == NULL)
_glGetQueryObjectuiv = dlsym(RTLD_DEFAULT, "glGetQueryObjectuivEXT");
_glMemoryBarrier = dlsym(RTLD_DEFAULT, "glMemoryBarrier");
_glDispatchCompute = dlsym(RTLD_DEFAULT, "glDispatchCompute");
_glMapBufferRange = dlsym(RTLD_DEFAULT, "glMapBufferRange");
_glUnmapBuffer = dlsym(RTLD_DEFAULT, "glUnmapBuffer");
_glBindImageTexture = dlsym(RTLD_DEFAULT, "glBindImageTexture");
_glTexStorage2D = dlsym(RTLD_DEFAULT, "glTexStorage2D");
_glBlitFramebuffer = dlsym(RTLD_DEFAULT, "glBlitFramebuffer");
#endif
}
*/
@@ -204,6 +248,14 @@ func (f *Functions) BindRenderbuffer(target Enum, fb Renderbuffer) {
C.glBindRenderbuffer(C.GLenum(target), C.GLuint(fb.V))
}
func (f *Functions) BindImageTexture(unit int, t Texture, level int, layered bool, layer int, access, format Enum) {
l := C.GLboolean(C.GL_FALSE)
if layered {
l = C.GL_TRUE
}
C.gio_glBindImageTexture(C.GLuint(unit), C.GLuint(t.V), C.GLint(level), l, C.GLint(layer), C.GLenum(access), C.GLenum(format))
}
func (f *Functions) BindTexture(target Enum, t Texture) {
C.glBindTexture(C.GLenum(target), C.GLuint(t.V))
}
@@ -216,12 +268,24 @@ func (f *Functions) BlendFunc(sfactor, dfactor Enum) {
C.glBlendFunc(C.GLenum(sfactor), C.GLenum(dfactor))
}
func (f *Functions) BufferData(target Enum, src []byte, usage Enum) {
func (f *Functions) BlitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1 int, mask Enum, filter Enum) {
C.gio_glBlitFramebuffer(
C.GLint(sx0), C.GLint(sy0), C.GLint(sx1), C.GLint(sy1),
C.GLint(dx0), C.GLint(dy0), C.GLint(dx1), C.GLint(dy1),
C.GLenum(mask), C.GLenum(filter),
)
}
func (f *Functions) BufferData(target Enum, size int, usage Enum) {
C.glBufferData(C.GLenum(target), C.GLsizeiptr(size), nil, C.GLenum(usage))
}
func (f *Functions) BufferSubData(target Enum, offset int, src []byte) {
var p unsafe.Pointer
if len(src) > 0 {
p = unsafe.Pointer(&src[0])
}
C.glBufferData(C.GLenum(target), C.GLsizeiptr(len(src)), p, C.GLenum(usage))
C.glBufferSubData(C.GLenum(target), C.GLintptr(offset), C.GLsizeiptr(len(src)), p)
}
func (f *Functions) CheckFramebufferStatus(target Enum) Enum {
@@ -338,6 +402,10 @@ func (f *Functions) DrawElements(mode Enum, count int, ty Enum, offset int) {
C.gio_glDrawElements(C.GLenum(mode), C.GLsizei(count), C.GLenum(ty), C.uintptr_t(offset))
}
func (f *Functions) DispatchCompute(x, y, z int) {
C.gio_glDispatchCompute(C.GLuint(x), C.GLuint(y), C.GLuint(z))
}
func (f *Functions) Enable(cap Enum) {
C.glEnable(C.GLenum(cap))
}
@@ -464,6 +532,18 @@ func (f *Functions) PixelStorei(pname Enum, param int32) {
C.glPixelStorei(C.GLenum(pname), C.GLint(param))
}
func (f *Functions) MemoryBarrier(barriers Enum) {
C.gio_glMemoryBarrier(C.GLbitfield(barriers))
}
func (f *Functions) MapBufferRange(target Enum, offset, length int, access Enum) []byte {
p := C.gio_glMapBufferRange(C.GLenum(target), C.GLintptr(offset), C.GLsizeiptr(length), C.GLbitfield(access))
if p == nil {
return nil
}
return (*([1 << 30]byte))(p)[:length:length]
}
func (f *Functions) Scissor(x, y, width, height int32) {
C.glScissor(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
}
@@ -487,12 +567,12 @@ func (f *Functions) ShaderSource(s Shader, src string) {
C.glShaderSource(C.GLuint(s.V), 1, &csrc, &strlen)
}
func (f *Functions) TexImage2D(target Enum, level int, internalFormat int, width int, height int, format Enum, ty Enum, data []byte) {
var p unsafe.Pointer
if len(data) > 0 {
p = unsafe.Pointer(&data[0])
}
C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GLint(internalFormat), C.GLsizei(width), C.GLsizei(height), 0, C.GLenum(format), C.GLenum(ty), p)
func (f *Functions) TexImage2D(target Enum, level int, internalFormat Enum, width int, height int, format Enum, ty Enum) {
C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GLint(internalFormat), C.GLsizei(width), C.GLsizei(height), 0, C.GLenum(format), C.GLenum(ty), nil)
}
func (f *Functions) TexStorage2D(target Enum, levels int, internalFormat Enum, width, height int) {
C.gio_glTexStorage2D(C.GLenum(target), C.GLsizei(levels), C.GLenum(internalFormat), C.GLsizei(width), C.GLsizei(height))
}
func (f *Functions) TexSubImage2D(target Enum, level int, x int, y int, width int, height int, format Enum, ty Enum, data []byte) {
@@ -535,6 +615,11 @@ func (f *Functions) UseProgram(p Program) {
C.glUseProgram(C.GLuint(p.V))
}
func (f *Functions) UnmapBuffer(target Enum) bool {
r := C.gio_glUnmapBuffer(C.GLenum(target))
return r == C.GL_TRUE
}
func (f *Functions) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride int, offset int) {
var n C.GLboolean = C.GL_FALSE
if normalized {
+31 -13
View File
@@ -27,6 +27,7 @@ var (
_glBlendEquation = LibGLESv2.NewProc("glBlendEquation")
_glBlendFunc = LibGLESv2.NewProc("glBlendFunc")
_glBufferData = LibGLESv2.NewProc("glBufferData")
_glBufferSubData = LibGLESv2.NewProc("glBufferSubData")
_glCheckFramebufferStatus = LibGLESv2.NewProc("glCheckFramebufferStatus")
_glClear = LibGLESv2.NewProc("glClear")
_glClearColor = LibGLESv2.NewProc("glClearColor")
@@ -78,6 +79,7 @@ var (
_glScissor = LibGLESv2.NewProc("glScissor")
_glShaderSource = LibGLESv2.NewProc("glShaderSource")
_glTexImage2D = LibGLESv2.NewProc("glTexImage2D")
_glTexStorage2D = LibGLESv2.NewProc("glTexStorage2D")
_glTexSubImage2D = LibGLESv2.NewProc("glTexSubImage2D")
_glTexParameteri = LibGLESv2.NewProc("glTexParameteri")
_glUniformBlockBinding = LibGLESv2.NewProc("glUniformBlockBinding")
@@ -132,6 +134,9 @@ func (c *Functions) BindFramebuffer(target Enum, fb Framebuffer) {
func (c *Functions) BindRenderbuffer(target Enum, rb Renderbuffer) {
syscall.Syscall(_glBindRenderbuffer.Addr(), 2, uintptr(target), uintptr(rb.V), 0)
}
func (f *Functions) BindImageTexture(unit int, t Texture, level int, layered bool, layer int, access, format Enum) {
panic("not implemented")
}
func (c *Functions) BindTexture(target Enum, t Texture) {
syscall.Syscall(_glBindTexture.Addr(), 2, uintptr(target), uintptr(t.V), 0)
}
@@ -141,12 +146,16 @@ func (c *Functions) BlendEquation(mode Enum) {
func (c *Functions) BlendFunc(sfactor, dfactor Enum) {
syscall.Syscall(_glBlendFunc.Addr(), 2, uintptr(sfactor), uintptr(dfactor), 0)
}
func (c *Functions) BufferData(target Enum, src []byte, usage Enum) {
if n := len(src); n == 0 {
syscall.Syscall6(_glBufferData.Addr(), 4, uintptr(target), 0, 0, uintptr(usage), 0, 0)
} else {
func (f *Functions) BlitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1 int, mask Enum, filter Enum) {
panic("not implemented")
}
func (c *Functions) BufferData(target Enum, size int, usage Enum) {
syscall.Syscall6(_glBufferData.Addr(), 4, uintptr(target), uintptr(size), 0, uintptr(usage), 0, 0)
}
func (f *Functions) BufferSubData(target Enum, offset int, src []byte) {
if n := len(src); n > 0 {
s0 := &src[0]
syscall.Syscall6(_glBufferData.Addr(), 4, uintptr(target), uintptr(n), uintptr(unsafe.Pointer(s0)), uintptr(usage), 0, 0)
syscall.Syscall6(_glBufferSubData.Addr(), 4, uintptr(target), uintptr(offset), uintptr(n), uintptr(unsafe.Pointer(s0)), 0, 0)
issue34474KeepAlive(s0)
}
}
@@ -242,6 +251,9 @@ func (c *Functions) DrawArrays(mode Enum, first, count int) {
func (c *Functions) DrawElements(mode Enum, count int, ty Enum, offset int) {
syscall.Syscall6(_glDrawElements.Addr(), 4, uintptr(mode), uintptr(count), uintptr(ty), uintptr(offset), 0, 0)
}
func (f *Functions) DispatchCompute(x, y, z int) {
panic("not implemented")
}
func (c *Functions) Enable(cap Enum) {
syscall.Syscall(_glEnable.Addr(), 1, uintptr(cap), 0, 0)
}
@@ -335,6 +347,12 @@ func (c *Functions) LinkProgram(p Program) {
func (c *Functions) PixelStorei(pname Enum, param int32) {
syscall.Syscall(_glPixelStorei.Addr(), 2, uintptr(pname), uintptr(param), 0)
}
func (f *Functions) MemoryBarrier(barriers Enum) {
panic("not implemented")
}
func (f *Functions) MapBufferRange(target Enum, offset, length int, access Enum) []byte {
panic("not implemented")
}
func (f *Functions) ReadPixels(x, y, width, height int, format, ty Enum, data []byte) {
d0 := &data[0]
syscall.Syscall9(_glReadPixels.Addr(), 7, uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(d0)), 0, 0)
@@ -352,14 +370,11 @@ func (c *Functions) ShaderSource(s Shader, src string) {
syscall.Syscall6(_glShaderSource.Addr(), 4, uintptr(s.V), 1, uintptr(unsafe.Pointer(psrc)), uintptr(unsafe.Pointer(&n)), 0, 0)
issue34474KeepAlive(psrc)
}
func (c *Functions) TexImage2D(target Enum, level int, internalFormat int, width, height int, format, ty Enum, data []byte) {
if len(data) == 0 {
syscall.Syscall9(_glTexImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(internalFormat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(ty), 0)
} else {
d0 := &data[0]
syscall.Syscall9(_glTexImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(internalFormat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(d0)))
issue34474KeepAlive(d0)
}
func (f *Functions) TexImage2D(target Enum, level int, internalFormat Enum, width int, height int, format Enum, ty Enum) {
syscall.Syscall9(_glTexImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(internalFormat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(ty), 0)
}
func (f *Functions) TexStorage2D(target Enum, levels int, internalFormat Enum, width, height int) {
syscall.Syscall6(_glTexStorage2D.Addr(), 5, uintptr(target), uintptr(levels), uintptr(internalFormat), uintptr(width), uintptr(height), 0)
}
func (c *Functions) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) {
d0 := &data[0]
@@ -390,6 +405,9 @@ func (c *Functions) Uniform4f(dst Uniform, v0, v1, v2, v3 float32) {
func (c *Functions) UseProgram(p Program) {
syscall.Syscall(_glUseProgram.Addr(), 1, uintptr(p.V), 0, 0)
}
func (f *Functions) UnmapBuffer(target Enum) bool {
panic("not implemented")
}
func (c *Functions) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) {
var norm uintptr
if normalized {
+20
View File
@@ -37,6 +37,26 @@ func CreateProgram(ctx *Functions, vsSrc, fsSrc string, attribs []string) (Progr
return prog, nil
}
func CreateComputeProgram(ctx *Functions, src string) (Program, error) {
cs, err := createShader(ctx, COMPUTE_SHADER, src)
if err != nil {
return Program{}, err
}
defer ctx.DeleteShader(cs)
prog := ctx.CreateProgram()
if !prog.Valid() {
return Program{}, errors.New("glCreateProgram failed")
}
ctx.AttachShader(prog, cs)
ctx.LinkProgram(prog)
if ctx.GetProgrami(prog, LINK_STATUS) == 0 {
log := ctx.GetProgramInfoLog(prog)
ctx.DeleteProgram(prog)
return Program{}, fmt.Errorf("program link failed: %s", strings.TrimSpace(log))
}
return prog, nil
}
func createShader(ctx *Functions, typ Enum, src string) (Shader, error) {
sh := ctx.CreateShader(typ)
if !sh.Valid() {