C
C#2y ago
frostfina

❔ Generic method that takes in a struct and calls the correctly-typed method

I'm working with OpenTK (an OpenGL binding) and I'd like to create a method that allows setting uniforms (basically variables inside of a shader). The solution I've come up with is the following. For context, Matrix4 is a struct. This method is part of my Shader class, in which I'm trying to abstract the native types.
public void SetUniform<T>(string name, T value) where T : struct
{
if (typeof(T) == typeof(Matrix4))
{
GL.UniformMatrix4(_uniforms[name], false, (Matrix4)value);
}
}
public void SetUniform<T>(string name, T value) where T : struct
{
if (typeof(T) == typeof(Matrix4))
{
GL.UniformMatrix4(_uniforms[name], false, (Matrix4)value);
}
}
The cast (Matrix4)value doesn't work though. I wrote it like this so that I can write a single method to set any type of uniform value, here the only implemented one is Matrix4. My question is : Is there a way to make this work, or do I have to write a method for each type of argument? If that's a bad solution, what would be a good one? (Alternatively, I could abstract uniforms further with an Uniform class so I'm not directly working with the native types in my shader abstraction, but that would also require adding an abstraction for the uniform use cases.)
11 Replies
Thinker
Thinker2y ago
If you want to use this approach then you could use if (value is Matrix4 matrix4) instead of typeof(T) == typeof(Matrix4) Otherwise, if you want different cases for different types, then personally I'd just have an overload for each type
frostfina
frostfinaOP2y ago
It still complains that cannot convert from 'ref T' to 'ref OpenTK.Mathematics.Matrix4'. I think I'll go with the overload approach though, somehow it didn't cross my mind. Thank you :)
TheRanger
TheRanger2y ago
well first you need to put ref on the argument try
public void SetUniform<T>(string name, T value) where T : struct
{
if (value is Matrix4 matrix4)
{
GL.UniformMatrix4(_uniforms[name], false, ref matrix4);
}
}
public void SetUniform<T>(string name, T value) where T : struct
{
if (value is Matrix4 matrix4)
{
GL.UniformMatrix4(_uniforms[name], false, ref matrix4);
}
}
frostfina
frostfinaOP2y ago
That I did, that's what caused the error I sent
TheRanger
TheRanger2y ago
tested it with an int and it works
frostfina
frostfinaOP2y ago
Mhh, weird Ah wait I didn't set the if like you though, that was the problem Thanks
Anton
Anton2y ago
you should use Unsafe.As here ah nvm if the value were passed by ref, then you would use that
nukleer bomb
nukleer bomb2y ago
This boxes the value. I would not except my value to be boxed when just calling OpenGL API
Anton
Anton2y ago
it actually doesn't box it it shouldn't at least it's treated as a static brach by the jit
nukleer bomb
nukleer bomb2y ago
Yeah you're right
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server