浏览代码

context: Cache active program

This would reduce the calls to glUseProgram if there actually was more
than one program.
Johannes Hofmann 7 年前
父节点
当前提交
4962639d01
共有 2 个文件被更改,包括 39 次插入15 次删除
  1. 15
    3
      src/context.rs
  2. 24
    12
      src/program.rs

+ 15
- 3
src/context.rs 查看文件

@@ -1,7 +1,8 @@
1
-use glutin;
2 1
 use glutin::GlContext;
3
-use std::mem;
2
+use glutin;
3
+use program::ProgramId;
4 4
 use std::ffi::CStr;
5
+use std::mem;
5 6
 
6 7
 pub(crate) mod gl {
7 8
     #![allow(unknown_lints)]
@@ -24,6 +25,7 @@ pub struct Context {
24 25
     pub(crate) gl: gl::Gl,
25 26
     active_texture_unit: TextureUnit,
26 27
     next_free_texture_unit: TextureUnit,
28
+    active_program: ProgramId,
27 29
 }
28 30
 
29 31
 impl ::std::fmt::Debug for Context {
@@ -50,6 +52,7 @@ impl Context {
50 52
             /// Initial active texture unit is supposed to be GL_TEXTURE0
51 53
             active_texture_unit: TextureUnit(0),
52 54
             next_free_texture_unit: TextureUnit(0),
55
+            active_program: ProgramId::invalid(),
53 56
         };
54 57
 
55 58
         // Initialize a vertex array object (VAO) if the current OpenGL context supports it. VAOs are
@@ -144,8 +147,8 @@ impl Context {
144 147
             unsafe {
145 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 154
     pub fn occupy_free_texture_unit(&mut self) -> TextureUnit {
@@ -157,4 +160,13 @@ impl Context {
157 160
 
158 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 查看文件

@@ -13,14 +13,25 @@ use texture::Texture;
13 13
 pub struct Program {
14 14
     vert_obj: u32,
15 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 20
 pub struct ProgramId {
21 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 35
 impl Program {
25 36
     pub fn from_paths<P: AsRef<Path>>(cx: &mut Context, vert_path: P, frag_path: P) -> Result<Program, String> {
26 37
         let vert_src = {
@@ -76,30 +87,32 @@ impl Program {
76 87
                 frag_obj
77 88
             };
78 89
 
79
-            let program_obj = {
90
+            let program_id = {
80 91
                 let prog = cx.gl.CreateProgram();
81 92
                 cx.gl.AttachShader(prog, vert_obj);
82 93
                 cx.gl.AttachShader(prog, frag_obj);
83 94
                 cx.gl.LinkProgram(prog);
84 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 103
             Ok(Program {
92 104
                 vert_obj,
93 105
                 frag_obj,
94
-                program_obj,
106
+                program_id,
95 107
             })
96 108
         }
97 109
     }
98 110
 
99 111
     pub fn add_texture(&mut self, cx: &mut Context, texture: &Texture, uniform_name: &CStr) {
100 112
         //TODO store reference to texture
113
+        cx.use_program(self.program_id);
101 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 116
             check_gl_errors!(cx);
104 117
 
105 118
             cx.gl.Uniform1i(tex_loc, texture.unit().index() as i32);
@@ -107,8 +120,9 @@ impl Program {
107 120
     }
108 121
 
109 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 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 126
             cx.gl.VertexAttribPointer(
113 127
                 attrib_id as u32,
114 128
                 number_components as i32, // size
@@ -122,9 +136,7 @@ impl Program {
122 136
     }
123 137
 
124 138
     pub fn id(&self) -> ProgramId {
125
-        ProgramId {
126
-            id: self.program_obj,
127
-        }
139
+        self.program_id
128 140
     }
129 141
 }
130 142