KhronosGroup / KhronosGroup/GLSL

Operator overloading

Open
#107 8 comments 11 reactions 0 assignees View on GitHub
Enhancement OpenGL OpenGL ES
Dominant language
JavaScript
Stars
458
Forks
114
Avg merge
4m
Merged PRs (30d)
1

Description

Right now it is extremely tedious to create abstracted custom types in GLSL. To do so we must resort to add() mul() etc.. functions, and we can't even create additional min() max() and normalize() functions for our types with out compilation errors. Some pretty stark common cases are [dual and quad floats/doubles](http://andrewthall.org/papers/df64_qf128.pdf), complex numbers, and quaternions. I can sort of create "libraries" for others to use via [shaderc](https://github.com/google/shaderc) with include directives, but any types I make will always be inconsistent and appear second class citizens to arithmetic primitives in the language, often resulting in people just choosing to use vec2's for complex numbers since it is easier in many cases.

One way to alleviate this issue would be to introduce syntax to overload operators. These would include:

* arithmetic operators (+,-,[],%,etc...)
* type conversion operators (vec2(mytype) etc...)
* built in functions, like min, max, normalize etc..

Some operators and functions may need to be excluded, but if most arithmetic operators could be overloaded it would start to make large scale GLSL programs a whole heck of a lot more manageable.

I'm going to strawman the syntax but essentially I would imagine it could look like this:

```
//conversion overload
struct Quaternion{
float x;
float y;
float z;
float w;
};

@operator Quaternion(const in vec4 value){
return Quaternion(value.x, value.y, value.z, value.w);
}

@operator vec4(const in Quaternion quat){
return vec4(quat.x, quat.y, quat.z, quat.w);
}
//explicit conversion
Quaternion quat = Quaternion(vec4 (1.0, 0.0, 0.0, 0.0));
vec4 vector = vec4(quat);

//builtin overload

Quaternion @operator normalize(const in Quaternion quat){
//converted because of aforementioned conversion operator
return Quaternion(normalize(vec4(quat)));
}

Quaternion quat1 = normalize(quat);

// arithmetic overload
//note ideally would not be restricted to same type
Quaternion @operator*(Quaternion a, Quaternion b) {
return Quaternion(
a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w
);
}

Quaternion quat2 = quat * quat1;

```

Note I'm not sure if implicit conversions are desirable or feasible. Implicit conversions are not really important to the proposal

Doing this would make GLSL code a whole lot easier to manage, code for complex numbers and multi floats that is the same as normal scalar code could simply be dropped right in, only type signatures need to be changed, and reduce cognitive load on developers. The fact that overloading at all exists in GLSL is itself precedent IMO.

This should be backward compatible with currently working code, if appropriate operator overload markers are chosen, currently working functions should all be fine, the only thing that changes is new code that couldn't exist before. There shouldn't be parsing ambiguity on the operators themselves, for example, with the strawman syntax, the @ symbol shouldn't conflict with any other declaration in the language AFAIK, and could match for @operator entirely (so it just becomes a keyword), then know that an identifier, bultin, or symbolic operator must follow next, semantic checking later identifiers by a check that it matches a predefined struct or primitive name. Currently I have the conversion operator as a special case (no return), since I was basing my strawman off of C++'s syntax, but if it helps parsing, I see no reason why we can't just have the return value for conversions as well, and it may help in identifying them.

example:
```
Quaternion @operator Quaternion(const in vec4 value){
return Quaternion(value.x, value.y, value.z, value.w);
}
```

I am unsure how GLSL internally manages builtins, theoretically custom ones should just be handled like functions at some point during compilation, so if there is going to be any issues, I would expect it to happen there.

Contributor guide

Open the contributing guide

Research direction

No repository files, tests, or implementation entry points are identified. Start by reviewing the GLSL specification and the proposed operator, conversion, and built-in overloading cases, then determine the agreed scope and compatibility requirements. Done means an approved design and implementation plan, with relevant parsing and semantic-checking tests identified.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.