forked from joejulian/gio
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:
@@ -121,12 +121,7 @@ func NewDevice() (*Device, error) {
|
||||
_IUnknownRelease(unsafe.Pointer(d3dctx), d3dctx.vtbl.Release)
|
||||
return nil, fmt.Errorf("d3d11: feature level too low: %d", featLvl)
|
||||
}
|
||||
floatFormat, ok := 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")
|
||||
}
|
||||
floatFormat, _ := detectFloatFormat(d3ddev)
|
||||
dev.floatFormat = floatFormat
|
||||
dev.depthStates = make(map[depthState]*_ID3D11DepthStencilState)
|
||||
dev.blendStates = make(map[blendState]*_ID3D11BlendState)
|
||||
@@ -253,6 +248,9 @@ func NewBackend(d *Device) (*Backend, error) {
|
||||
caps := backend.Caps{
|
||||
MaxTextureSize: 2048, // 9.1 maximum
|
||||
}
|
||||
if d.floatFormat != 0 {
|
||||
caps.Features |= backend.FeatureFloatRenderTargets
|
||||
}
|
||||
switch {
|
||||
case d.featLvl >= _D3D_FEATURE_LEVEL_11_0:
|
||||
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
|
||||
}
|
||||
|
||||
func (b *Backend) NewComputeProgram(shader backend.ShaderSources) (backend.Program, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (b *Backend) NewProgram(vertexShader, fragmentShader backend.ShaderSources) (backend.Program, error) {
|
||||
vs, err := b.dev.dev.CreateVertexShader(vertexShader.HLSL)
|
||||
if err != nil {
|
||||
@@ -667,17 +669,30 @@ func (b *Backend) BlendFunc(sfactor, dfactor backend.BlendFactor) {
|
||||
b.blendState.dfactor = dfactor
|
||||
}
|
||||
|
||||
func (t *Texture) Upload(img *image.RGBA) {
|
||||
b := img.Bounds()
|
||||
w := b.Dx()
|
||||
if img.Stride != w*4 {
|
||||
panic("unsupported stride")
|
||||
func (b *Backend) BindImageTexture(unit int, tex backend.Texture, access backend.AccessBits, f backend.TextureFormat) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
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))
|
||||
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() {
|
||||
@@ -710,6 +725,10 @@ func (p *Program) Release() {
|
||||
p.frag.shader = nil
|
||||
}
|
||||
|
||||
func (p *Program) SetStorageBuffer(binding int, buffer backend.Buffer) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (p *Program) SetVertexUniforms(buf backend.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)
|
||||
}
|
||||
|
||||
func (b *Buffer) Download(data []byte) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
@@ -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(
|
||||
c.vtbl.UpdateSubresource,
|
||||
7,
|
||||
uintptr(unsafe.Pointer(c)),
|
||||
uintptr(unsafe.Pointer(res)),
|
||||
0, // DstSubresource
|
||||
0, // pDstBox
|
||||
uintptr(unsafe.Pointer(dstBox)),
|
||||
uintptr(unsafe.Pointer(&data[0])),
|
||||
uintptr(rowPitch),
|
||||
uintptr(depthPitch),
|
||||
|
||||
+11
-11
@@ -71,14 +71,14 @@ func (s *FBO) Blit() {
|
||||
s.c.Uniform1i(s.c.GetUniformLocation(prog, "tex"), 0)
|
||||
s.quad = s.c.CreateBuffer()
|
||||
s.c.BindBuffer(glimpl.ARRAY_BUFFER, s.quad)
|
||||
s.c.BufferData(glimpl.ARRAY_BUFFER,
|
||||
unsafe.BytesView([]float32{
|
||||
-1, +1, 0, 1,
|
||||
+1, +1, 1, 1,
|
||||
-1, -1, 0, 0,
|
||||
+1, -1, 1, 0,
|
||||
}),
|
||||
glimpl.STATIC_DRAW)
|
||||
coords := unsafe.BytesView([]float32{
|
||||
-1, +1, 0, 1,
|
||||
+1, +1, 1, 1,
|
||||
-1, -1, 0, 0,
|
||||
+1, -1, 1, 0,
|
||||
})
|
||||
s.c.BufferData(glimpl.ARRAY_BUFFER, len(coords), glimpl.STATIC_DRAW)
|
||||
s.c.BufferSubData(glimpl.ARRAY_BUFFER, 0, coords)
|
||||
s.blitted = true
|
||||
}
|
||||
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)
|
||||
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 */ {
|
||||
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))
|
||||
s.c.BindRenderbuffer(glimpl.RENDERBUFFER, s.depthBuffer)
|
||||
@@ -136,7 +136,7 @@ func (s *FBO) Refresh(w, h int) error {
|
||||
var pixel [4]byte
|
||||
s.c.ReadPixels(0, 0, 1, 1, glimpl.RGBA, glimpl.UNSIGNED_BYTE, pixel[:])
|
||||
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 {
|
||||
return fmt.Errorf("fallback RGBA framebuffer incomplete (%dx%d), status: %#x error: %x", s.width, s.height, st, s.c.GetError())
|
||||
}
|
||||
|
||||
@@ -94,8 +94,12 @@ func (c *d3d11Context) Release() {
|
||||
if c.fbo != nil {
|
||||
c.fbo.Release()
|
||||
}
|
||||
c.swchain.Release()
|
||||
c.Device.Release()
|
||||
if c.swchain != nil {
|
||||
c.swchain.Release()
|
||||
}
|
||||
if c.Device != nil {
|
||||
c.Device.Release()
|
||||
}
|
||||
c.fbo = nil
|
||||
c.swchain = nil
|
||||
c.Device = nil
|
||||
|
||||
+48
-10
@@ -23,6 +23,7 @@ type Device interface {
|
||||
NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error)
|
||||
NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error)
|
||||
NewBuffer(typ BufferBinding, size int) (Buffer, error)
|
||||
NewComputeProgram(shader ShaderSources) (Program, error)
|
||||
NewProgram(vertexShader, fragmentShader ShaderSources) (Program, error)
|
||||
NewInputLayout(vertexShader ShaderSources, layout []InputDesc) (InputLayout, error)
|
||||
|
||||
@@ -43,17 +44,29 @@ type Device interface {
|
||||
BindTexture(unit int, t Texture)
|
||||
BindVertexBuffer(b Buffer, stride, offset int)
|
||||
BindIndexBuffer(b Buffer)
|
||||
BindImageTexture(unit int, texture Texture, access AccessBits, format TextureFormat)
|
||||
|
||||
MemoryBarrier()
|
||||
DispatchCompute(x, y, z int)
|
||||
}
|
||||
|
||||
type ShaderSources struct {
|
||||
GLSL100ES string
|
||||
GLSL300ES string
|
||||
GLSL130 string
|
||||
GLSL150 string
|
||||
HLSL []byte
|
||||
Uniforms UniformsReflection
|
||||
Inputs []InputLocation
|
||||
Textures []TextureBinding
|
||||
Name string
|
||||
GLSL100ES string
|
||||
GLSL300ES string
|
||||
GLSL310ES string
|
||||
GLSL130 string
|
||||
GLSL150 string
|
||||
HLSL []byte
|
||||
Uniforms UniformsReflection
|
||||
Inputs []InputLocation
|
||||
Textures []TextureBinding
|
||||
StorageBuffers []StorageBufferBinding
|
||||
}
|
||||
|
||||
type StorageBufferBinding struct {
|
||||
Binding int
|
||||
BlockSize int
|
||||
}
|
||||
|
||||
type UniformsReflection struct {
|
||||
@@ -105,6 +118,8 @@ type InputLayout interface {
|
||||
Release()
|
||||
}
|
||||
|
||||
type AccessBits uint8
|
||||
|
||||
type BlendFactor uint8
|
||||
|
||||
type DrawMode uint8
|
||||
@@ -127,6 +142,7 @@ type Caps struct {
|
||||
|
||||
type Program interface {
|
||||
Release()
|
||||
SetStorageBuffer(binding int, buf Buffer)
|
||||
SetVertexUniforms(buf Buffer)
|
||||
SetFragmentUniforms(buf Buffer)
|
||||
}
|
||||
@@ -134,6 +150,7 @@ type Program interface {
|
||||
type Buffer interface {
|
||||
Release()
|
||||
Upload(data []byte)
|
||||
Download(data []byte) error
|
||||
}
|
||||
|
||||
type Framebuffer interface {
|
||||
@@ -150,7 +167,7 @@ type Timer interface {
|
||||
}
|
||||
|
||||
type Texture interface {
|
||||
Upload(img *image.RGBA)
|
||||
Upload(offset, size image.Point, pixels []byte)
|
||||
Release()
|
||||
}
|
||||
|
||||
@@ -171,11 +188,18 @@ const (
|
||||
BufferBindingUniforms
|
||||
BufferBindingTexture
|
||||
BufferBindingFramebuffer
|
||||
BufferBindingShaderStorage
|
||||
)
|
||||
|
||||
const (
|
||||
TextureFormatSRGB TextureFormat = iota
|
||||
TextureFormatFloat
|
||||
TextureFormatRGBA8
|
||||
)
|
||||
|
||||
const (
|
||||
AccessRead AccessBits = 1 + iota
|
||||
AccessWrite
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -184,7 +208,9 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
FeatureTimers Features = iota
|
||||
FeatureTimers Features = 1 << iota
|
||||
FeatureFloatRenderTargets
|
||||
FeatureCompute
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -202,3 +228,15 @@ const (
|
||||
func (f Features) Has(feats Features) bool {
|
||||
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
@@ -37,7 +37,7 @@ type glstate struct {
|
||||
// nattr is the current number of enabled vertex arrays.
|
||||
nattr int
|
||||
prog *gpuProgram
|
||||
texUnits [2]*gpuTexture
|
||||
texUnits [4]*gpuTexture
|
||||
layout *gpuInputLayout
|
||||
buffer bufferBinding
|
||||
}
|
||||
@@ -87,6 +87,7 @@ type gpuProgram struct {
|
||||
nattr int
|
||||
vertUniforms uniformsTracker
|
||||
fragUniforms uniformsTracker
|
||||
storage [storageBindings]*gpuBuffer
|
||||
}
|
||||
|
||||
type uniformsTracker struct {
|
||||
@@ -111,13 +112,17 @@ type gpuInputLayout struct {
|
||||
// textureTriple holds the type settings for
|
||||
// a TexImage2D call.
|
||||
type textureTriple struct {
|
||||
internalFormat int
|
||||
internalFormat glimpl.Enum
|
||||
format glimpl.Enum
|
||||
typ glimpl.Enum
|
||||
}
|
||||
|
||||
type Context = glimpl.Context
|
||||
|
||||
const (
|
||||
storageBindings = 32
|
||||
)
|
||||
|
||||
// NewBackend returns a new Backend.
|
||||
//
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
floatTriple, err := floatTripleFor(f, ver, exts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
floatTriple, ffboErr := floatTripleFor(f, ver, exts)
|
||||
srgbaTriple, err := srgbaTripleFor(ver, exts)
|
||||
if err != nil {
|
||||
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{
|
||||
glver: ver,
|
||||
gles: gles,
|
||||
ubo: ubo,
|
||||
ubo: gles30,
|
||||
funcs: f,
|
||||
floatTriple: floatTriple,
|
||||
alphaTriple: alphaTripleFor(ver),
|
||||
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") {
|
||||
b.feats.Features |= backend.FeatureTimers
|
||||
}
|
||||
@@ -232,6 +241,8 @@ func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, mi
|
||||
tex.triple = b.floatTriple
|
||||
case backend.TextureFormatSRGB:
|
||||
tex.triple = b.srgbaTriple
|
||||
case backend.TextureFormatRGBA8:
|
||||
tex.triple = textureTriple{glimpl.RGBA8, glimpl.RGBA, glimpl.UNSIGNED_BYTE}
|
||||
default:
|
||||
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_WRAP_S, 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 {
|
||||
tex.Release()
|
||||
return nil, err
|
||||
@@ -267,6 +283,9 @@ func (b *Backend) NewBuffer(typ backend.BufferBinding, size int) (backend.Buffer
|
||||
buf.Release()
|
||||
return nil, err
|
||||
}
|
||||
firstBinding := firstBufferType(typ)
|
||||
b.funcs.BindBuffer(firstBinding, buf.obj)
|
||||
b.funcs.BufferData(firstBinding, size, glimpl.DYNAMIC_DRAW)
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
@@ -275,6 +294,9 @@ func (b *Backend) NewImmutableBuffer(typ backend.BufferBinding, data []byte) (ba
|
||||
glErr(b.funcs)
|
||||
obj := b.funcs.CreateBuffer()
|
||||
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.immutable = true
|
||||
if err := glErr(b.funcs); err != nil {
|
||||
@@ -291,6 +313,40 @@ func glErr(f *glimpl.Functions) error {
|
||||
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) {
|
||||
if b.state.texUnits[unit] != t {
|
||||
b.funcs.ActiveTexture(glimpl.TEXTURE0 + glimpl.Enum(unit))
|
||||
@@ -433,6 +489,18 @@ func (b *Backend) NewInputLayout(vs backend.ShaderSources, layout []backend.Inpu
|
||||
}, 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) {
|
||||
attr := make([]string, len(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}
|
||||
}
|
||||
|
||||
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) {
|
||||
p.vertUniforms.setBuffer(buffer)
|
||||
}
|
||||
@@ -600,10 +676,31 @@ func (b *gpuBuffer) Upload(data []byte) {
|
||||
if b.hasBuffer {
|
||||
firstBinding := firstBufferType(b.typ)
|
||||
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() {
|
||||
if b.hasBuffer {
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
glErr(f.backend.funcs)
|
||||
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")
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
func (t *gpuTexture) Upload(img *image.RGBA) {
|
||||
t.backend.BindTexture(0, t)
|
||||
var pixels []byte
|
||||
b := img.Bounds()
|
||||
w, h := b.Dx(), b.Dy()
|
||||
if img.Stride != w*4 {
|
||||
panic("unsupported stride")
|
||||
func (t *gpuTexture) Upload(offset, size image.Point, pixels []byte) {
|
||||
if min := size.X * size.Y * 4; min > len(pixels) {
|
||||
panic(fmt.Errorf("size %d larger than data %d", min, len(pixels)))
|
||||
}
|
||||
start := (b.Min.X + b.Min.Y*w) * 4
|
||||
end := (b.Max.X + (b.Max.Y-1)*w) * 4
|
||||
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)
|
||||
t.backend.BindTexture(0, t)
|
||||
t.backend.funcs.TexSubImage2D(glimpl.TEXTURE_2D, 0, offset.X, offset.Y, size.X, size.Y, t.triple.format, t.triple.typ, pixels)
|
||||
}
|
||||
|
||||
func (t *gpuTimer) Begin() {
|
||||
@@ -792,7 +893,7 @@ func floatTripleFor(f *glimpl.Functions, ver [2]int, exts []string) (textureTrip
|
||||
var attempts []string
|
||||
for _, tt := range triples {
|
||||
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)
|
||||
st := f.CheckFramebufferStatus(glimpl.FRAMEBUFFER)
|
||||
if st == glimpl.FRAMEBUFFER_COMPLETE {
|
||||
@@ -815,7 +916,7 @@ func srgbaTripleFor(ver [2]int, exts []string) (textureTriple, error) {
|
||||
}
|
||||
|
||||
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 {
|
||||
// R8, RED not supported on OpenGL ES 2.0.
|
||||
intf, f = glimpl.LUMINANCE, glimpl.Enum(glimpl.LUMINANCE)
|
||||
@@ -840,6 +941,8 @@ func firstBufferType(typ backend.BufferBinding) glimpl.Enum {
|
||||
return glimpl.ARRAY_BUFFER
|
||||
case typ&backend.BufferBindingUniforms != 0:
|
||||
return glimpl.UNIFORM_BUFFER
|
||||
case typ&backend.BufferBindingShaderStorage != 0:
|
||||
return glimpl.SHADER_STORAGE_BUFFER
|
||||
default:
|
||||
panic("unsupported buffer type")
|
||||
}
|
||||
|
||||
+1
-1
@@ -479,7 +479,7 @@ func (r *renderer) texHandle(cache *resourceCache, data imageOpData) backend.Tex
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
handle.Upload(data.src)
|
||||
backend.UploadImage(handle, image.Pt(0, 0), data.src)
|
||||
tex.tex = handle
|
||||
return tex.tex
|
||||
}
|
||||
|
||||
+22
-2
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user