YUYV OpenGL Fragment Shader I made a shader to display a YUYV surface (data arranged as: Y0 U0 Y1 V0). It's working, but I don't know anything about shaders, or openGL, or anything graphic related as a matter of fact. I feel more like a mad scientist patching random bits of code together than a programmer. Thus, I would appreciate if anyone could look it up and tell me what I could improve, performance-wise, logic-wise or syntax-wise. I also have some questions:


What desktop hardware will that work on? Is there any restriction, or will it work on any  10 years old desktop?
Would that work on an android tablet?
Will any interpolation of pixel be performed, if my rendering surface is the same size as the texture? Is it possible to have interpolation (with some flag, not by implementing it)?


I load my YUYV texture as RGBA texture of width/2 by height. The rest should be self-explanatory:

#version 330 core
uniform sampler2D tex;
uniform mat4 convMat; /* Color conversion matrix */
uniform vec2 dim; /* Width and height of image */
in vec2 UV;
out vec3 color;

void main(){
    vec4 yuv;
    ivec2 iUV = ivec2(UV*dim*vec2(0.5, 1)); /* Absolute coordinate of desired pixel in texture */

    yuv = texelFetch(texy, iUV, 0);
    if (int(UV.x*dim.x) % 2 == 1){
        /* There are 2 Y in a texture RGBA pixel, choose the right one based on absolute pixel coordinate */
        yuv.x = yuv.z;
    };
    yuv.z = yuv.w;
    yuv.w = 1;
    color = (convMat*yuv).rgb;
};
Okay, trying to answer a few of your questions to the best of my knowledge:




  What desktop hardware will that work on? Is there any restriction, or will it work on any 10 years old desktop?


Probably not in a 10yo PC. Your code is currently targeting GLSL version 3.3, which was released circa 2010. You can check a version history here. However, if you need to be backward compatible, there are changes you can make to this code to target older OpenGL versions. I'll mention those at the end.




  Would that work on an android tablet?


No. Android devices use OpenGL-ES, which is a variant of Desktop OpenGL version 2.0. You wouldn't have the texelFetch() function neither integer types in the current OpenGL-ES used by both Android and iOS devices.




  Will any interpolation of pixel be performed, if my rendering surface is the same size as the texture? Is it possible to have interpolation (with some flag, not by implementing it)?


What exactly do you mean by interpolation? By any chance are you talking about texture filtering? By using texelFetch(), you have opted-out of texture filtering. It is not clear to my why you did this however. If you were to switch your texture sampling to a function like texture() (or texture2D if targeting older versions) you would be able to have filtered lookup and also avoid the non-portable texelFetch(). texture()/texture2D() also take the UVs as normalized 0-1 range texture coordinates, so it would make your shader faster too by eliminating the integer conversions.



Backward compatibility: You can make this code backward compatible with older OpenGL version by replacing texelFetch() with texture()/texture2D(), as I've mentioned before. That would also be necessary for current OpenGL-ES compat. You would also have to remove any integer conversions. Older OpenGL and OpenGL-ES hardware can only operate on floating point types! (no int or ivec).

A comment on performance: Branching is still an expensive operation on a lot of graphics hardware out there. So the most obvious improvement here would be to eliminate the conditional if test. You might be able to pull it off using several clever tricks. Maybe the mod function might be of help.