Advertisement

When to worry about amount of uniforms in a shader

Started by August 12, 2018 08:17 AM
4 comments, last by Makusik Fedakusik 6 years, 5 months ago

This is the current uniform layout in my deferred renderer:

[


uniform sampler2D texture_diffuse;	/* Albedo map of the material */
uniform sampler2D texture_normal;	/* Normal map of the material */
uniform sampler2D texture_metalness;	/* Metalness map of the material */
uniform sampler2D texture_roughness;	/* Roughness map of the material */
uniform samplerCube texture_cubemap;	/* Environment reflection map */
uniform samplerCube texture_ibl;	/* Environment light map (IBL) */

uniform float uMetalness;	/* User specified metalness of the material */
uniform float uRoughness;	/* User specified roughness of the material */
uniform float uReflective;	/* User specified reflectiveness of the material */

uniform float normalMapEnabled;	/* Set on CPU. Controls whether material normalmap is used */
uniform float enableSkybox; 	/* Set on CPU. Controls whether skybox is used */
uniform float enableIBL;	/* Set on CPU. Controls whether skybox IBL is used */

uniform vec3 uAmbient;		/* Ambient of the scene. Used for IBL */
uniform vec3 uMaterialColor;	/* User specified color of the material */

 

I've been thinking, should I worry about this many uniforms? They are being set by each material in the engine. I wrote some cpu-sided checks to see if I am updating the same uniform handle to the same value (and ignoring it if so), to try to help a little bit.

I could easily combine the texture_normal, texture_metalness, and texture_roughness to a single sampler2D. Would that help much when drawing?

If performance is a problem for you then it might help. Less uniforms to handle means less work on the CPU everytime you change them or swap shaders. Less samplers to sample... well.. obviously it's faster on the GPU also if you can afford grouping the texture channels together (sometimes it's not a good idea e.g. when using block compression with channels containing totally unrelated info with different frequencies of change).

Advertisement

Apart from the CPU cost of setting uniforms which was already mentioned, there can be GPU cost as well. Each individual texture sampler takes up GPU resources (registers), which can limit overall occupancy. This means that the GPU will be able to execute the shader less effectively. It is a good idea to combine multiple textures into one, because it will take up less registers for its descriptor (in DX12/Vulkan terms, but it will apply to every API), and also you can reduce sample instructions by sampling multiple textures with one instruction. Sampling multiple channels from a single texture also improves memory access latency.

Will give it a try then, thanks! :)

Minimize gl-states switching (group object by opaque/transparent/no-depth)

Group textures to atlas

Group uniforms to struct

Tune render target size and precision (RGBA32F and other)

Could you pack floats to short and unpack? Or pack to texture?

Could you create vertex cache and load it all on GPU, draw as "indexes.size + offset"

This topic is closed to new replies.

Advertisement