-
Notifications
You must be signed in to change notification settings - Fork 550
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Design the shader parameters logic #19
Comments
Notes from @csherratt:
|
Notes from @glennw:
|
I've advanced with this issue quite a bit. Sorry for the wall of text... I hope to get some feedback. Shader parameters are just a more complex case of the same problem we have with vertex attributes. Those also need to be matched against shader inputs. Comparing strings at that point is not the biggest threat - we also need to verify the semantics to match, and (more importantly) we need to iterate given resources for any requested one. So there is a total of 4 components that need to be optimized out:
The first two points apply equally to vertex attributes. Semantic verification is an open question about attributes, and we may want to add it later on. No cloning is done by the user (or render client) for vertex attributes, because they are already stored on the render thread. Here is my proposed solution: pub type EnvBlockHandle = u8;
pub type EnvUniformHandle = u16;
pub type EnvTextureHandle = u8;
struct Environment {
blocks: Vec<(String, device::dev::Buffer)>,
uniforms: Vec<(String, device::shade::UniformValue)>,
textures: Vec<(String, device::dev::Texture, device::dev::Sampler)>,
}
impl Environment {
pub fn new() -> Environment;
pub fn add_block(&mut self, &str, device::dev::Buffer) -> EnvBlockHandle ;
pub fn add_uniform(&mut self, &str, device::shade::UniformValue) -> EnvUniformHandle;
pub fn add_texture(&mut self, &str, device::dev::Texture, device::dev::Sampler) -> EnvTextureHandle;
}
impl render::Client {
// sends the environment for the render task to store
fn register_environment(&mut self, Environment) -> EnvironmentHandle;
fn unregister_environment(&mut self, EnvironmentHandle);
// these methods are to change existing environment variables
// passing an index instead of a full name is both cheap and DRY (yay!)
fn set_env_block(&mut self, EnvironmentHandle, EnvBlockHandle, device::dev::Buffer);
fn set_env_uniform(&mut self, EnvironmentHandle, EnvUniformHandle, device::shade::UniformValue);
fn set_env_texture(&mut self, EnvironmentHandle, EnvTextureHandle, device::dev::Texture, device::dev::Sampler);
} Here is an example of the user code: // at initialization
let mut env = gfx::Environment::new();
// we get a hold of this one to change it later
let var_color = env.add_uniform("color", gfx::ValueF32Vec([0.5, ..4]));
// not going to change it, so ignoring the result
env.add_texture("diffuse", my_texture_handle, my_sampler_handle);
let env_handle = renderer.register_environment(env_handle);
...
// at run-time
renderer.set_env_uniform(env_handle, var_color, my_color_value);
renderer.draw(..., env_handle); During the rendering, pub type EnvironmentCache = HashMap<(EnvironmentHandle, ProgramHandle), EnvironmentShortcut>; Where the struct EnvironmentShortcut
blocks: Vec<EnvBlockHandle>, // size equals to ProgramMeta::blocks
uniforms: Vec<EnvUniformHandle>, // size equals to ProgramMeta::uniforms
textures: Vec<EnvTextureHandle> // size equals to ProgramMeta::textures
} If the shortcut is not found, it is constructed by looking up the corresponding parameters in the |
So is this |
@bjz Baking is not the right term. |
Ah ok, thanks for the clarification. |
Here is a breakdown of our choices:
Current consensus leans towards Choice 3, but we need to figure out how to make it performance effective (reduce the number of heap allocations and the memory to copy) and yet ergonomic. |
Here is how Irrlicht handles it: http://irrlicht.sourceforge.net/docu/example010.html |
Proposal prototype N2: https://gist.github.com/kvark/182cb352b7ef599dcdbc Apparently, we can skip N2 and aim further (from @csherratt):
|
Refactored base vertex/instance calls
A draw call from the user side should provide the following entities:
SubMesh
, which is a slice into the attributes and vertex indices, which themselves are linked to raw bufferstarget::Frame
, which contains the surfaces to be bound as colors and depth targetsshader::Program
, which is not just the shader program ID, but also has meta-data attached about all the used attributes and uniform values/buffersshader::Environment
, the unresolved key structure to encapsulate all needed shader parameters in some form, including the material data, camera, lights, etc.The last thing is what needs to be designed efficiently, since it needs to be accessed on every call, matched against shader meta-data (see Draw Call Verification), and also passed around a lot.
In Claymore I used the Map to store parameters by name:
I consider it to be not efficient enough, because there is a lot of allocations, and carrying out names everywhere (and comparing them) is a bit too heavy. We'll need something very generic and more efficient than this.
The text was updated successfully, but these errors were encountered: