_pdep_u32 in GLSL / HLSL / SPIR-V - opengl

I need to interleave* the bits of three unsigned integers in a GLSL program that will be compiled to SPIR-V.
In C, I would use the intrinsic _pdep_u32 but I can't find something like that in the OpenGL reference. Does it exist with some other name? Alternatively, does it exist in HLSL or in raw SPIR-V?
I am aware that there is a tool for converting LLVM IR to SPIR-V. Is it possible to use it to generate _pdep_u32-equivalent bytecode?
Otherwise, can this behavior be implemented in some other way that is also very fast?
*That is, the bits from the 32-bit integers A, B and C must appear in the order ABCABC...etc

Related

Understanding the Datatypes in OpenGL

The way OpenGL Datatypes are used there confuses me a bit. There is for example the unsigned integer "GLuint" and is is used for shader-objects as well as various different buffers-objects. What is this GLuint and what are these datatypes about?
They are, in general, just aliases for different types. For example GLuint is normally a regular uint. The reason they exist is because the graphics driver expects a specific integer size, e.g. a uint64_t, but data types like int are not necessarily consistent across compilers and architectures.
Thus OpenGL provides it's own type aliases to ensure that handles are always exactly the size it needs to function properly.

Prefixing hex value with 0x

I'm querying a GL_TYPE in OpenGL and it's reporting back the hexadecimal value as an integer, as it should.
For example: 0x1406 is #define'd as GL_FLOAT but is being given to me from OpenGL in integer form as 5126.
Unfortunately OpenGL doesn't just return the type and it also doesn't just accept the integer (read: hex) value back. It apparently needs it to be prefixed with 0x before being used.
I'm trying to save myself a switch/case and instead cast/convert on the fly but I don't see another way. Do I have any other options? No boost please.
It's unclear what sort of "conversion" you have in mind: 0x1406 equals 5126. They're just different ways of writing the same number in source code, and the compiler translates them both into the binary form that's used at runtime.
You should be able to just use the == operator to compare the result of glGetProgramResource against a constant like GL_FLOAT, regardless of whether that constant is defined as 0x1406 or 5126 in the source code.

Underlying implementation of normalize() and length() in GLSL

What is the underlying implementation of normalize() and length() in GLSL? I am trying to gauge the performance of my code and what to know what instructions are being executed for certain built in functions in GLSL. Where can I get more information on the underlying implementation of other built in functions?
The OpenGL Shading Language spec generally doesn't require a particular implementation of its functions, as long as they give the results it specifies. In GLSL 4.5, for example, see the correctness requirements on page 84, and the functions length() and normalize() on page 150.
Moreover, GLSL doesn't define a binary format for compiled shader code; that format is accordingly implementation dependent.
However, in general, I presume the length function would be implemented using a dot product and a square root, and the normalize function would be implemented by calling the length function and also doing three divisions, or one division and a vector multiplication.
The answer is wildly GPU/vendor dependent ; but it may give you a clue to look at the output provided by AMD Shader Analyser or take a peek into 'binary' dumps of compiled shaders on NVidia - last time I checked (long time ago), they were containing assembly code in text form.

Ensuring OpenGL compatible types in c++

OpenGL buffer objects support various data types of well defined width (GL_FLOAT is 32 bit, GL_HALF_FLOAT is 16 bit, GL_INT is 32 bit ...)
How would one go about ensuring cross platform and futureproof types for OpenGL?
For example, feeding float data from a c++ array to to a buffer object and saying its type is GL_FLOAT will not work on platforms where float isn't 32 bit.
While doing some research on this, I noticed a subtle but interesting change in how these types are defined in the GL specs. The change happened between OpenGL 4.1 and 4.2.
Up to OpenGL 4.1, the table that lists the data types (Table 2.2 in the recent spec documents) has the header Minimum Bit Width for the size column, and the table caption says (emphasis added by me):
GL types are not C types. Thus, for example, GL type int is referred to as GLint outside this document, and is not necessarily equivalent to the C type int. An implementation may use more bits than the number indicated in the table to represent a GL type. Correct interpretation of integer values outside the minimum range is not required, however.
Starting with the OpenGL 4.2 spec, the table header changes to Bit Width, and the table caption to:
GL types are not C types. Thus, for example, GL type int is referred to as GLint outside this document, and is not necessarily equivalent to the C type int. An implementation must use exactly the number of bits indicated in the table to represent a GL type.
This influenced the answer to the question. If you go with the latest definition, you can use standard sized type definitions instead of the GL types in your code, and safely assume that they match. For example, you can use int32_t from <cstdint> instead of GLint.
Using the GL types is still the most straightforward solution. Depending on your code architecture and preferences, it might be undesirable, though. If you like to divide your software into components, and want to have OpenGL rendering isolated in a single component while providing a certain level of abstraction, you probably don't want to use GL types all over your code. Yet, once the data reaches the rendering code, it has to match the corresponding GL types.
As a typical example, say you have computational code that produces data you want to render. You may not want to have GLfloat types all over your computational code, because it can be used independent of OpenGL. Yet, once you're ready to display the result of the computation, and want to drop the data into a VBO for OpenGL rendering, the type has to be the same as GLfloat.
There are various approaches you can use. One is what I mentioned above, using sized types from standard C++ header files in your non-rendering code. Similarly, you can define your own typedefs that match the types used by OpenGL. Or, less desirable for performance reasons, you can convert the data where necessary, possibly based on comparing the sizeof() values between the incoming types and the GL types.

why gl_VertexID is not an unsigned int?

I am in the process of designing a shader program that makes use of the built-in variable gl_VertexID:
gl_VertexID — contains the index of the current vertex
The variable is defined as a signed int. Why it is not an unsigned int? What happens when it is used with very large arrays (e.g. a 2^30 long array)?
Does GLSL treat it as an unsigned int?
I want to use its content as an output of my shader (e.g writing it into an output FBO buffer) I will read its content using glReadPixels with GL_RED_INTEGER as format and either GL_INT or GL_UNSIGNED_INT as type.
Which one is correct?
If I use GL_INT I will not be able to address very large arrays.
In order to use GL_UNSIGNED_INT I might cast the generated gl_VertexID to a uint inside my shader but again, how to access long array?
Most likely historical reasons. gl_VertexID was first defined as part of the EXT_gpu_shader4 extension. This extension is defined based on OpenGL 2.0:
This extension is written against the OpenGL 2.0 specification and version 1.10.59 of the OpenGL Shading Language specification.
GLSL did not yet support unsigned types at the time. They were not introduced until OpenGL 3.0.
I cannot tell if OpenGL might treat the vertex id as unsigned int, but you could most likely create your own (full 32-bit) ID. I have done this some time ago by specifying a rgba8888 vertex color attribute which is converted to an id in the shader by bit-shifting the r,g,b, and a components.
Doing this i also noticed that this wasn't anyhow slower than using gl_VertexID, which seemed to introduce some overhead. Nowadays just use an unsigned int attribute.
Also, i wonder, why would you want to read back the gl_VertexID?
(i did this once for an algorithm and it turned out to be not thought through and now has been replaced by sth more efficient ;) )