mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
use explicit binding for textures
- prevents dozens of glUniform1i calls when drawing stuff, thus improving performance by 5-10% (more on WebAssembly, where each gl call is passed through JS)
This commit is contained in:
@@ -52,10 +52,15 @@ pub enum BufferDataUsage {
|
||||
},
|
||||
}
|
||||
|
||||
pub enum TextureShaderLocation {
|
||||
Uniform(UniformLocation),
|
||||
ExplicitBinding(usize),
|
||||
}
|
||||
|
||||
pub enum ResourceBinding<'a> {
|
||||
Texture {
|
||||
texture: Rc<RefCell<dyn GpuTexture>>,
|
||||
shader_location: UniformLocation,
|
||||
shader_location: TextureShaderLocation,
|
||||
},
|
||||
Buffer {
|
||||
buffer: &'a dyn Buffer,
|
||||
@@ -71,7 +76,14 @@ impl<'a> ResourceBinding<'a> {
|
||||
) -> Self {
|
||||
Self::Texture {
|
||||
texture: texture.clone(),
|
||||
shader_location: shader_location.clone(),
|
||||
shader_location: TextureShaderLocation::Uniform(shader_location.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn texture_with_binding(texture: &Rc<RefCell<dyn GpuTexture>>, binding: usize) -> Self {
|
||||
Self::Texture {
|
||||
texture: texture.clone(),
|
||||
shader_location: TextureShaderLocation::ExplicitBinding(binding),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
use crate::framebuffer::BufferDataUsage;
|
||||
use crate::framebuffer::{BufferDataUsage, TextureShaderLocation};
|
||||
use crate::gl::geometry_buffer::GlGeometryBuffer;
|
||||
use crate::{
|
||||
buffer::{Buffer, BufferKind},
|
||||
@@ -475,13 +475,16 @@ fn pre_draw(
|
||||
} => {
|
||||
let texture = texture.borrow();
|
||||
let texture = texture.as_any().downcast_ref::<GlTexture>().unwrap();
|
||||
unsafe {
|
||||
server
|
||||
.gl
|
||||
.uniform_1_i32(Some(&shader_location.id), texture_unit)
|
||||
};
|
||||
texture.bind(server, texture_unit as u32);
|
||||
texture_unit += 1;
|
||||
match shader_location {
|
||||
TextureShaderLocation::Uniform(uniform) => {
|
||||
unsafe { server.gl.uniform_1_i32(Some(&uniform.id), texture_unit) };
|
||||
texture.bind(server, texture_unit as u32);
|
||||
texture_unit += 1;
|
||||
}
|
||||
TextureShaderLocation::ExplicitBinding(binding) => {
|
||||
texture.bind(server, *binding as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
ResourceBinding::Buffer {
|
||||
buffer,
|
||||
|
||||
@@ -281,7 +281,24 @@ impl GlProgram {
|
||||
initial_source.insert_str(0, &texture_bindings);
|
||||
}
|
||||
|
||||
Self::from_source(server, name, &vertex_source, &fragment_source)
|
||||
let program = Self::from_source(server, name, &vertex_source, &fragment_source)?;
|
||||
|
||||
unsafe {
|
||||
server.set_program(Some(program.id));
|
||||
let mut texture_unit_index = 0;
|
||||
for property in properties {
|
||||
if let PropertyKind::Sampler { .. } = property.kind {
|
||||
if let Some(location) =
|
||||
server.gl.get_uniform_location(program.id, &property.name)
|
||||
{
|
||||
server.gl.uniform_1_i32(Some(&location), texture_unit_index);
|
||||
}
|
||||
texture_unit_index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(program)
|
||||
}
|
||||
|
||||
pub fn from_source(
|
||||
|
||||
@@ -45,7 +45,7 @@ use crate::{
|
||||
buffer::Buffer,
|
||||
error::FrameworkError,
|
||||
framebuffer::{FrameBuffer, ResourceBindGroup, ResourceBinding},
|
||||
gpu_program::{BuiltInUniformBlock, GpuProgram},
|
||||
gpu_program::BuiltInUniformBlock,
|
||||
gpu_texture::GpuTexture,
|
||||
server::GraphicsServer,
|
||||
uniform::StaticUniformBuffer,
|
||||
@@ -170,16 +170,15 @@ impl<'a> BundleRenderContext<'a> {
|
||||
&mut self,
|
||||
server: &dyn GraphicsServer,
|
||||
material: &Material,
|
||||
program: &dyn GpuProgram,
|
||||
material_bindings: &mut ArrayVec<ResourceBinding, 32>,
|
||||
) -> Result<(), FrameworkError> {
|
||||
let shader = material.shader().data_ref();
|
||||
for property in shader.definition.properties.iter() {
|
||||
let binding = material_bindings.len();
|
||||
if property.name.as_str() == "fyrox_sceneDepth" {
|
||||
if let Some(scene_depth) = self.scene_depth.as_ref() {
|
||||
if let Ok(location) = program.uniform_location(&property.name) {
|
||||
material_bindings.push(ResourceBinding::texture(scene_depth, &location));
|
||||
}
|
||||
material_bindings
|
||||
.push(ResourceBinding::texture_with_binding(scene_depth, binding));
|
||||
}
|
||||
} else if let Some(PropertyValue::Sampler { value, fallback }) =
|
||||
material.properties().get(&property.name)
|
||||
@@ -193,10 +192,7 @@ impl<'a> BundleRenderContext<'a> {
|
||||
SamplerFallback::Black => self.black_dummy,
|
||||
SamplerFallback::Volume => self.volume_dummy,
|
||||
});
|
||||
|
||||
if let Ok(uniform) = program.uniform_location(&property.name) {
|
||||
material_bindings.push(ResourceBinding::texture(texture, &uniform));
|
||||
}
|
||||
material_bindings.push(ResourceBinding::texture_with_binding(texture, binding));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,12 +477,7 @@ impl RenderDataBundle {
|
||||
};
|
||||
|
||||
let mut material_bindings = ArrayVec::<ResourceBinding, 32>::new();
|
||||
render_context.apply_material(
|
||||
server,
|
||||
material,
|
||||
&*render_pass.program,
|
||||
&mut material_bindings,
|
||||
)?;
|
||||
render_context.apply_material(server, material, &mut material_bindings)?;
|
||||
|
||||
let block_locations = render_pass.program.built_in_uniform_blocks();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user