1+ // Licensed to the .NET Foundation under one or more agreements.
2+ // The .NET Foundation licenses this file to you under the MIT license.
3+
4+ using System ;
5+ using System . Collections . Generic ;
6+ using System . Diagnostics ;
7+ using System . Runtime . CompilerServices ;
8+
9+ #if GLES
10+ using Silk . NET . OpenGLES ;
11+ #elif GL
12+ using Silk . NET . OpenGL ;
13+ #elif LEGACY
14+ using Silk . NET . OpenGL . Legacy ;
15+ #else
16+
17+ using Silk . NET . OpenGL ;
18+
19+ #endif
20+
21+ #if GL
22+ namespace Silk . NET . OpenGL . Extensions . ImGui
23+ #elif GLES
24+ namespace Silk . NET . OpenGLES . Extensions . ImGui
25+ #elif LEGACY
26+ namespace Silk . NET . OpenGL . Legacy . Extensions . ImGui
27+ #else
28+
29+ namespace Example
30+ #endif
31+ {
32+ internal struct UniformFieldInfo
33+ {
34+ public int Location ;
35+ public string Name ;
36+ public int Size ;
37+ public UniformType Type ;
38+ }
39+
40+ internal class Shader
41+ {
42+ public uint Program { get ; private set ; }
43+ private readonly Dictionary < string , int > _uniformToLocation = new Dictionary < string , int > ( ) ;
44+ private readonly Dictionary < string , int > _attribLocation = new Dictionary < string , int > ( ) ;
45+ private bool _initialized = false ;
46+ private GL _gl ;
47+ private ( ShaderType Type , string Path ) [ ] _files ;
48+
49+ public Shader ( GL gl , string vertexShader , string fragmentShader )
50+ {
51+ _gl = gl ;
52+ _files = new [ ] {
53+ ( ShaderType . VertexShader , vertexShader ) ,
54+ ( ShaderType . FragmentShader , fragmentShader ) ,
55+ } ;
56+ Program = CreateProgram ( _files ) ;
57+ }
58+
59+ public void UseShader ( )
60+ {
61+ _gl . UseProgram ( Program ) ;
62+ }
63+
64+ public void Dispose ( )
65+ {
66+ if ( _initialized )
67+ {
68+ _gl . DeleteProgram ( Program ) ;
69+ _initialized = false ;
70+ }
71+ }
72+
73+ public UniformFieldInfo [ ] GetUniforms ( )
74+ {
75+ _gl . GetProgram ( Program , GLEnum . ActiveUniforms , out var uniformCount ) ;
76+
77+ UniformFieldInfo [ ] uniforms = new UniformFieldInfo [ uniformCount ] ;
78+
79+ for ( int i = 0 ; i < uniformCount ; i ++ )
80+ {
81+ string name = _gl . GetActiveUniform ( Program , ( uint ) i , out int size , out UniformType type ) ;
82+
83+ UniformFieldInfo fieldInfo ;
84+ fieldInfo . Location = GetUniformLocation ( name ) ;
85+ fieldInfo . Name = name ;
86+ fieldInfo . Size = size ;
87+ fieldInfo . Type = type ;
88+
89+ uniforms [ i ] = fieldInfo ;
90+ }
91+
92+ return uniforms ;
93+ }
94+
95+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
96+ public int GetUniformLocation ( string uniform )
97+ {
98+ if ( _uniformToLocation . TryGetValue ( uniform , out int location ) == false )
99+ {
100+ location = _gl . GetUniformLocation ( Program , uniform ) ;
101+ _uniformToLocation . Add ( uniform , location ) ;
102+
103+ if ( location == - 1 )
104+ {
105+ Debug . Print ( $ "The uniform '{ uniform } ' does not exist in the shader!") ;
106+ }
107+ }
108+
109+ return location ;
110+ }
111+
112+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
113+ public int GetAttribLocation ( string attrib )
114+ {
115+ if ( _attribLocation . TryGetValue ( attrib , out int location ) == false )
116+ {
117+ location = _gl . GetAttribLocation ( Program , attrib ) ;
118+ _attribLocation . Add ( attrib , location ) ;
119+
120+ if ( location == - 1 )
121+ {
122+ Debug . Print ( $ "The attrib '{ attrib } ' does not exist in the shader!") ;
123+ }
124+ }
125+
126+ return location ;
127+ }
128+
129+ private uint CreateProgram ( params ( ShaderType Type , string source ) [ ] shaderPaths )
130+ {
131+ var program = _gl . CreateProgram ( ) ;
132+
133+ Span < uint > shaders = stackalloc uint [ shaderPaths . Length ] ;
134+ for ( int i = 0 ; i < shaderPaths . Length ; i ++ )
135+ {
136+ shaders [ i ] = CompileShader ( shaderPaths [ i ] . Type , shaderPaths [ i ] . source ) ;
137+ }
138+
139+ foreach ( var shader in shaders )
140+ _gl . AttachShader ( program , shader ) ;
141+
142+ _gl . LinkProgram ( program ) ;
143+
144+ _gl . GetProgram ( program , GLEnum . LinkStatus , out var success ) ;
145+ if ( success == 0 )
146+ {
147+ string info = _gl . GetProgramInfoLog ( program ) ;
148+ Debug . WriteLine ( $ "GL.LinkProgram had info log:\n { info } ") ;
149+ }
150+
151+ foreach ( var shader in shaders )
152+ {
153+ _gl . DetachShader ( program , shader ) ;
154+ _gl . DeleteShader ( shader ) ;
155+ }
156+
157+ _initialized = true ;
158+
159+ return program ;
160+ }
161+
162+ private uint CompileShader ( ShaderType type , string source )
163+ {
164+ var shader = _gl . CreateShader ( type ) ;
165+ _gl . ShaderSource ( shader , source ) ;
166+ _gl . CompileShader ( shader ) ;
167+
168+ _gl . GetShader ( shader , ShaderParameterName . CompileStatus , out var success ) ;
169+ if ( success == 0 )
170+ {
171+ string info = _gl . GetShaderInfoLog ( shader ) ;
172+ Debug . WriteLine ( $ "GL.CompileShader for shader [{ type } ] had info log:\n { info } ") ;
173+ }
174+
175+ return shader ;
176+ }
177+ }
178+ }
0 commit comments