Constant buffer strategy and thoughts

Started by
3 comments, last by _the_phantom_ 7 years, 3 months ago

Hi all,

I've arrived at the moment that my shaders/shaderpacks and shader manager is up and running. All nice and abstracted within the renderer. The next stop is constant buffers.

Before I dive in/ run off and implement, I'd like to share some thoughts and hear your opinion on how you handle this.

The approach I have in mind for now, is based on articles I've read and experience I have with playing around with the CBuffers:

- I will have different CBuffers in my shaders, based on update frequency

- so far I've come up with the following 'types'

-- CB per frame (camera etc.)

-- CB per object (world orientiation for mesh instance etc.)

-- CB per material (will also set the texture in the unexposed part of the renderer)

- I don't see a reason yet, to have a CB per application, because for example the projection matrix, is multiplied with view on the CPU side, and then sent 'per object' (to prevent this calculation for each vertex)

- assuming each CBuffer will need updating through the application, I will need predefined structs for each type of CBuffer

-- meaning the unique CBuffers for all shaders, need to be known structs in the application (I can force this in the asset pipeline I guess)

-- this means that I will not use the D3D shader reflect API to dynamically figure out what CBuffers are used within which shader. I could do this, but in the end I cannot support unlimited CBuffer types, because I wouldn't have the structs in the application, to be able to update them. Is this a correct assumption, or could i somehow 'work around' this and create a block of memory with the needed variables in the dynamic struct?

- I will link 'n' CBuffer handles in each shaderpack (pack consists of combination of VS, PS etc.)

-- my CBufferManager will either set another CB or simply leave it, when it's already bound to 1 of the 14(?) slots)

- this also means I will not distinct CBuffers per shader type (i.e. separate for the PS, VS etc.).

I'm curious what your view in on this approach and/or how I can do this otherwise/ better.

All input is appreciated is always.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Advertisement

- I don't see a reason yet, to have a CB per application, because for example the projection matrix, is multiplied with view on the CPU side, and then sent 'per object' (to prevent this calculation for each vertex)

That doesn't sound right. projection-matrix is usually eigther attribute of the camera (you can really neglect that situation where multiple cameras would share the same projection), or at least of the view, meaning it should not be sent 'per object' but 'per frame'.

Seeing how you actually reason about the project-matrix being part of the application, this is heavily limiting - shadow-passes, 2D-UI rendering, etc... might all need different project matrices, so you should make that configurable eigther per view or camera, regardless of how you structure your C-buffers.

On the same note, 'per frame'-CB, you are strictly refering to update-frequency, right? This data obviously has to be replicated for every camera, for shadow-passes, reflections etc...

As for 'per application'-data, the only thing I can think about is timestep/time passed, but you could also just store this data in the 'per camera' buffer if adding an additional cbuffer for the application would complicate your design (since you'll be updating .

Thanks.

About the viewmatrix, I'll have to check how I do it know, I think there are (at least) 2 options:

- multiply viewProj with World and update that 'per object'

- just send viewProj 'per frame' and multiply with World in the shader

It's good to know that there are many more additions to 'when' to use the CBuffers, I didn't think of that yet.

It wil be a '2-level' system; 1 being based on the update frequency and the other being for 'what purpose' it actually is. I.e. there can be several instances of a CBuffer per frame or per object (I could say that the material CBuffer is also a CBuffer per frame, which is not updated each frame).

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Any thoughts? I'm especially curious on whether or not to use the d3d reflect API here, and why

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

The main reason for considering the reflection API is flexibility.

If all your structures have to be defined in code as structs then any time you want/need to experiment or add features you are going to be recompiling the whole engine just to add a new thing.

On a previous engine aside from the 'core system' variables our constant buffers were built up on the fly/at load time based on the shader's requirements. (We also didn't use those structures when filling constant buffers; everything was just a blob of bytes in to which offsets and types were recorded).

This meant that artists, graphics and/or game play programmers could invent new shaders, build a material to use them and they would (once the game play systems driving them were hooked up) just work without requiring a core engine recompile. (We also had reserved names/semantics, so if you had a struct which included say 'position' on a per-object basis then you would get the same 'position' values which were passed to 'default' structures via a system which would track and replicate values across constant buffers.)

This topic is closed to new replies.

Advertisement