Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/mobile/gl: Suggestions/questions that arose while adding WebGL backend. #10218

Closed
dmitshur opened this issue Mar 23, 2015 · 8 comments
Closed

Comments

@dmitshur
Copy link
Contributor

Hi @crawshaw,

Based on your proposal in google/gxui#49 (comment) to try adding a WebGL backend to x/mobile/gl, I've been playing on a branch with making that happen.

Overall, it's going really well, and most things were a natural fit. I got it to work rendering a basic triangle with these imports:

package main

import (
    "encoding/binary"
    "errors"
    "fmt"

    "github.com/go-gl/mathgl/mgl32"
    glfw "github.com/shurcooL/goglfw"
    "golang.org/x/mobile/f32"
    "golang.org/x/mobile/gl"
)

image

Along the way, I found some issues with the existing interface of x/mobile/gl and I was wondering what your thoughts on making changes are.

First, a summary of my proposed changes, and below is a detailed rationale:

BufferData(target, usage, src) -> BufferData(target, src, usage)

GenBuffer -> CreateBuffer
GenFramebuffer -> CreateFramebuffer
GenRenderbuffer -> CreateRenderbuffer
GenTexture -> CreateTexture

// Maybe?
GetShaderi -> GetShaderParameteri
GetProgrami -> GetProgramParameteri

// Even more maybe?
+func GetShaderParameterb(s Shader, pname Enum) bool
+func GetProgramParameterb(p Program, pname Enum) bool

1. func BufferData(target Enum, usage Enum, src []byte) parameter order.

The order of usage and src seems to be swapped compared to OpenGL ES spec:

http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferData.xhtml

void glBufferData(GLenum target,
                  GLsizeiptr size,
                  const GLvoid * data,
                  GLenum usage);

It is also swapped compared to WebGL spec:

void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
void bufferData(GLenum target, ArrayBufferView data, GLenum usage);
void bufferData(GLenum target, ArrayBuffer? data, GLenum usage);

Notably, usage should come last.

I suggest swapping the order:

func BufferData(target Enum, src []byte, usage Enum)

2. When need to invent new names, consider WebGL names instead of own.

The x/mobile/gl package offers a higher level API that slightly deviates from the OpenGL ES spec. It comes up with new function names in a few cases where no equivalent func exists in OpenGL ES spec. For example:

http://www.khronos.org/opengles/sdk/docs/man3/html/glGenBuffers.xhtml

void glGenBuffers(GLsizei n, GLuint * buffers)

func GenBuffer() Buffer

glGenBuffer always creates a single buffer, while the OpenGL ES spec's glGenBuffers takes a parameter n.

WebGL spec does not have glGenBuffers either, but instead it provides:

WebGLBuffer? createBuffer();

Which is exactly the same signature, just different name. I suggest using func CreateBuffer() Buffer to match WebGL spec name.

It is more consistent with other OpenGL names like glCreateProgram and glCreateShader.

Similarly:

GenFramebuffer -> CreateFramebuffer
GenRenderbuffer -> CreateRenderbuffer
GenTexture -> CreateTexture

Another such case is something I'm less sure about, but I'll mention it.

x/mobile/gl has GetShaderi and GetProgrami. Those do not exist in OpenGL ES, it only has the GetShaderiv and GetProgramiv variants that accept multiple entries and use pointers.

WebGL does not have GetShaderiv and GetProgramiv, but instead it has:

any getShaderParameter(WebGLShader? shader, GLenum pname);
any getProgramParameter(WebGLProgram? program, GLenum pname);

Which is the same signature, just different name.

So, if you want to be more consistent with WebGL spec here, I would recommend renaming:

GetShaderi -> GetShaderParameteri
GetProgrami -> GetProgramParameteri

(And possibly offer the boolean variants GetShaderParameterb and GetProgramParameterb...)

Reason why I think it's better to reuse existing WebGL names rather invent own ones is (when signatures match), when inventing own, everyone has to find and learn it. But when reusing WebGL names, people porting/looking at existing WebGL code, which I imagine is a lot of code in the wild, will have an easier time porting/understanding Go code that uses x/mobile/gl package.

Thoughts?

/cc @ajhager @slimsag @neelance

@crawshaw
Copy link
Member

I never decided when to freeze the method signatures of the gl package. It definitely should be frozen by the time Go 1.5 comes out. But I suppose it is still safe to change some, as long as nothing breaks silently.

  • BufferData change looks good.
  • s/Gen/Create/ is OK. Create is a better word.
  • I'm not really interested enough in exactly matching WebGL to change Get{Shader,Program}i to Get{Shader,Program}Parameteri. Seems unnecessarily wordy, and the names are clear enough.

If you'd like to send CLs for the first two, please do. Update any call references to them in the mobile repo please.

@dmitshur
Copy link
Contributor Author

Okay, sounds good, I'll do that. Would you want this CL separately from adding WebGL or is fine to do everything in one?

Another issue I've noticed in the internal glBoolean helper:

func glBoolean(b bool) C.GLboolean {
    if b {
        return 0
    }
    return 1
}

Its logic seems to return the opposite of what it should. Is that unintentional?

If so, I'll fix that too, and probably use the TRUE and FALSE consts.

@crawshaw
Copy link
Member

Separate please. Any idea that's logically separable should be a separate CL.

I don't know what happened to glBoolean. That looks entirely wrong. Strangely, it's used a bunch, so I don't know how anything works.

@dmitshur
Copy link
Contributor Author

I don't know what happened to glBoolean. That looks entirely wrong. Strangely, it's used a bunch, so I don't know how anything works.

Yeah, I was surprised to find that too.

It was causing issues for my existing GL code (that previously worked) when I did gl.VertexAttribPointer and needed to set normalized to true.

@dmitshur
Copy link
Contributor Author

@crawshaw, I've submitted a CL at https://go-review.googlesource.com/8000, please take a look.

@dmitshur
Copy link
Contributor Author

I've found another inconsistency:

func DrawElements(mode, ty Enum, offset, count int)

That parameter order deviates from both OpenGL ES and WebGL specs:

https://www.khronos.org/opengles/sdk/docs/man3/html/glDrawElements.xhtml

Can we change it to have same parameter order?

func DrawElements(mode Enum, count int, ty Enum, offset int)

@crawshaw
Copy link
Member

Go for it.

@dmitshur
Copy link
Contributor Author

Another issue.

Change Request Summary

GetActiveUniform(p Program, u Uniform) -> GetActiveUniform(p Program, index uint)
GetActiveAttrib(p Program, a Attrib) -> GetActiveAttrib(p Program, index uint)

Rationale

Uniforms have concept of a Uniform Location, as well as index. (Something similar, but less clearly defined also applies to attributes.)

The OpenGL ES spec for glGetUniformLocation states the return type is GLint and it represents:

glGetUniformLocation returns an integer that represents the location of a specific uniform variable within a the default uniform block of a program object.

(Emphasis added by me.)

Uniform index type used is similar but not the same, it's GLuint. See, e.g., https://www.khronos.org/opengles/sdk/docs/man3/html/glGetActiveUniform.xhtml.

The WebGL spec defines a named type WebGLUniformLocation to represent Uniform Location, and also uses GLuint for the index.

Consider glGetUniformLocation:

WebGLUniformLocation? getUniformLocation(WebGLProgram? program, DOMString name)

The current equivalent x/mobile/gl API is:

// GetUniformLocation returns the location of uniform variable.
//
// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniformLocation.xhtml
func GetUniformLocation(p Program, name string) Uniform

Which is good (although I would've preferred the name UniformLocation rather than deviating from the spec).

But another func expects an index of the uniform, not Uniform Location as its parameter:

WebGLActiveInfo? getActiveAttrib(WebGLProgram? program, GLuint index);
WebGLActiveInfo? getActiveUniform(WebGLProgram? program, GLuint index);

Yet the x/mobile/gl API expects a Uniform Location type instead of an index:

// GetActiveUniform returns details about an active uniform variable.
//
// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetActiveUniform.xhtml
func GetActiveUniform(p Program, u Uniform) (name string, size int, ty Enum)

This makes GetActiveUniform really awkward to use, because there is no way to get/create the Uniform type.

The typical usage of GetActiveUniform makes sense when the parameter, correctly, is an index:

uniformCount := gl.GetProgrami(program, gl.ACTIVE_UNIFORMS)
for index := 0; index < uniformCount; index++ {
    name, size, ty := gl.GetActiveUniform(program, index)
    ...
}

As things are, I need to try to create a Uniform type by doing gl.Uniform{Value: int32(i)}, which is awkward and not cross-platform compatible.

On desktop both Uniform Location and index are internally just integers, so it can be done, but that's going around the type system instead of using it correctly. The problem is that in WebGL, the Uniform Location is actually a JavaScript Object, while uniform index is an integer, so it can't work. See this answer for relevant info.

I highly recommend following the spec and using the type system correctly here. GetActiveUniform and GetActiveAttrib should accept an index as their 2nd parameter, not location type.

Would that change be amenable to you?

Edit: This also applies to EnableVertexAttribArray, DisableVertexAttribArray, and VertexAttribPointer. They take an index, not location type. Edit 2: Actually, the spec is pretty confusing/inconsistent for attrib location/indicies... It seems they're mixed and match and treated the same. :/ Edit 3: After looking more into it, this does not apply to any of those 3, sorry.

crawshaw pushed a commit to golang/mobile that referenced this issue Mar 30, 2015
Reorder DrawElements arguments to match OpenGL spec order:
    DrawElements(mode, ty, offset, count) -> (mode, count, ty, offset)
GetActiveAttrib, GetActiveUniform are defined by spec to accept
corresponding integer _index_, not location type. Change their
signature to do that:
    GetActiveAttrib(p Program, a Attrib) -> (p Program, index uint32)
    GetActiveUniform(p Program, u Uniform) -> (p Program, index uint32)
Clarify and make documentation, parameter names more clear for Uniform
(uniform location), Attrib (attribute location) types,
EnableVertexAttribArray, DisableVertexAttribArray, GetAttribLocation,
GetUniformLocation funcs.
Resolves golang/go#10218 again.

Change-Id: I5b822235d9485701186a43dae0b9fd898cc6a3d8
Reviewed-on: https://go-review.googlesource.com/8166
Reviewed-by: David Crawshaw <crawshaw@golang.org>
@golang golang locked and limited conversation to collaborators Jun 25, 2016
imWildCat pushed a commit to imWildCat/go-mobile that referenced this issue Apr 10, 2021
Change func names and parameter order to more closely follow OpenGL
ES/WebGL spec.
    BufferData(target, usage, src) -> BufferData(target, src, usage)
    GenBuffer -> CreateBuffer
    GenFramebuffer -> CreateFramebuffer
    GenRenderbuffer -> CreateRenderbuffer
    GenTexture -> CreateTexture
Fix issue where glBoolean helper was returning inverted result.
Make Attrib.String() logic consistent with others (print value, not
struct).
Make internal code of GetUniformLocation the same as GetAttribLocation
and BindAttribLocation for consistency.
Resolves golang/go#10218.

Change-Id: Ib33dfff7c22c4d178b2e6b8d228f80f3c17308a8
Reviewed-on: https://go-review.googlesource.com/8000
Reviewed-by: David Crawshaw <crawshaw@golang.org>
imWildCat pushed a commit to imWildCat/go-mobile that referenced this issue Apr 10, 2021
Reorder DrawElements arguments to match OpenGL spec order:
    DrawElements(mode, ty, offset, count) -> (mode, count, ty, offset)
GetActiveAttrib, GetActiveUniform are defined by spec to accept
corresponding integer _index_, not location type. Change their
signature to do that:
    GetActiveAttrib(p Program, a Attrib) -> (p Program, index uint32)
    GetActiveUniform(p Program, u Uniform) -> (p Program, index uint32)
Clarify and make documentation, parameter names more clear for Uniform
(uniform location), Attrib (attribute location) types,
EnableVertexAttribArray, DisableVertexAttribArray, GetAttribLocation,
GetUniformLocation funcs.
Resolves golang/go#10218 again.

Change-Id: I5b822235d9485701186a43dae0b9fd898cc6a3d8
Reviewed-on: https://go-review.googlesource.com/8166
Reviewed-by: David Crawshaw <crawshaw@golang.org>
imWildCat pushed a commit to imWildCat/go-mobile that referenced this issue Apr 11, 2021
Change func names and parameter order to more closely follow OpenGL
ES/WebGL spec.
    BufferData(target, usage, src) -> BufferData(target, src, usage)
    GenBuffer -> CreateBuffer
    GenFramebuffer -> CreateFramebuffer
    GenRenderbuffer -> CreateRenderbuffer
    GenTexture -> CreateTexture
Fix issue where glBoolean helper was returning inverted result.
Make Attrib.String() logic consistent with others (print value, not
struct).
Make internal code of GetUniformLocation the same as GetAttribLocation
and BindAttribLocation for consistency.
Resolves golang/go#10218.

Change-Id: Ib33dfff7c22c4d178b2e6b8d228f80f3c17308a8
Reviewed-on: https://go-review.googlesource.com/8000
Reviewed-by: David Crawshaw <crawshaw@golang.org>
imWildCat pushed a commit to imWildCat/go-mobile that referenced this issue Apr 11, 2021
Reorder DrawElements arguments to match OpenGL spec order:
    DrawElements(mode, ty, offset, count) -> (mode, count, ty, offset)
GetActiveAttrib, GetActiveUniform are defined by spec to accept
corresponding integer _index_, not location type. Change their
signature to do that:
    GetActiveAttrib(p Program, a Attrib) -> (p Program, index uint32)
    GetActiveUniform(p Program, u Uniform) -> (p Program, index uint32)
Clarify and make documentation, parameter names more clear for Uniform
(uniform location), Attrib (attribute location) types,
EnableVertexAttribArray, DisableVertexAttribArray, GetAttribLocation,
GetUniformLocation funcs.
Resolves golang/go#10218 again.

Change-Id: I5b822235d9485701186a43dae0b9fd898cc6a3d8
Reviewed-on: https://go-review.googlesource.com/8166
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants