What do double square brackets around "position" mean in the Metal language? - syntax

What does float4 position [[position]]; do in the following snippet?
#include <metal_stdlib>
using namespace metal;
struct Vertex
{
float4 position [[position]];
float4 color;
};
vertex Vertex vertex_main(device Vertex *vertices [[buffer(0)]], uint vid [[vertex_id]])
{
return vertices[vid];
}
I am confused by the [[position]] part and similar usage in the function definition especially.

The Metal Shading Language is documented at https://developer.apple.com/metal/metal-shading-language-specification.pdf
In particular look at "Table 9" on page 68 of that document. There [[position]] is identified as an attribute qualifier for the return type of a Vertex Function. I assume that means that when your vertex shader returns the caller will use the values in that part of the struct to determine the positions of the vertices the shader would like to modify.

I don't have enough reputation to respond to your comment regarding the name of the brackets, but the [[]] brackets are attribute syntax taken from C++11.

Metal is based on C++ and the this is just the syntax of attributes in C++11. See this for more details about the grammar.

Related

Can I make a GLSL struct have std140 layout?

I just tried to do this
C++
struct PointLight
{
glm::vec4 position;
glm::vec4 colour;
};
std::vector <PointLight> lights_array;
GLSL 320 ES:
layout (std140) struct PointLight
{
vec4 position;
vec4 colour;
};
layout (std140) buffer Lights
{
int count;
PointLight data [];
}
b_lights;
The compile error surprised me:
error C7600: no value specified for layout qualifier 'std140'
I can't find a straight answer but I get the impression that I can't specify std140 for struct definitions. Is this so? Or how can I spell it?
If not, then how am I able to guarantee that I can send lights_array to glBufferData so that it has the correct layout in the shader's b_lights.data array?
In other words, why is std140 required for the buffer but not for the struct?
Interface blocks have layouts, not structs. The layout applies to how the block lays out its elements, recursively, through their entire contents.
So you don't need to apply an interface block layout to a random struct.

Shader inputs to registers mapping

I have a compiled pixel shader 4.0 (I don’t have source code for that), with the following in the input signature:
// Name Index Mask Register
// TEXCOORD 4 xyz 4
// TEXCOORD 8 w 4
There’re are other input slots, I’ve only pasted the interesting lines of the signature.
As you see, the signature says both TEXCOORD4 and TEXCOORD8 input values go to v4 input register, the former one to xyz fields, the latter one to w field.
MSDN says the type of TEXCOORD[n] input is float4.
Which component of TEXCOORD8 input value goes to the v4.w field, x or w?
I don't think that mapping is specific to a particular component - the HLSL compiler is just attempting to map the inputs to a more efficient layout. I'm fairly certain the input signature for the shader is going to look something like:
float4 myPixelShader(float3 input_f3 : TEXCOORD4, float input_scalar : TEXCOORD8)
{
// ...
}
so if you're looking to create a vertex shader that outputs to this particular shader, you could just mirror that layout in your output, so something like:
struct MyInterpolants
{
float3 something : TEXCOORD4;
float something_scalar : TEXCOORD8;
}
MyInterpolants MyVertexShader(...)
{
MyInterpolants o;
float3 calc;
float4 some_var;
// Some code here that does something and fills elements of some_var and calc
o.something = calc;
o.something_scalar = some_var.z;
return o;
}
should map just fine. It doesn't really matter which element of a local variable is mapped to that output, as long as you're passing a scalar and the signatures between the pixel shader input and vertex shader outputs match. So you could pass x, y, z or w to that scalar output and it'll work out the same.

What are the valid types for a WebGL vertex shader attribute?

The following attribute seems fine:
attribute vec4 coord;
The following attribute complains that an attribute "cannot be bool or int":
attribute int ty;
The following attribute complains of a "syntax error":
attribute uint ty;
These results seem quite arbitrary. I can't find a list of the valid types for vertex shader attributes. What are the rules for whether an attribute type is valid in WebGL?
OpenGL ES Shading Language 1.00 specification, page 36, section 4.3.3: "Attribute":
The attribute qualifier is used to declare variables that are passed to a vertex shader from OpenGL ES on a per-vertex basis. It is an error to declare an attribute variable in any type of shader other than a vertex shader. Attribute variables are read-only as far as the vertex shader is concerned. Values for attribute variables are passed to a vertex shader through the OpenGL ES vertex API or as part of a vertex array. They convey vertex attributes to the vertex shader and are expected to change on every vertex shader run. The attribute qualifier can be used only with the data types float, vec2, vec3, vec4, mat2, mat3, and mat4. Attribute variables cannot be declared as arrays or structures.

Can you use glVertexAttribPointer to assign a smaller vector to a larger one?

From section 5.8 of The OpenGL® ES Shading Language (v1.00, r17) [PDF] (emphasis mine):
The assignment operator stores the value of the rvalue-expression into the l-value and returns an r-value with the type and precision of the lvalue-expression. The lvalue-expression and rvalue-expression must have the same type. All desired type-conversions must be specified explicitly via a constructor.
So it sounds like doing something like this would not be legal:
vec3 my_vec3 = vec3(1, 2, 3);
vec4 my_vec4 = my_vec3;
And to make it legal the second line would have to be something like:
vec4 my_vec4 = vec4(my_vec3, 1); // add 4th component
I assumed that glVertexAttribPointer had similar requirements. That is, if you were assigning to a vec4 that the size parameter would have to be equal to 4.
Then I came across the GLES20TriangleRenderer sample for Android. Some relevant snippets:
attribute vec4 aPosition;
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
So aPosition is a vec4, but the call to glVertexAttribPointer that's used to set it has a size of 3. Is this code correct, is GLES20TriangleRenderer relying on unspecified behavior, or is there something else I'm missing?
The size of the attribute data passed to the shader does not have to match the size of the attribute in that shader. You can pass 2 values (from glVertexAttribPointer) to an attribute defined as a vec4; the leftover two values are zero, except for the W component which is 1. And similarly, you can pass 4 values to a vec2 attribute; the extra values are discarded.
So you can mix and match vertex attributes with uploaded values all you want.

Attribute Parameter in Vertex shader

I am doing work on Opengl-es 2.0 in ubuntu 10.10 with pvrsdk .
In my code i am taking the vertices of triangle to render but when i have to use the Attribute parameter in vertex shader . how does it change
I see that in examples they are using myVertex . what is meant by that.
like this:
const char* pszVertShader = "\
attribute highp vec4 myVertex;\
uniform mediump mat4 projmatrix;\
invariant gl_Position;\
void main(void)\
{\
gl_Position = projmatrix * myVertex;\
}";
===============================render======================
glBindAttribLocation(uiProgramObject, VERTEX_ARRAY, "myVertex");
So i just wanna know that I am taking vertices from text file will it affect the myVertex attribute.
if you need another information I can provide you and I have already posted my whole code in previous question here
OpenGL 3/OpenGL-ES 2 are abandoned the concept of predefined vertex attributes "position", "normal", "texcoord", …, that are supplied through glVertexPointer, glNormalPointer, glTexCoordPointer, …
Instead in your shaders you introduce custom varyings/in attribute identifiers. Those identifiers are referred to by a so called attribute location, a numeric index. glBindAttribLocation allows one to assign attribute identifiers to specific locations. In the case of above code fragment there seems to exists a global constant VERTEX_ARRAY – introduced by the program code(!), i.e. not predefined by OpenGL or something like that – that is universally used for the myVertex varying/in attribute in the shader.
So that particular vertex attribute can be supplied with data by glVertexAttribPointer through a common token VERTEX_ARRAY in a statement similar to this:
glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, false, 0, isVBO ? (char*)vertex.offset : (char*)vertex.data + vertex.offset);
Of course the exact semantics of the glVertexAttribPointer calls depends on the particular program that does them.
Instead of a (global) constant VERTEX_ARRAY you could as well use a variable shader.attrib.vertex, which you set per shader using
shader.attrib.vertex = glGetAttribLocation(shader.program_object, "myVertex");
and use that variable in the calls to glVertexAttribPointer
glVertexAttribPointer(shader.attrib.vertex, …)

Resources