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
+39 -16
View File
@@ -121,12 +121,7 @@ func NewDevice() (*Device, error) {
_IUnknownRelease(unsafe.Pointer(d3dctx), d3dctx.vtbl.Release) _IUnknownRelease(unsafe.Pointer(d3dctx), d3dctx.vtbl.Release)
return nil, fmt.Errorf("d3d11: feature level too low: %d", featLvl) return nil, fmt.Errorf("d3d11: feature level too low: %d", featLvl)
} }
floatFormat, ok := detectFloatFormat(d3ddev) floatFormat, _ := detectFloatFormat(d3ddev)
if !ok {
_IUnknownRelease(unsafe.Pointer(d3ddev), d3ddev.vtbl.Release)
_IUnknownRelease(unsafe.Pointer(d3dctx), d3dctx.vtbl.Release)
return nil, fmt.Errorf("d3d11: no available floating point formats")
}
dev.floatFormat = floatFormat dev.floatFormat = floatFormat
dev.depthStates = make(map[depthState]*_ID3D11DepthStencilState) dev.depthStates = make(map[depthState]*_ID3D11DepthStencilState)
dev.blendStates = make(map[blendState]*_ID3D11BlendState) dev.blendStates = make(map[blendState]*_ID3D11BlendState)
@@ -253,6 +248,9 @@ func NewBackend(d *Device) (*Backend, error) {
caps := backend.Caps{ caps := backend.Caps{
MaxTextureSize: 2048, // 9.1 maximum MaxTextureSize: 2048, // 9.1 maximum
} }
if d.floatFormat != 0 {
caps.Features |= backend.FeatureFloatRenderTargets
}
switch { switch {
case d.featLvl >= _D3D_FEATURE_LEVEL_11_0: case d.featLvl >= _D3D_FEATURE_LEVEL_11_0:
caps.MaxTextureSize = 16384 caps.MaxTextureSize = 16384
@@ -524,6 +522,10 @@ func (b *Backend) NewImmutableBuffer(typ backend.BufferBinding, data []byte) (ba
return &Buffer{backend: b, buf: buf, bind: bind, immutable: true}, nil return &Buffer{backend: b, buf: buf, bind: bind, immutable: true}, nil
} }
func (b *Backend) NewComputeProgram(shader backend.ShaderSources) (backend.Program, error) {
panic("not implemented")
}
func (b *Backend) NewProgram(vertexShader, fragmentShader backend.ShaderSources) (backend.Program, error) { func (b *Backend) NewProgram(vertexShader, fragmentShader backend.ShaderSources) (backend.Program, error) {
vs, err := b.dev.dev.CreateVertexShader(vertexShader.HLSL) vs, err := b.dev.dev.CreateVertexShader(vertexShader.HLSL)
if err != nil { if err != nil {
@@ -667,17 +669,30 @@ func (b *Backend) BlendFunc(sfactor, dfactor backend.BlendFactor) {
b.blendState.dfactor = dfactor b.blendState.dfactor = dfactor
} }
func (t *Texture) Upload(img *image.RGBA) { func (b *Backend) BindImageTexture(unit int, tex backend.Texture, access backend.AccessBits, f backend.TextureFormat) {
b := img.Bounds() panic("not implemented")
w := b.Dx() }
if img.Stride != w*4 {
panic("unsupported stride") func (b *Backend) MemoryBarrier() {
panic("not implemented")
}
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
dst := &_D3D11_BOX{
left: uint32(offset.X),
top: uint32(offset.Y),
right: uint32(offset.X + size.X),
bottom: uint32(offset.Y + size.Y),
front: 0,
back: 1,
} }
start := (b.Min.X + b.Min.Y*w) * 4
end := (b.Max.X + (b.Max.Y-1)*w) * 4
pixels := img.Pix[start:end]
res := (*_ID3D11Resource)(unsafe.Pointer(t.tex)) res := (*_ID3D11Resource)(unsafe.Pointer(t.tex))
t.backend.dev.ctx.UpdateSubresource(res, uint32(img.Stride), uint32(len(pixels)), pixels) t.backend.dev.ctx.UpdateSubresource(res, dst, uint32(stride), uint32(len(pixels)), pixels)
} }
func (t *Texture) Release() { func (t *Texture) Release() {
@@ -710,6 +725,10 @@ func (p *Program) Release() {
p.frag.shader = nil p.frag.shader = nil
} }
func (p *Program) SetStorageBuffer(binding int, buffer backend.Buffer) {
panic("not implemented")
}
func (p *Program) SetVertexUniforms(buf backend.Buffer) { func (p *Program) SetVertexUniforms(buf backend.Buffer) {
p.vert.uniforms = buf.(*Buffer) p.vert.uniforms = buf.(*Buffer)
} }
@@ -726,8 +745,12 @@ func (b *Backend) BindIndexBuffer(buf backend.Buffer) {
b.dev.ctx.IASetIndexBuffer(buf.(*Buffer).buf, _DXGI_FORMAT_R16_UINT, 0) b.dev.ctx.IASetIndexBuffer(buf.(*Buffer).buf, _DXGI_FORMAT_R16_UINT, 0)
} }
func (b *Buffer) Download(data []byte) error {
panic("not implemented")
}
func (b *Buffer) Upload(data []byte) { func (b *Buffer) Upload(data []byte) {
b.backend.dev.ctx.UpdateSubresource((*_ID3D11Resource)(unsafe.Pointer(b.buf)), 0, 0, data) b.backend.dev.ctx.UpdateSubresource((*_ID3D11Resource)(unsafe.Pointer(b.buf)), nil, 0, 0, data)
} }
func (b *Buffer) Release() { func (b *Buffer) Release() {
+2 -2
View File
@@ -1127,14 +1127,14 @@ func (c *_ID3D11DeviceContext) PSSetShader(s *_ID3D11PixelShader) {
) )
} }
func (c *_ID3D11DeviceContext) UpdateSubresource(res *_ID3D11Resource, rowPitch, depthPitch uint32, data []byte) { func (c *_ID3D11DeviceContext) UpdateSubresource(res *_ID3D11Resource, dstBox *_D3D11_BOX, rowPitch, depthPitch uint32, data []byte) {
syscall.Syscall9( syscall.Syscall9(
c.vtbl.UpdateSubresource, c.vtbl.UpdateSubresource,
7, 7,
uintptr(unsafe.Pointer(c)), uintptr(unsafe.Pointer(c)),
uintptr(unsafe.Pointer(res)), uintptr(unsafe.Pointer(res)),
0, // DstSubresource 0, // DstSubresource
0, // pDstBox uintptr(unsafe.Pointer(dstBox)),
uintptr(unsafe.Pointer(&data[0])), uintptr(unsafe.Pointer(&data[0])),
uintptr(rowPitch), uintptr(rowPitch),
uintptr(depthPitch), uintptr(depthPitch),
+11 -11
View File
@@ -71,14 +71,14 @@ func (s *FBO) Blit() {
s.c.Uniform1i(s.c.GetUniformLocation(prog, "tex"), 0) s.c.Uniform1i(s.c.GetUniformLocation(prog, "tex"), 0)
s.quad = s.c.CreateBuffer() s.quad = s.c.CreateBuffer()
s.c.BindBuffer(glimpl.ARRAY_BUFFER, s.quad) s.c.BindBuffer(glimpl.ARRAY_BUFFER, s.quad)
s.c.BufferData(glimpl.ARRAY_BUFFER, coords := unsafe.BytesView([]float32{
unsafe.BytesView([]float32{ -1, +1, 0, 1,
-1, +1, 0, 1, +1, +1, 1, 1,
+1, +1, 1, 1, -1, -1, 0, 0,
-1, -1, 0, 0, +1, -1, 1, 0,
+1, -1, 1, 0, })
}), s.c.BufferData(glimpl.ARRAY_BUFFER, len(coords), glimpl.STATIC_DRAW)
glimpl.STATIC_DRAW) s.c.BufferSubData(glimpl.ARRAY_BUFFER, 0, coords)
s.blitted = true s.blitted = true
} }
s.c.BindFramebuffer(glimpl.FRAMEBUFFER, glimpl.Framebuffer{}) s.c.BindFramebuffer(glimpl.FRAMEBUFFER, glimpl.Framebuffer{})
@@ -112,9 +112,9 @@ func (s *FBO) Refresh(w, h int) error {
} }
s.c.BindTexture(glimpl.TEXTURE_2D, s.colorTex) s.c.BindTexture(glimpl.TEXTURE_2D, s.colorTex)
if s.gl3 { if s.gl3 {
s.c.TexImage2D(glimpl.TEXTURE_2D, 0, glimpl.SRGB8_ALPHA8, w, h, glimpl.RGBA, glimpl.UNSIGNED_BYTE, nil) s.c.TexImage2D(glimpl.TEXTURE_2D, 0, glimpl.SRGB8_ALPHA8, w, h, glimpl.RGBA, glimpl.UNSIGNED_BYTE)
} else /* EXT_sRGB */ { } else /* EXT_sRGB */ {
s.c.TexImage2D(glimpl.TEXTURE_2D, 0, glimpl.SRGB_ALPHA_EXT, w, h, glimpl.SRGB_ALPHA_EXT, glimpl.UNSIGNED_BYTE, nil) s.c.TexImage2D(glimpl.TEXTURE_2D, 0, glimpl.SRGB_ALPHA_EXT, w, h, glimpl.SRGB_ALPHA_EXT, glimpl.UNSIGNED_BYTE)
} }
currentRB := glimpl.Renderbuffer(s.c.GetBinding(glimpl.RENDERBUFFER_BINDING)) currentRB := glimpl.Renderbuffer(s.c.GetBinding(glimpl.RENDERBUFFER_BINDING))
s.c.BindRenderbuffer(glimpl.RENDERBUFFER, s.depthBuffer) s.c.BindRenderbuffer(glimpl.RENDERBUFFER, s.depthBuffer)
@@ -136,7 +136,7 @@ func (s *FBO) Refresh(w, h int) error {
var pixel [4]byte var pixel [4]byte
s.c.ReadPixels(0, 0, 1, 1, glimpl.RGBA, glimpl.UNSIGNED_BYTE, pixel[:]) s.c.ReadPixels(0, 0, 1, 1, glimpl.RGBA, glimpl.UNSIGNED_BYTE, pixel[:])
if pixel[0] == 128 { // Correct sRGB color value is ~188 if pixel[0] == 128 { // Correct sRGB color value is ~188
s.c.TexImage2D(glimpl.TEXTURE_2D, 0, glimpl.RGBA, w, h, glimpl.RGBA, glimpl.UNSIGNED_BYTE, nil) s.c.TexImage2D(glimpl.TEXTURE_2D, 0, glimpl.RGBA, w, h, glimpl.RGBA, glimpl.UNSIGNED_BYTE)
if st := s.c.CheckFramebufferStatus(glimpl.FRAMEBUFFER); st != glimpl.FRAMEBUFFER_COMPLETE { if st := s.c.CheckFramebufferStatus(glimpl.FRAMEBUFFER); st != glimpl.FRAMEBUFFER_COMPLETE {
return fmt.Errorf("fallback RGBA framebuffer incomplete (%dx%d), status: %#x error: %x", s.width, s.height, st, s.c.GetError()) return fmt.Errorf("fallback RGBA framebuffer incomplete (%dx%d), status: %#x error: %x", s.width, s.height, st, s.c.GetError())
} }
+6 -2
View File
@@ -94,8 +94,12 @@ func (c *d3d11Context) Release() {
if c.fbo != nil { if c.fbo != nil {
c.fbo.Release() c.fbo.Release()
} }
c.swchain.Release() if c.swchain != nil {
c.Device.Release() c.swchain.Release()
}
if c.Device != nil {
c.Device.Release()
}
c.fbo = nil c.fbo = nil
c.swchain = nil c.swchain = nil
c.Device = nil c.Device = nil
+48 -10
View File
@@ -23,6 +23,7 @@ type Device interface {
NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error) NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error)
NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error) NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error)
NewBuffer(typ BufferBinding, size int) (Buffer, error) NewBuffer(typ BufferBinding, size int) (Buffer, error)
NewComputeProgram(shader ShaderSources) (Program, error)
NewProgram(vertexShader, fragmentShader ShaderSources) (Program, error) NewProgram(vertexShader, fragmentShader ShaderSources) (Program, error)
NewInputLayout(vertexShader ShaderSources, layout []InputDesc) (InputLayout, error) NewInputLayout(vertexShader ShaderSources, layout []InputDesc) (InputLayout, error)
@@ -43,17 +44,29 @@ type Device interface {
BindTexture(unit int, t Texture) BindTexture(unit int, t Texture)
BindVertexBuffer(b Buffer, stride, offset int) BindVertexBuffer(b Buffer, stride, offset int)
BindIndexBuffer(b Buffer) BindIndexBuffer(b Buffer)
BindImageTexture(unit int, texture Texture, access AccessBits, format TextureFormat)
MemoryBarrier()
DispatchCompute(x, y, z int)
} }
type ShaderSources struct { type ShaderSources struct {
GLSL100ES string Name string
GLSL300ES string GLSL100ES string
GLSL130 string GLSL300ES string
GLSL150 string GLSL310ES string
HLSL []byte GLSL130 string
Uniforms UniformsReflection GLSL150 string
Inputs []InputLocation HLSL []byte
Textures []TextureBinding Uniforms UniformsReflection
Inputs []InputLocation
Textures []TextureBinding
StorageBuffers []StorageBufferBinding
}
type StorageBufferBinding struct {
Binding int
BlockSize int
} }
type UniformsReflection struct { type UniformsReflection struct {
@@ -105,6 +118,8 @@ type InputLayout interface {
Release() Release()
} }
type AccessBits uint8
type BlendFactor uint8 type BlendFactor uint8
type DrawMode uint8 type DrawMode uint8
@@ -127,6 +142,7 @@ type Caps struct {
type Program interface { type Program interface {
Release() Release()
SetStorageBuffer(binding int, buf Buffer)
SetVertexUniforms(buf Buffer) SetVertexUniforms(buf Buffer)
SetFragmentUniforms(buf Buffer) SetFragmentUniforms(buf Buffer)
} }
@@ -134,6 +150,7 @@ type Program interface {
type Buffer interface { type Buffer interface {
Release() Release()
Upload(data []byte) Upload(data []byte)
Download(data []byte) error
} }
type Framebuffer interface { type Framebuffer interface {
@@ -150,7 +167,7 @@ type Timer interface {
} }
type Texture interface { type Texture interface {
Upload(img *image.RGBA) Upload(offset, size image.Point, pixels []byte)
Release() Release()
} }
@@ -171,11 +188,18 @@ const (
BufferBindingUniforms BufferBindingUniforms
BufferBindingTexture BufferBindingTexture
BufferBindingFramebuffer BufferBindingFramebuffer
BufferBindingShaderStorage
) )
const ( const (
TextureFormatSRGB TextureFormat = iota TextureFormatSRGB TextureFormat = iota
TextureFormatFloat TextureFormatFloat
TextureFormatRGBA8
)
const (
AccessRead AccessBits = 1 + iota
AccessWrite
) )
const ( const (
@@ -184,7 +208,9 @@ const (
) )
const ( const (
FeatureTimers Features = iota FeatureTimers Features = 1 << iota
FeatureFloatRenderTargets
FeatureCompute
) )
const ( const (
@@ -202,3 +228,15 @@ const (
func (f Features) Has(feats Features) bool { func (f Features) Has(feats Features) bool {
return f&feats == feats return f&feats == feats
} }
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)
}
+127 -24
View File
@@ -37,7 +37,7 @@ type glstate struct {
// nattr is the current number of enabled vertex arrays. // nattr is the current number of enabled vertex arrays.
nattr int nattr int
prog *gpuProgram prog *gpuProgram
texUnits [2]*gpuTexture texUnits [4]*gpuTexture
layout *gpuInputLayout layout *gpuInputLayout
buffer bufferBinding buffer bufferBinding
} }
@@ -87,6 +87,7 @@ type gpuProgram struct {
nattr int nattr int
vertUniforms uniformsTracker vertUniforms uniformsTracker
fragUniforms uniformsTracker fragUniforms uniformsTracker
storage [storageBindings]*gpuBuffer
} }
type uniformsTracker struct { type uniformsTracker struct {
@@ -111,13 +112,17 @@ type gpuInputLayout struct {
// textureTriple holds the type settings for // textureTriple holds the type settings for
// a TexImage2D call. // a TexImage2D call.
type textureTriple struct { type textureTriple struct {
internalFormat int internalFormat glimpl.Enum
format glimpl.Enum format glimpl.Enum
typ glimpl.Enum typ glimpl.Enum
} }
type Context = glimpl.Context type Context = glimpl.Context
const (
storageBindings = 32
)
// NewBackend returns a new Backend. // NewBackend returns a new Backend.
// //
// Pass a WebGL context if GOOS is "js", otherwise pass nil for the current // Pass a WebGL context if GOOS is "js", otherwise pass nil for the current
@@ -133,24 +138,28 @@ func NewBackend(ctx Context) (*Backend, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
floatTriple, err := floatTripleFor(f, ver, exts) floatTriple, ffboErr := floatTripleFor(f, ver, exts)
if err != nil {
return nil, err
}
srgbaTriple, err := srgbaTripleFor(ver, exts) srgbaTriple, err := srgbaTripleFor(ver, exts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ubo := ver[0] >= 3 && gles gles30 := gles && ver[0] >= 3
gles31 := gles && (ver[0] > 3 || (ver[0] == 3 && ver[1] >= 1))
b := &Backend{ b := &Backend{
glver: ver, glver: ver,
gles: gles, gles: gles,
ubo: ubo, ubo: gles30,
funcs: f, funcs: f,
floatTriple: floatTriple, floatTriple: floatTriple,
alphaTriple: alphaTripleFor(ver), alphaTriple: alphaTripleFor(ver),
srgbaTriple: srgbaTriple, srgbaTriple: srgbaTriple,
} }
if ffboErr == nil {
b.feats.Features |= backend.FeatureFloatRenderTargets
}
if gles31 {
b.feats.Features |= backend.FeatureCompute
}
if hasExtension(exts, "GL_EXT_disjoint_timer_query_webgl2") || hasExtension(exts, "GL_EXT_disjoint_timer_query") { if hasExtension(exts, "GL_EXT_disjoint_timer_query_webgl2") || hasExtension(exts, "GL_EXT_disjoint_timer_query") {
b.feats.Features |= backend.FeatureTimers b.feats.Features |= backend.FeatureTimers
} }
@@ -232,6 +241,8 @@ func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, mi
tex.triple = b.floatTriple tex.triple = b.floatTriple
case backend.TextureFormatSRGB: case backend.TextureFormatSRGB:
tex.triple = b.srgbaTriple tex.triple = b.srgbaTriple
case backend.TextureFormatRGBA8:
tex.triple = textureTriple{glimpl.RGBA8, glimpl.RGBA, glimpl.UNSIGNED_BYTE}
default: default:
return nil, errors.New("unsupported texture format") return nil, errors.New("unsupported texture format")
} }
@@ -240,7 +251,12 @@ func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, mi
b.funcs.TexParameteri(glimpl.TEXTURE_2D, glimpl.TEXTURE_MIN_FILTER, toTexFilter(minFilter)) b.funcs.TexParameteri(glimpl.TEXTURE_2D, glimpl.TEXTURE_MIN_FILTER, toTexFilter(minFilter))
b.funcs.TexParameteri(glimpl.TEXTURE_2D, glimpl.TEXTURE_WRAP_S, glimpl.CLAMP_TO_EDGE) b.funcs.TexParameteri(glimpl.TEXTURE_2D, glimpl.TEXTURE_WRAP_S, glimpl.CLAMP_TO_EDGE)
b.funcs.TexParameteri(glimpl.TEXTURE_2D, glimpl.TEXTURE_WRAP_T, glimpl.CLAMP_TO_EDGE) b.funcs.TexParameteri(glimpl.TEXTURE_2D, glimpl.TEXTURE_WRAP_T, glimpl.CLAMP_TO_EDGE)
b.funcs.TexImage2D(glimpl.TEXTURE_2D, 0, tex.triple.internalFormat, width, height, tex.triple.format, tex.triple.typ, nil) if b.gles && b.glver[0] >= 3 {
// Immutable textures are required for BindImageTexture, and can't hurt otherwise.
b.funcs.TexStorage2D(glimpl.TEXTURE_2D, 1, tex.triple.internalFormat, width, height)
} else {
b.funcs.TexImage2D(glimpl.TEXTURE_2D, 0, tex.triple.internalFormat, width, height, tex.triple.format, tex.triple.typ)
}
if err := glErr(b.funcs); err != nil { if err := glErr(b.funcs); err != nil {
tex.Release() tex.Release()
return nil, err return nil, err
@@ -267,6 +283,9 @@ func (b *Backend) NewBuffer(typ backend.BufferBinding, size int) (backend.Buffer
buf.Release() buf.Release()
return nil, err return nil, err
} }
firstBinding := firstBufferType(typ)
b.funcs.BindBuffer(firstBinding, buf.obj)
b.funcs.BufferData(firstBinding, size, glimpl.DYNAMIC_DRAW)
} }
return buf, nil return buf, nil
} }
@@ -275,6 +294,9 @@ func (b *Backend) NewImmutableBuffer(typ backend.BufferBinding, data []byte) (ba
glErr(b.funcs) glErr(b.funcs)
obj := b.funcs.CreateBuffer() obj := b.funcs.CreateBuffer()
buf := &gpuBuffer{backend: b, obj: obj, typ: typ, size: len(data), hasBuffer: true} buf := &gpuBuffer{backend: b, obj: obj, typ: typ, size: len(data), hasBuffer: true}
firstBinding := firstBufferType(typ)
b.funcs.BindBuffer(firstBinding, buf.obj)
b.funcs.BufferData(firstBinding, len(data), glimpl.STATIC_DRAW)
buf.Upload(data) buf.Upload(data)
buf.immutable = true buf.immutable = true
if err := glErr(b.funcs); err != nil { if err := glErr(b.funcs); err != nil {
@@ -291,6 +313,40 @@ func glErr(f *glimpl.Functions) error {
return nil return nil
} }
func (b *Backend) MemoryBarrier() {
b.funcs.MemoryBarrier(glimpl.ALL_BARRIER_BITS)
}
func (b *Backend) DispatchCompute(x, y, z int) {
if p := b.state.prog; p != nil {
for binding, buf := range p.storage {
if buf != nil {
b.funcs.BindBufferBase(glimpl.SHADER_STORAGE_BUFFER, binding, buf.obj)
}
}
}
b.funcs.DispatchCompute(x, y, z)
}
func (b *Backend) BindImageTexture(unit int, tex backend.Texture, access backend.AccessBits, f backend.TextureFormat) {
t := tex.(*gpuTexture)
var acc glimpl.Enum
switch access {
case backend.AccessWrite:
acc = glimpl.WRITE_ONLY
default:
panic("unsupported access bits")
}
var format glimpl.Enum
switch f {
case backend.TextureFormatRGBA8:
format = glimpl.RGBA8
default:
panic("unsupported format")
}
b.funcs.BindImageTexture(unit, t.obj, 0, false, 0, acc, format)
}
func (b *Backend) bindTexture(unit int, t *gpuTexture) { func (b *Backend) bindTexture(unit int, t *gpuTexture) {
if b.state.texUnits[unit] != t { if b.state.texUnits[unit] != t {
b.funcs.ActiveTexture(glimpl.TEXTURE0 + glimpl.Enum(unit)) b.funcs.ActiveTexture(glimpl.TEXTURE0 + glimpl.Enum(unit))
@@ -433,6 +489,18 @@ func (b *Backend) NewInputLayout(vs backend.ShaderSources, layout []backend.Inpu
}, nil }, nil
} }
func (b *Backend) NewComputeProgram(src backend.ShaderSources) (backend.Program, error) {
p, err := glimpl.CreateComputeProgram(b.funcs, src.GLSL310ES)
if err != nil {
return nil, fmt.Errorf("%s: %v", src.Name, err)
}
gpuProg := &gpuProgram{
backend: b,
obj: p,
}
return gpuProg, nil
}
func (b *Backend) NewProgram(vertShader, fragShader backend.ShaderSources) (backend.Program, error) { func (b *Backend) NewProgram(vertShader, fragShader backend.ShaderSources) (backend.Program, error) {
attr := make([]string, len(vertShader.Inputs)) attr := make([]string, len(vertShader.Inputs))
for _, inp := range vertShader.Inputs { for _, inp := range vertShader.Inputs {
@@ -503,6 +571,14 @@ func lookupUniform(funcs *glimpl.Functions, p glimpl.Program, loc backend.Unifor
return uniformLocation{uniform: u, offset: loc.Offset, typ: loc.Type, size: loc.Size} return uniformLocation{uniform: u, offset: loc.Offset, typ: loc.Type, size: loc.Size}
} }
func (p *gpuProgram) SetStorageBuffer(binding int, buffer backend.Buffer) {
buf := buffer.(*gpuBuffer)
if buf.typ&backend.BufferBindingShaderStorage == 0 {
panic("not a shader storage buffer")
}
p.storage[binding] = buf
}
func (p *gpuProgram) SetVertexUniforms(buffer backend.Buffer) { func (p *gpuProgram) SetVertexUniforms(buffer backend.Buffer) {
p.vertUniforms.setBuffer(buffer) p.vertUniforms.setBuffer(buffer)
} }
@@ -600,10 +676,31 @@ func (b *gpuBuffer) Upload(data []byte) {
if b.hasBuffer { if b.hasBuffer {
firstBinding := firstBufferType(b.typ) firstBinding := firstBufferType(b.typ)
b.backend.funcs.BindBuffer(firstBinding, b.obj) b.backend.funcs.BindBuffer(firstBinding, b.obj)
b.backend.funcs.BufferData(firstBinding, data, glimpl.STATIC_DRAW) b.backend.funcs.BufferSubData(firstBinding, 0, data)
} }
} }
func (b *gpuBuffer) Download(data []byte) error {
if len(data) > b.size {
panic("buffer size overflow")
}
if !b.hasBuffer {
copy(data, b.data)
return nil
}
firstBinding := firstBufferType(b.typ)
b.backend.funcs.BindBuffer(firstBinding, b.obj)
bufferMap := b.backend.funcs.MapBufferRange(firstBinding, 0, len(data), glimpl.MAP_READ_BIT)
if bufferMap == nil {
return fmt.Errorf("MapBufferRange: error %#x", b.backend.funcs.GetError())
}
copy(data, bufferMap)
if !b.backend.funcs.UnmapBuffer(firstBinding) {
return errors.New("buffer content lost")
}
return nil
}
func (b *gpuBuffer) Release() { func (b *gpuBuffer) Release() {
if b.hasBuffer { if b.hasBuffer {
b.backend.funcs.DeleteBuffer(b.obj) b.backend.funcs.DeleteBuffer(b.obj)
@@ -649,10 +746,20 @@ func (b *Backend) BindIndexBuffer(buf backend.Buffer) {
b.funcs.BindBuffer(glimpl.ELEMENT_ARRAY_BUFFER, gbuf.obj) b.funcs.BindBuffer(glimpl.ELEMENT_ARRAY_BUFFER, gbuf.obj)
} }
func (b *Backend) BlitFramebuffer(dst, src backend.Framebuffer, srect, drect image.Rectangle) {
b.funcs.BindFramebuffer(glimpl.DRAW_FRAMEBUFFER, dst.(*gpuFramebuffer).obj)
b.funcs.BindFramebuffer(glimpl.READ_FRAMEBUFFER, src.(*gpuFramebuffer).obj)
b.funcs.BlitFramebuffer(
srect.Min.X, srect.Min.Y, srect.Max.X, srect.Max.Y,
drect.Min.X, drect.Min.Y, drect.Max.X, drect.Max.Y,
glimpl.COLOR_BUFFER_BIT|glimpl.DEPTH_BUFFER_BIT|glimpl.STENCIL_BUFFER_BIT,
glimpl.NEAREST)
}
func (f *gpuFramebuffer) ReadPixels(src image.Rectangle, pixels []byte) error { func (f *gpuFramebuffer) ReadPixels(src image.Rectangle, pixels []byte) error {
glErr(f.backend.funcs) glErr(f.backend.funcs)
f.backend.BindFramebuffer(f) f.backend.BindFramebuffer(f)
if len(pixels) < src.Dx()*src.Dy() { if len(pixels) < src.Dx()*src.Dy()*4 {
return errors.New("unexpected RGBA size") return errors.New("unexpected RGBA size")
} }
f.backend.funcs.ReadPixels(src.Min.X, src.Min.Y, src.Dx(), src.Dy(), glimpl.RGBA, glimpl.UNSIGNED_BYTE, pixels) f.backend.funcs.ReadPixels(src.Min.X, src.Min.Y, src.Dx(), src.Dy(), glimpl.RGBA, glimpl.UNSIGNED_BYTE, pixels)
@@ -714,18 +821,12 @@ func (t *gpuTexture) Release() {
t.backend.funcs.DeleteTexture(t.obj) t.backend.funcs.DeleteTexture(t.obj)
} }
func (t *gpuTexture) Upload(img *image.RGBA) { func (t *gpuTexture) Upload(offset, size image.Point, pixels []byte) {
t.backend.BindTexture(0, t) if min := size.X * size.Y * 4; min > len(pixels) {
var pixels []byte panic(fmt.Errorf("size %d larger than data %d", min, len(pixels)))
b := img.Bounds()
w, h := b.Dx(), b.Dy()
if img.Stride != w*4 {
panic("unsupported stride")
} }
start := (b.Min.X + b.Min.Y*w) * 4 t.backend.BindTexture(0, t)
end := (b.Max.X + (b.Max.Y-1)*w) * 4 t.backend.funcs.TexSubImage2D(glimpl.TEXTURE_2D, 0, offset.X, offset.Y, size.X, size.Y, t.triple.format, t.triple.typ, pixels)
pixels = img.Pix[start:end]
t.backend.funcs.TexImage2D(glimpl.TEXTURE_2D, 0, t.triple.internalFormat, w, h, t.triple.format, t.triple.typ, pixels)
} }
func (t *gpuTimer) Begin() { func (t *gpuTimer) Begin() {
@@ -792,7 +893,7 @@ func floatTripleFor(f *glimpl.Functions, ver [2]int, exts []string) (textureTrip
var attempts []string var attempts []string
for _, tt := range triples { for _, tt := range triples {
const size = 256 const size = 256
f.TexImage2D(glimpl.TEXTURE_2D, 0, tt.internalFormat, size, size, tt.format, tt.typ, nil) f.TexImage2D(glimpl.TEXTURE_2D, 0, tt.internalFormat, size, size, tt.format, tt.typ)
f.FramebufferTexture2D(glimpl.FRAMEBUFFER, glimpl.COLOR_ATTACHMENT0, glimpl.TEXTURE_2D, tex, 0) f.FramebufferTexture2D(glimpl.FRAMEBUFFER, glimpl.COLOR_ATTACHMENT0, glimpl.TEXTURE_2D, tex, 0)
st := f.CheckFramebufferStatus(glimpl.FRAMEBUFFER) st := f.CheckFramebufferStatus(glimpl.FRAMEBUFFER)
if st == glimpl.FRAMEBUFFER_COMPLETE { if st == glimpl.FRAMEBUFFER_COMPLETE {
@@ -815,7 +916,7 @@ func srgbaTripleFor(ver [2]int, exts []string) (textureTriple, error) {
} }
func alphaTripleFor(ver [2]int) textureTriple { func alphaTripleFor(ver [2]int) textureTriple {
intf, f := glimpl.R8, glimpl.Enum(glimpl.RED) intf, f := glimpl.Enum(glimpl.R8), glimpl.Enum(glimpl.RED)
if ver[0] < 3 { if ver[0] < 3 {
// R8, RED not supported on OpenGL ES 2.0. // R8, RED not supported on OpenGL ES 2.0.
intf, f = glimpl.LUMINANCE, glimpl.Enum(glimpl.LUMINANCE) intf, f = glimpl.LUMINANCE, glimpl.Enum(glimpl.LUMINANCE)
@@ -840,6 +941,8 @@ func firstBufferType(typ backend.BufferBinding) glimpl.Enum {
return glimpl.ARRAY_BUFFER return glimpl.ARRAY_BUFFER
case typ&backend.BufferBindingUniforms != 0: case typ&backend.BufferBindingUniforms != 0:
return glimpl.UNIFORM_BUFFER return glimpl.UNIFORM_BUFFER
case typ&backend.BufferBindingShaderStorage != 0:
return glimpl.SHADER_STORAGE_BUFFER
default: default:
panic("unsupported buffer type") panic("unsupported buffer type")
} }
+1 -1
View File
@@ -479,7 +479,7 @@ func (r *renderer) texHandle(cache *resourceCache, data imageOpData) backend.Tex
if err != nil { if err != nil {
panic(err) panic(err)
} }
handle.Upload(data.src) backend.UploadImage(handle, image.Pt(0, 0), data.src)
tex.tex = handle tex.tex = handle
return tex.tex return tex.tex
} }
+22 -2
View File
@@ -8,19 +8,24 @@ type (
) )
const ( const (
ALL_BARRIER_BITS = 0xffffffff
ARRAY_BUFFER = 0x8892 ARRAY_BUFFER = 0x8892
BLEND = 0xbe2 BLEND = 0xbe2
CLAMP_TO_EDGE = 0x812f CLAMP_TO_EDGE = 0x812f
COLOR_ATTACHMENT0 = 0x8ce0 COLOR_ATTACHMENT0 = 0x8ce0
COLOR_BUFFER_BIT = 0x4000 COLOR_BUFFER_BIT = 0x4000
COMPILE_STATUS = 0x8b81 COMPILE_STATUS = 0x8b81
COMPUTE_SHADER = 0x91B9
DEPTH_BUFFER_BIT = 0x100 DEPTH_BUFFER_BIT = 0x100
DEPTH_ATTACHMENT = 0x8d00 DEPTH_ATTACHMENT = 0x8d00
DEPTH_COMPONENT16 = 0x81a5 DEPTH_COMPONENT16 = 0x81a5
DEPTH_COMPONENT24 = 0x81A6 DEPTH_COMPONENT24 = 0x81A6
DEPTH_COMPONENT32F = 0x8CAC DEPTH_COMPONENT32F = 0x8CAC
DEPTH_TEST = 0xb71 DEPTH_TEST = 0xb71
DRAW_FRAMEBUFFER = 0x8CA9
DST_COLOR = 0x306 DST_COLOR = 0x306
DYNAMIC_DRAW = 0x88E8
DYNAMIC_READ = 0x88E9
ELEMENT_ARRAY_BUFFER = 0x8893 ELEMENT_ARRAY_BUFFER = 0x8893
EXTENSIONS = 0x1f03 EXTENSIONS = 0x1f03
FALSE = 0 FALSE = 0
@@ -39,6 +44,7 @@ const (
LINEAR = 0x2601 LINEAR = 0x2601
LINK_STATUS = 0x8b82 LINK_STATUS = 0x8b82
LUMINANCE = 0x1909 LUMINANCE = 0x1909
MAP_READ_BIT = 0x0001
MAX_TEXTURE_SIZE = 0xd33 MAX_TEXTURE_SIZE = 0xd33
NEAREST = 0x2600 NEAREST = 0x2600
NO_ERROR = 0x0 NO_ERROR = 0x0
@@ -50,6 +56,8 @@ const (
R16F = 0x822d R16F = 0x822d
R8 = 0x8229 R8 = 0x8229
READ_FRAMEBUFFER = 0x8ca8 READ_FRAMEBUFFER = 0x8ca8
READ_ONLY = 0x88B8
READ_WRITE = 0x88BA
RED = 0x1903 RED = 0x1903
RENDERER = 0x1F01 RENDERER = 0x1F01
RENDERBUFFER = 0x8d41 RENDERBUFFER = 0x8d41
@@ -59,12 +67,14 @@ const (
RGB = 0x1907 RGB = 0x1907
RGBA = 0x1908 RGBA = 0x1908
RGBA8 = 0x8058 RGBA8 = 0x8058
SHADER_STORAGE_BUFFER = 0x90D2
SHORT = 0x1402 SHORT = 0x1402
SRGB = 0x8c40 SRGB = 0x8c40
SRGB_ALPHA_EXT = 0x8c42 SRGB_ALPHA_EXT = 0x8c42
SRGB8 = 0x8c41 SRGB8 = 0x8c41
SRGB8_ALPHA8 = 0x8c43 SRGB8_ALPHA8 = 0x8c43
STATIC_DRAW = 0x88e4 STATIC_DRAW = 0x88e4
STENCIL_BUFFER_BIT = 0x00000400
TEXTURE_2D = 0xde1 TEXTURE_2D = 0xde1
TEXTURE_MAG_FILTER = 0x2800 TEXTURE_MAG_FILTER = 0x2800
TEXTURE_MIN_FILTER = 0x2801 TEXTURE_MIN_FILTER = 0x2801
@@ -81,6 +91,7 @@ const (
UNSIGNED_SHORT = 0x1403 UNSIGNED_SHORT = 0x1403
VERSION = 0x1f02 VERSION = 0x1f02
VERTEX_SHADER = 0x8b31 VERTEX_SHADER = 0x8b31
WRITE_ONLY = 0x88B9
ZERO = 0x0 ZERO = 0x0
// EXT_disjoint_timer_query // EXT_disjoint_timer_query
@@ -96,11 +107,14 @@ var _ interface {
BindBuffer(target Enum, b Buffer) BindBuffer(target Enum, b Buffer)
BindBufferBase(target Enum, index int, buffer Buffer) BindBufferBase(target Enum, index int, buffer Buffer)
BindFramebuffer(target Enum, fb Framebuffer) BindFramebuffer(target Enum, fb Framebuffer)
BindImageTexture(unit int, t Texture, level int, layered bool, layer int, access, format Enum)
BindRenderbuffer(target Enum, fb Renderbuffer) BindRenderbuffer(target Enum, fb Renderbuffer)
BindTexture(target Enum, t Texture) BindTexture(target Enum, t Texture)
BlendEquation(mode Enum) BlendEquation(mode Enum)
BlendFunc(sfactor, dfactor 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 CheckFramebufferStatus(target Enum) Enum
Clear(mask Enum) Clear(mask Enum)
ClearColor(red, green, blue, alpha float32) ClearColor(red, green, blue, alpha float32)
@@ -124,6 +138,7 @@ var _ interface {
DepthMask(mask bool) DepthMask(mask bool)
DisableVertexAttribArray(a Attrib) DisableVertexAttribArray(a Attrib)
Disable(cap Enum) Disable(cap Enum)
DispatchCompute(x, y, z int)
DrawArrays(mode Enum, first, count int) DrawArrays(mode Enum, first, count int)
DrawElements(mode Enum, count int, ty Enum, offset int) DrawElements(mode Enum, count int, ty Enum, offset int)
Enable(cap Enum) Enable(cap Enum)
@@ -144,11 +159,15 @@ var _ interface {
GetUniformLocation(p Program, name string) Uniform GetUniformLocation(p Program, name string) Uniform
InvalidateFramebuffer(target, attachment Enum) InvalidateFramebuffer(target, attachment Enum)
LinkProgram(p Program) 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) ReadPixels(x, y, width, height int, format, ty Enum, data []byte)
RenderbufferStorage(target, internalformat Enum, width, height int) RenderbufferStorage(target, internalformat Enum, width, height int)
ShaderSource(s Shader, src string) 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) 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) UniformBlockBinding(p Program, uniformBlockIndex uint, uniformBlockBinding uint)
Uniform1f(dst Uniform, v float32) Uniform1f(dst Uniform, v float32)
Uniform1i(dst Uniform, v int) Uniform1i(dst Uniform, v int)
@@ -156,6 +175,7 @@ var _ interface {
Uniform3f(dst Uniform, v0, v1, v2 float32) Uniform3f(dst Uniform, v0, v1, v2 float32)
Uniform4f(dst Uniform, v0, v1, v2, v3 float32) Uniform4f(dst Uniform, v0, v1, v2, v3 float32)
UseProgram(p Program) UseProgram(p Program)
UnmapBuffer(target Enum) bool
VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int)
Viewport(x, y, width, height int) Viewport(x, y, width, height int)
} = (*Functions)(nil) } = (*Functions)(nil)
+93 -8
View File
@@ -51,6 +51,13 @@ static void (*_glEndQuery)(GLenum target);
static void (*_glGenQueries)(GLsizei n, GLuint *ids); static void (*_glGenQueries)(GLsizei n, GLuint *ids);
static void (*_glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params); static void (*_glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params);
static const GLubyte* (*_glGetStringi)(GLenum name, GLuint index); 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. // 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) { __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); _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() { __attribute__((constructor)) static void gio_loadGLFunctions() {
#ifdef __APPLE__ #ifdef __APPLE__
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
@@ -122,6 +157,7 @@ __attribute__((constructor)) static void gio_loadGLFunctions() {
_glGetUniformBlockIndex = glGetUniformBlockIndex; _glGetUniformBlockIndex = glGetUniformBlockIndex;
_glUniformBlockBinding = glUniformBlockBinding; _glUniformBlockBinding = glUniformBlockBinding;
_glGetStringi = glGetStringi; _glGetStringi = glGetStringi;
_glTexStorage2D = glTexStorage2D;
#else #else
// Load libGLESv3 if available. // Load libGLESv3 if available.
dlopen("libGLESv3.so", RTLD_NOW | RTLD_GLOBAL); dlopen("libGLESv3.so", RTLD_NOW | RTLD_GLOBAL);
@@ -150,6 +186,14 @@ __attribute__((constructor)) static void gio_loadGLFunctions() {
_glGetQueryObjectuiv = dlsym(RTLD_DEFAULT, "glGetQueryObjectuiv"); _glGetQueryObjectuiv = dlsym(RTLD_DEFAULT, "glGetQueryObjectuiv");
if (_glGetQueryObjectuiv == NULL) if (_glGetQueryObjectuiv == NULL)
_glGetQueryObjectuiv = dlsym(RTLD_DEFAULT, "glGetQueryObjectuivEXT"); _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 #endif
} }
*/ */
@@ -204,6 +248,14 @@ func (f *Functions) BindRenderbuffer(target Enum, fb Renderbuffer) {
C.glBindRenderbuffer(C.GLenum(target), C.GLuint(fb.V)) 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) { func (f *Functions) BindTexture(target Enum, t Texture) {
C.glBindTexture(C.GLenum(target), C.GLuint(t.V)) 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)) 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 var p unsafe.Pointer
if len(src) > 0 { if len(src) > 0 {
p = unsafe.Pointer(&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 { 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)) 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) { func (f *Functions) Enable(cap Enum) {
C.glEnable(C.GLenum(cap)) 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)) 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) { func (f *Functions) Scissor(x, y, width, height int32) {
C.glScissor(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height)) 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) 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) { func (f *Functions) TexImage2D(target Enum, level int, internalFormat Enum, width int, height int, format Enum, ty Enum) {
var p unsafe.Pointer 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)
if len(data) > 0 { }
p = unsafe.Pointer(&data[0])
} func (f *Functions) TexStorage2D(target Enum, levels int, internalFormat Enum, width, height int) {
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) 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) { 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)) 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) { func (f *Functions) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride int, offset int) {
var n C.GLboolean = C.GL_FALSE var n C.GLboolean = C.GL_FALSE
if normalized { if normalized {
+31 -13
View File
@@ -27,6 +27,7 @@ var (
_glBlendEquation = LibGLESv2.NewProc("glBlendEquation") _glBlendEquation = LibGLESv2.NewProc("glBlendEquation")
_glBlendFunc = LibGLESv2.NewProc("glBlendFunc") _glBlendFunc = LibGLESv2.NewProc("glBlendFunc")
_glBufferData = LibGLESv2.NewProc("glBufferData") _glBufferData = LibGLESv2.NewProc("glBufferData")
_glBufferSubData = LibGLESv2.NewProc("glBufferSubData")
_glCheckFramebufferStatus = LibGLESv2.NewProc("glCheckFramebufferStatus") _glCheckFramebufferStatus = LibGLESv2.NewProc("glCheckFramebufferStatus")
_glClear = LibGLESv2.NewProc("glClear") _glClear = LibGLESv2.NewProc("glClear")
_glClearColor = LibGLESv2.NewProc("glClearColor") _glClearColor = LibGLESv2.NewProc("glClearColor")
@@ -78,6 +79,7 @@ var (
_glScissor = LibGLESv2.NewProc("glScissor") _glScissor = LibGLESv2.NewProc("glScissor")
_glShaderSource = LibGLESv2.NewProc("glShaderSource") _glShaderSource = LibGLESv2.NewProc("glShaderSource")
_glTexImage2D = LibGLESv2.NewProc("glTexImage2D") _glTexImage2D = LibGLESv2.NewProc("glTexImage2D")
_glTexStorage2D = LibGLESv2.NewProc("glTexStorage2D")
_glTexSubImage2D = LibGLESv2.NewProc("glTexSubImage2D") _glTexSubImage2D = LibGLESv2.NewProc("glTexSubImage2D")
_glTexParameteri = LibGLESv2.NewProc("glTexParameteri") _glTexParameteri = LibGLESv2.NewProc("glTexParameteri")
_glUniformBlockBinding = LibGLESv2.NewProc("glUniformBlockBinding") _glUniformBlockBinding = LibGLESv2.NewProc("glUniformBlockBinding")
@@ -132,6 +134,9 @@ func (c *Functions) BindFramebuffer(target Enum, fb Framebuffer) {
func (c *Functions) BindRenderbuffer(target Enum, rb Renderbuffer) { func (c *Functions) BindRenderbuffer(target Enum, rb Renderbuffer) {
syscall.Syscall(_glBindRenderbuffer.Addr(), 2, uintptr(target), uintptr(rb.V), 0) 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) { func (c *Functions) BindTexture(target Enum, t Texture) {
syscall.Syscall(_glBindTexture.Addr(), 2, uintptr(target), uintptr(t.V), 0) 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) { func (c *Functions) BlendFunc(sfactor, dfactor Enum) {
syscall.Syscall(_glBlendFunc.Addr(), 2, uintptr(sfactor), uintptr(dfactor), 0) syscall.Syscall(_glBlendFunc.Addr(), 2, uintptr(sfactor), uintptr(dfactor), 0)
} }
func (c *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) {
if n := len(src); n == 0 { panic("not implemented")
syscall.Syscall6(_glBufferData.Addr(), 4, uintptr(target), 0, 0, uintptr(usage), 0, 0) }
} else { 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] 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) 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) { 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) 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) { func (c *Functions) Enable(cap Enum) {
syscall.Syscall(_glEnable.Addr(), 1, uintptr(cap), 0, 0) 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) { func (c *Functions) PixelStorei(pname Enum, param int32) {
syscall.Syscall(_glPixelStorei.Addr(), 2, uintptr(pname), uintptr(param), 0) 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) { func (f *Functions) ReadPixels(x, y, width, height int, format, ty Enum, data []byte) {
d0 := &data[0] 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) 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) syscall.Syscall6(_glShaderSource.Addr(), 4, uintptr(s.V), 1, uintptr(unsafe.Pointer(psrc)), uintptr(unsafe.Pointer(&n)), 0, 0)
issue34474KeepAlive(psrc) issue34474KeepAlive(psrc)
} }
func (c *Functions) TexImage2D(target Enum, level int, internalFormat int, width, height int, format, ty Enum, data []byte) { func (f *Functions) TexImage2D(target Enum, level int, internalFormat Enum, width int, height int, format Enum, ty Enum) {
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)
syscall.Syscall9(_glTexImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(internalFormat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(ty), 0) }
} else { func (f *Functions) TexStorage2D(target Enum, levels int, internalFormat Enum, width, height int) {
d0 := &data[0] syscall.Syscall6(_glTexStorage2D.Addr(), 5, uintptr(target), uintptr(levels), uintptr(internalFormat), uintptr(width), uintptr(height), 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 (c *Functions) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) { func (c *Functions) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) {
d0 := &data[0] d0 := &data[0]
@@ -390,6 +405,9 @@ func (c *Functions) Uniform4f(dst Uniform, v0, v1, v2, v3 float32) {
func (c *Functions) UseProgram(p Program) { func (c *Functions) UseProgram(p Program) {
syscall.Syscall(_glUseProgram.Addr(), 1, uintptr(p.V), 0, 0) 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) { func (c *Functions) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) {
var norm uintptr var norm uintptr
if normalized { if normalized {
+20
View File
@@ -37,6 +37,26 @@ func CreateProgram(ctx *Functions, vsSrc, fsSrc string, attribs []string) (Progr
return prog, nil 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) { func createShader(ctx *Functions, typ Enum, src string) (Shader, error) {
sh := ctx.CreateShader(typ) sh := ctx.CreateShader(typ)
if !sh.Valid() { if !sh.Valid() {