Skip to content
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

Lookup table to increase styling performance #179

Closed
SunBlack opened this issue Feb 10, 2017 · 5 comments
Closed

Lookup table to increase styling performance #179

SunBlack opened this issue Feb 10, 2017 · 5 comments

Comments

@SunBlack
Copy link

SunBlack commented Feb 10, 2017

Currently styling performance can be slow in case you have multiple conditions.

E.g.

tileset.style = new Cesium3DTileStyle({
	"color" : {
		"conditions" : [
			["(${MYPROPERTY} === 0)", "rgb(196, 196, 196)"],
			["(${MYPROPERTY} === 1)", "rgb(64, 64, 64)"],
			["(${MYPROPERTY} === 2)", "rgb(128, 128, 0)"],
			["(${MYPROPERTY} === 3)", "rgb(128, 0, 0)"],
			["true", "rgb(255, 255, 255)"],
		]
	}
});

Results in a shader which looks like

vec4 getColorFromStyle() 
{ 
    if ((czm_tiles3d_style_MYPROPERTY == 0.0)) 
    { 
        return vec4(0.7686274509803922, 0.7686274509803922, 0.7686274509803922, 1.0); 
    } 
    else if ((czm_tiles3d_style_MYPROPERTY == 1.0)) 
    { 
        return vec4(0.25098039215686274, 0.25098039215686274, 0.25098039215686274, 1.0); 
    } 
    else if ((czm_tiles3d_style_MYPROPERTY == 2.0)) 
    { 
        return vec4(0.5019607843137255, 0.5019607843137255, 0.0, 1.0); 
    } 
    else if ((czm_tiles3d_style_MYPROPERTY == 3.0)) 
    { 
        return vec4(0.5019607843137255, 0.0, 0.0, 1.0); 
    } 
    else if (true) 
    { 
        return vec4(1.0, 1.0, 1.0, 1.0); 
    } 
    return vec4(1.0); 
}

In case of a GPU this is unnecessary slow, because if its SIMD architecture all conditions must be checked. Lookup tables can prevent this issue. A lookup table is usually implemented as array (or Texture in OpenGL).

Some idea how the syntax could be:

tileset.style = new Cesium3DTileStyle({
	"color" : {
		"lookup" : [{
			"name" : "COLOR_MAPPING1",
			"expression" : "MYPROPERTY",
			"values": [
				["0", "rgb(196, 196, 196)"],
				["1", "rgb(64, 64, 64)"],
				["2", "rgb(128, 128, 0)"],
				["3", "rgb(128, 0, 0)"],
				["default", "rgb(255, 255, 255)"],
			]
		},
		{
			"name" : "COLOR_MAPPING2",
			"expression" : "MYPROPERTY",
			"values": [
				["0", "rgb(196, 196, 0)"],
				["1", "rgb(64, 0, 64)"],
				["2", "rgb(128, 128, 32)"],
				["3", "rgb(128, 0, 32)"],
				["default", "rgb(255, 255, 255)"],
			]
		}],
		"color" : {
			"conditions" : [
				["(${MYCONDITION} === 0)", "lookup(COLOR_MAPPING1, ${MYCONDITION})"],
				["(${MYCONDITION} === 1)", "lookup(COLOR_MAPPING2, ${MYCONDITION})"]
				["true", "rgb(255, 255, 255)"],
			]
		}
	}
});

Another possible syntax is

tileset.style = new Cesium3DTileStyle({
	"color" : {
		"lookup" : [{
			"name" : "MYMAPPEDPROPERTY",
			"expression" : "MYPROPERTY",
			"values": [
				["0", "rgb(196, 196, 196)"],
				["1", "rgb(64, 64, 64)"],
				["2", "rgb(128, 128, 0)"],
				["3", "rgb(128, 0, 0)"],
				["default", "rgb(255, 255, 255)"],
			]
		},
		{
			"name" : "MYMAPPEDPROPERTY2",
			"expression" : "MYPROPERTY",
			"values": [
				["0", "rgb(196, 196, 0)"],
				["1", "rgb(64, 0, 64)"],
				["2", "rgb(128, 128, 32)"],
				["3", "rgb(128, 0, 32)"],
				["default", "rgb(255, 255, 255)"],
			]
		}],
		"color" : {
			"conditions" : [
				["(${MYCONDITION} === 0)", "${MYMAPPEDPROPERTY}"],
				["(${MYCONDITION} === 1)", "${MYMAPPEDPROPERTY2}"]
				["true", "rgb(255, 255, 255)"],
			]
		}
	}
});

Original issue see here

@pjcozzi
Copy link
Contributor

pjcozzi commented Feb 11, 2017

Thanks @SunBlack! Just curious how big are your typical lookup tables and do you have any performance numbers?

@SunBlack
Copy link
Author

Typically we have around 10 entries. But there exists also some debug cases in which we have some hundreds (e.g. you could give each BATCH_ID an unique color).

@lilleyse
Copy link
Contributor

I wonder if it's possible to detect this for simple cases and create a lookup table, but all in the implementation.

@SunBlack
Copy link
Author

It should be possible in case following things are true:

  • left (or right) condition variable is always same from type integer
  • condition is always "==="
  • monotonously de/increasing right condition value
  • value is const

In case parsed condition values are not monotonously de/increasing there should be a limit how many percent are not used. E.g. if you are using every time default color except the value is part of a geometric series it could increase performance if you are sing a lookup table - but we should not forget memory usage. Okay geometric series may be no real scenario, but we have not used values. So maybe start using a lookup table if there are more than 4 conditions (or 3, 5, ...=> performance check) and in case the difference between lowest and highest value are more than 10-20 values calculate percent usage of values. If the amount is to small split maybe into multiple lookup tables.

Example:

"conditions" : [
	["(${MYCONDITION} === 0)", "..."],
	["(${MYCONDITION} === 1)", "..."]
	...
	["(${MYCONDITION} === 5)", "..."]
	["(${MYCONDITION} === 1000)", "..."]
	["(${MYCONDITION} === 1001)", "..."]
	...
	["(${MYCONDITION} === 1005)", "..."]
	["default", "..."],

Could be parsed to into a single loopup table like this:

vec4 getColorFromStyle() 
{ 
    if (czm_tiles3d_style_MYPROPERTY >= 0) 
    { 
        if (czm_tiles3d_style_MYPROPERTY <= 5) return texture2D(..., czm_tiles3d_style_MYPROPERTY, ...);
        if (czm_tiles3d_style_MYPROPERTY >= 1000) return texture2D(..., czm_tiles3d_style_MYPROPERTY-994, ...);
    }
     return vec4(1.0); 
}

But in general I don't believe it is worth to check this automatically. In case you have performance issue user can better optimize usage of lookup tables than a script.

@lilleyse lilleyse mentioned this issue Nov 15, 2021
85 tasks
@lilleyse
Copy link
Contributor

Noted this idea in #2 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants