Skip to content
This repository has been archived by the owner on May 9, 2018. It is now read-only.

Buffer binding #35

Merged
merged 12 commits into from
Nov 13, 2017
Merged

Buffer binding #35

merged 12 commits into from
Nov 13, 2017

Conversation

davepagurek
Copy link
Member

@davepagurek davepagurek commented Nov 12, 2017

screen shot 2017-11-12 at 10 41 22 pm

@@ -1,11 +1,149 @@
import Shader from './shader';
import Qualifier from './qualifier';
import Set from './util/set';
import InterfaceVariable from './interface';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: could you do these imports alphabetically, please? (just a convention I like)

Copy link
Member

@abhimadan abhimadan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of my comments refer to #36, in case that gets merged first. I don't mind either way, but we should talk about how to resolve the merge conflicts beforehand, since both PRs are pretty large.

src/interface.ts Outdated
@@ -23,4 +23,20 @@ export default class InterfaceVariable implements Hashable {
public hashCode(): string {
return this.declaration();
}

public wrapAttributeValue(value: any[]): any {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you rename wrapAttributeValue to something more descriptive, like wrapAttributeBufferInTypedArray? It took a while to figure out what this was actually doing.

src/shader.ts Outdated
@@ -22,18 +22,21 @@ export default class Shader {
.join('\n');
}

public inputs(): Set<Variable> {
public inputs(): Set<InterfaceVariable> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my pending PR for adding local variables, I remove dependencies and just use inputs() and outputs() to get VariableSources (just the variable name and type). There are other fields inputDecls and outputDecls which contain VariableDeclaration[]s to use in code generation. If I submit first, you can change these to inputVars() and outputVars() and use them the way you are now (but you would need to cast to get back that they're InterfaceVariables, so maybe there should be InterfaceVariableDeclaration and LocalVariableDeclaration nodes?)

this.attributeBuffers = new Map();
this.uniformPositions = new Map();
this.inputs = new Map();
[...vertexShader.inputs().union(fragmentShader.inputs())].forEach(input => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we expect there to be common inputs between vertex and fragment shaders? I think fragment shader inputs come from vertex shader outputs. We don't bind buffers for those inputs.

Copy link
Member Author

@davepagurek davepagurek Nov 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only does stuff for uniforms, which you get for both, and attributes, which should only be inputs for the vertex shader (but we don't check that), and currently ignores in and out variables. Haven't thought too much yet about those but there aren't buffers being made for them anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, that makes sense. Although I still don't understand the purpose of the inputs map, which takes inputs from both the fragment and vertex shader, and doesn't check whether or not those inputs are attributes. If you're only using it for attribute variables, can you
a) just get inputs from the vertex shader, and
b) filter by qualifier so that you only add attributes to the map?

this.createBuffers();
}

public setAttribute(input: string, value: any[], usage: GLenum = this.gl.STATIC_DRAW) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems awkward to key input interface variables by their declaration string. Why can't we just iterate over the set of inputs?

Also, can we change the signature of this to take all input variables, and all buffers? Maybe something like this:

public setAttributes(inputVars: InterfaceVariable[], buffer: any[], usage: GLenum);

If we do this, we can figure out the stride and offset for each attribute.

Copy link
Member Author

@davepagurek davepagurek Nov 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the end user to bind a value to a variable, which they may not want to do all at once, e.g. shader.bindAttribute('position', [1, -1, 0, ... ]). From the user's perspective, they'd be naming their variables by strings anyway, so wouldn't it be weird to make them pass in an object as a key?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the map was keyed by declaration for some reason, which is why I thought it was awkward. I'm okay with just variable names, because as you said, they're naming these variables with strings anyway.

Can we also support binding for multiple attributes at once (taking a string[] instead of InterfaceVariable[])? Binding separately in this way with multiple buffers will be less performant than interleaving the data if we want multiple attributes, so it's good to at least leave the option open.

Also, FWIW, I think we need to think more carefully about what buffer-related work we want users to do outside of our library. Right now, they have to gather each attribute's data in separate buffers, which is simple on their end, but leads to inefficient GPU cache use. On the other hand, they gather every attribute's data in a single buffer and pass it in to avoid cache problems, but this might be too restrictive to use. However, I'm fine with your current approach, and I'll make a separate issue for this.

this.gl.enableVertexAttribArray(position);
}

// TODO: support variadic args
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, why do we want variadic args?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to, but there are the non-v versions of all the uniform functions that maybe people want to call directly instead of wrapping in an array, so our call might mirror that. Definitely not a key feature or anything, just something that we might consider doing in the name of not limiting the library's usage

@@ -15,13 +17,13 @@ export default class ShaderPipelineBuilder {

// Vertex shader outputs must be a superset of fragment shader inputs.
// Might want to enforce equality (need to check the standard), but for now, this should be sufficient.
const inVars = this.fragmentShader.inputs();
const outVars = this.vertexShader.outputs();
const inVars = new Set<Variable>([...this.fragmentShader.inputs()].map(v => v.variable));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My pending PR will redefine inputs and outputs to return what you want here, so you won't need a map.

src/type.ts Outdated
@@ -31,4 +31,85 @@ export default class Type {

return true;
}

public wrapAttributeValue(value: any[]): any {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above: can you rename to wrapAttributeBufferInTypedArray?

.filter(input => input.variable.qualifier == Qualifier.Attribute)
.forEach(input => this.attributes.set(input.variable.name(), input.variable));
this.uniforms = new Set(
[...vertexShader.inputDecls]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implies we're going to expect users to pass in uniforms to the inputs parameter in a Shader constructor. Would it be better to have a separate uniforms constructor parameter? Shader inputs and uniforms are used for different purposes (vertex/fragment-specific vs static for entire pipeline), so it could be less confusing to split them at the Shader level.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to think about this more in another PR I think

@davepagurek
Copy link
Member Author

davepagurek commented Nov 13, 2017

Ok so changes I made:

  • It's no longer just the vertex shader's inputs. The fragment shader can reference uniforms that the vertex shader doesn't because the vertex shader might not care about them. The uniforms can maybe be a separate section in the shader but I'm going to leave that until later.
  • Matrices multiplied by vectors is allowed, but throws an error right now, so I commented out the error and those tests until we fix.
  • Added code to build samples for a browser
  • Have to specify float precision in shaders. TODO: allow this to change.

Copy link
Member

@armcburney armcburney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@@ -8,6 +8,7 @@ export default class EqualAssignment extends AssignmentExpression {
}

public source(): string {
console.log(this);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this console.log?

@davepagurek davepagurek merged commit 85aed02 into master Nov 13, 2017
@davepagurek davepagurek deleted the buffer-binding branch November 13, 2017 14:20
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants