Browse Source

context: Cache active program

This would reduce the calls to glUseProgram if there actually was more
than one program.
Johannes Hofmann 7 years ago
parent
commit
4962639d01
2 changed files with 39 additions and 15 deletions
  1. 15
    3
      src/context.rs
  2. 24
    12
      src/program.rs

+ 15
- 3
src/context.rs View File

1
-use glutin;
2
 use glutin::GlContext;
1
 use glutin::GlContext;
3
-use std::mem;
2
+use glutin;
3
+use program::ProgramId;
4
 use std::ffi::CStr;
4
 use std::ffi::CStr;
5
+use std::mem;
5
 
6
 
6
 pub(crate) mod gl {
7
 pub(crate) mod gl {
7
     #![allow(unknown_lints)]
8
     #![allow(unknown_lints)]
24
     pub(crate) gl: gl::Gl,
25
     pub(crate) gl: gl::Gl,
25
     active_texture_unit: TextureUnit,
26
     active_texture_unit: TextureUnit,
26
     next_free_texture_unit: TextureUnit,
27
     next_free_texture_unit: TextureUnit,
28
+    active_program: ProgramId,
27
 }
29
 }
28
 
30
 
29
 impl ::std::fmt::Debug for Context {
31
 impl ::std::fmt::Debug for Context {
50
             /// Initial active texture unit is supposed to be GL_TEXTURE0
52
             /// Initial active texture unit is supposed to be GL_TEXTURE0
51
             active_texture_unit: TextureUnit(0),
53
             active_texture_unit: TextureUnit(0),
52
             next_free_texture_unit: TextureUnit(0),
54
             next_free_texture_unit: TextureUnit(0),
55
+            active_program: ProgramId::invalid(),
53
         };
56
         };
54
 
57
 
55
         // Initialize a vertex array object (VAO) if the current OpenGL context supports it. VAOs are
58
         // Initialize a vertex array object (VAO) if the current OpenGL context supports it. VAOs are
144
             unsafe {
147
             unsafe {
145
                 self.gl.ActiveTexture(gl::TEXTURE0 + unit.0);
148
                 self.gl.ActiveTexture(gl::TEXTURE0 + unit.0);
146
             }
149
             }
150
+            self.active_texture_unit = unit;
147
         }
151
         }
148
-        self.active_texture_unit = unit;
149
     }
152
     }
150
 
153
 
151
     pub fn occupy_free_texture_unit(&mut self) -> TextureUnit {
154
     pub fn occupy_free_texture_unit(&mut self) -> TextureUnit {
157
 
160
 
158
         tu
161
         tu
159
     }
162
     }
163
+
164
+    pub fn use_program(&mut self, prog: ProgramId) {
165
+        if prog != self.active_program {
166
+            unsafe {
167
+                self.gl.UseProgram(prog.index());
168
+            }
169
+            self.active_program = prog;
170
+        }
171
+    }
160
 }
172
 }

+ 24
- 12
src/program.rs View File

13
 pub struct Program {
13
 pub struct Program {
14
     vert_obj: u32,
14
     vert_obj: u32,
15
     frag_obj: u32,
15
     frag_obj: u32,
16
-    program_obj: u32,
16
+    program_id: ProgramId,
17
 }
17
 }
18
 
18
 
19
-#[derive(Clone, Debug)]
19
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
20
 pub struct ProgramId {
20
 pub struct ProgramId {
21
     id: u32,
21
     id: u32,
22
 }
22
 }
23
 
23
 
24
+impl ProgramId {
25
+    /// Returns an invalid `ProgramId`.
26
+    pub fn invalid() -> Self {
27
+        ProgramId{ id: 0 }
28
+    }
29
+
30
+    pub fn index(&self) -> u32 {
31
+        self.id
32
+    }
33
+}
34
+
24
 impl Program {
35
 impl Program {
25
     pub fn from_paths<P: AsRef<Path>>(cx: &mut Context, vert_path: P, frag_path: P) -> Result<Program, String> {
36
     pub fn from_paths<P: AsRef<Path>>(cx: &mut Context, vert_path: P, frag_path: P) -> Result<Program, String> {
26
         let vert_src = {
37
         let vert_src = {
76
                 frag_obj
87
                 frag_obj
77
             };
88
             };
78
 
89
 
79
-            let program_obj = {
90
+            let program_id = {
80
                 let prog = cx.gl.CreateProgram();
91
                 let prog = cx.gl.CreateProgram();
81
                 cx.gl.AttachShader(prog, vert_obj);
92
                 cx.gl.AttachShader(prog, vert_obj);
82
                 cx.gl.AttachShader(prog, frag_obj);
93
                 cx.gl.AttachShader(prog, frag_obj);
83
                 cx.gl.LinkProgram(prog);
94
                 cx.gl.LinkProgram(prog);
84
                 check_link_errors(cx, prog)?;
95
                 check_link_errors(cx, prog)?;
85
 
96
 
86
-                cx.gl.UseProgram(prog);
87
-                check_gl_errors!(cx);
88
-                prog
97
+                ProgramId { id: prog }
89
             };
98
             };
90
 
99
 
100
+            cx.use_program(program_id);
101
+            check_gl_errors!(cx);
102
+
91
             Ok(Program {
103
             Ok(Program {
92
                 vert_obj,
104
                 vert_obj,
93
                 frag_obj,
105
                 frag_obj,
94
-                program_obj,
106
+                program_id,
95
             })
107
             })
96
         }
108
         }
97
     }
109
     }
98
 
110
 
99
     pub fn add_texture(&mut self, cx: &mut Context, texture: &Texture, uniform_name: &CStr) {
111
     pub fn add_texture(&mut self, cx: &mut Context, texture: &Texture, uniform_name: &CStr) {
100
         //TODO store reference to texture
112
         //TODO store reference to texture
113
+        cx.use_program(self.program_id);
101
         unsafe {
114
         unsafe {
102
-            let tex_loc = cx.gl.GetUniformLocation(self.program_obj, uniform_name.as_ptr() as *const _);
115
+            let tex_loc = cx.gl.GetUniformLocation(self.program_id.index(), uniform_name.as_ptr() as *const _);
103
             check_gl_errors!(cx);
116
             check_gl_errors!(cx);
104
 
117
 
105
             cx.gl.Uniform1i(tex_loc, texture.unit().index() as i32);
118
             cx.gl.Uniform1i(tex_loc, texture.unit().index() as i32);
107
     }
120
     }
108
 
121
 
109
     pub fn add_attribute(&mut self, cx: &mut Context, name: &CStr, number_components: u32, stride: usize, offset: usize) {
122
     pub fn add_attribute(&mut self, cx: &mut Context, name: &CStr, number_components: u32, stride: usize, offset: usize) {
123
+        cx.use_program(self.program_id);
110
         unsafe {
124
         unsafe {
111
-            let attrib_id = cx.gl.GetAttribLocation(self.program_obj, name.as_ptr() as *const _);
125
+            let attrib_id = cx.gl.GetAttribLocation(self.program_id.index(), name.as_ptr() as *const _);
112
             cx.gl.VertexAttribPointer(
126
             cx.gl.VertexAttribPointer(
113
                 attrib_id as u32,
127
                 attrib_id as u32,
114
                 number_components as i32, // size
128
                 number_components as i32, // size
122
     }
136
     }
123
 
137
 
124
     pub fn id(&self) -> ProgramId {
138
     pub fn id(&self) -> ProgramId {
125
-        ProgramId {
126
-            id: self.program_obj,
127
-        }
139
+        self.program_id
128
     }
140
     }
129
 }
141
 }
130
 
142