using System.Collections.Immutable; using System.Security.Cryptography.X509Certificates; using Dashboard.Drawing; using OpenTK.Graphics.OpenGL; namespace Dashboard.OpenGL.Drawing { public class GLShader : IShader { public GLDeviceContext Context { get; } public int Handle { get; } public ImmutableList Attributes { get; } public ImmutableList Uniforms { get; } public ImmutableList Blocks { get; } public ImmutableList Textures { get; } public GLShader(GLDeviceContext context, int handle) { Context = context; Handle = handle; List list = new List(); List list2 = new List(); int count = GL.GetProgrami(handle, ProgramProperty.ActiveAttributes); for (int i = 0; i < count; i++) { list.Add(GetAttribute(handle, i)); } Attributes = list.ToImmutableList(); list.Clear(); count = GL.GetProgrami(handle, ProgramProperty.ActiveUniforms); for (int i = 0; i < count; i++) { var property = GetUniform(handle, i, out bool isSampler); list.Add(property); if (isSampler) list2.Add(property); } Uniforms = list.ToImmutableList(); Textures = list2.ToImmutableList(); list.Clear(); count = GL.GetProgrami(handle, ProgramProperty.ActiveUniformBlocks); for (int i = 0; i < count; i++) { var property = GetBlock(handle, i); list.Add(property); } Blocks = list.ToImmutableList(); } private static ShaderMappingProperty GetAttribute(int program, int index) { string name = GL.GetActiveAttrib(program, (uint)index, 260, out _, out _, out _); int location = GL.GetAttribLocation(program, name); return new ShaderMappingProperty(name, location); } private static ShaderMappingProperty GetUniform(int program, int index, out bool isSampler) { string name = GL.GetActiveUniform(program, (uint)index, 260, out _, out _, out OpenTK.Graphics.OpenGL.UniformType type); int location = GL.GetUniformLocation(program, name); isSampler = type switch { OpenTK.Graphics.OpenGL.UniformType.Sampler1D or OpenTK.Graphics.OpenGL.UniformType.Sampler1DArray or OpenTK.Graphics.OpenGL.UniformType.Sampler1DShadow or OpenTK.Graphics.OpenGL.UniformType.Sampler1DArrayShadow or OpenTK.Graphics.OpenGL.UniformType.IntSampler1D or OpenTK.Graphics.OpenGL.UniformType.IntSampler1DArray or OpenTK.Graphics.OpenGL.UniformType.UnsignedIntSampler1D or OpenTK.Graphics.OpenGL.UniformType.UnsignedIntSampler1DArray or OpenTK.Graphics.OpenGL.UniformType.Sampler2D or OpenTK.Graphics.OpenGL.UniformType.Sampler2DShadow or OpenTK.Graphics.OpenGL.UniformType.Sampler2DRect or OpenTK.Graphics.OpenGL.UniformType.Sampler2DRectShadow or OpenTK.Graphics.OpenGL.UniformType.Sampler2DArray or OpenTK.Graphics.OpenGL.UniformType.Sampler2DArrayShadow or OpenTK.Graphics.OpenGL.UniformType.Sampler2DMultisample or OpenTK.Graphics.OpenGL.UniformType.Sampler2DMultisampleArray or OpenTK.Graphics.OpenGL.UniformType.IntSampler2D or OpenTK.Graphics.OpenGL.UniformType.IntSampler2DRect or OpenTK.Graphics.OpenGL.UniformType.IntSampler2DArray or OpenTK.Graphics.OpenGL.UniformType.IntSampler2DMultisample or OpenTK.Graphics.OpenGL.UniformType.IntSampler2DMultisampleArray or OpenTK.Graphics.OpenGL.UniformType.UnsignedIntSampler2D or OpenTK.Graphics.OpenGL.UniformType.UnsignedIntSampler2DRect or OpenTK.Graphics.OpenGL.UniformType.UnsignedIntSampler2DArray or OpenTK.Graphics.OpenGL.UniformType.UnsignedIntSampler2DMultisample or OpenTK.Graphics.OpenGL.UniformType.UnsignedIntSampler2DMultisampleArray or OpenTK.Graphics.OpenGL.UniformType.Sampler3D or OpenTK.Graphics.OpenGL.UniformType.IntSampler3D or OpenTK.Graphics.OpenGL.UniformType.UnsignedIntSampler3D or OpenTK.Graphics.OpenGL.UniformType.SamplerCube or OpenTK.Graphics.OpenGL.UniformType.SamplerCubeShadow or OpenTK.Graphics.OpenGL.UniformType.SamplerCubeMapArray or OpenTK.Graphics.OpenGL.UniformType.SamplerCubeMapArrayShadow or OpenTK.Graphics.OpenGL.UniformType.IntSamplerCube or OpenTK.Graphics.OpenGL.UniformType.IntSamplerCubeMapArray or OpenTK.Graphics.OpenGL.UniformType.UnsignedIntSamplerCube or OpenTK.Graphics.OpenGL.UniformType.UnsignedIntSamplerCubeMapArray => true, _ => false, }; return new ShaderMappingProperty(name, location); } private static ShaderMappingProperty GetBlock(int program, int index) { int size = 0; unsafe { GL.GetActiveUniformBlockiv(program, (uint)index, UniformBlockPName.UniformBlockDataSize, &size); } GL.GetActiveUniformBlockName(program, (uint)index, 1024, out _, out string name); return new ShaderMappingProperty(name, index); } public void Dispose() { Context.Collector.DeleteProgram(Handle); } } }