Skip to content

Commit

Permalink
Preprocess used shader defines from source
Browse files Browse the repository at this point in the history
  • Loading branch information
karimnaaji committed Jul 12, 2022
1 parent 7fa1b41 commit 7fe3bb1
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 20 deletions.
32 changes: 13 additions & 19 deletions src/render/program.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ export type DrawMode =
| $PropertyType<WebGLRenderingContext, 'TRIANGLES'>
| $PropertyType<WebGLRenderingContext, 'LINE_STRIP'>;

type ShaderSource = {
fragmentSource: string,
vertexSource: string,
staticAttributes: Array<string>,
usedDefines: Array<string>
};

function getTokenizedAttributes(array: Array<string>): Array<string> {
const result = [];

Expand All @@ -44,19 +51,6 @@ function getTokenizedAttributes(array: Array<string>): Array<string> {
return result;
}

function isDefineUsed(source: {fragmentSource: string, vertexSource: string, staticAttributes: Array<string>}, define: string): boolean {
if (!define) {
return false;
}
if (source.fragmentSource.includes(define)) {
return true;
}
if (source.vertexSource.includes(define)) {
return true;
}
return false;
}

class Program<Us: UniformBindings> {
program: WebGLProgram;
attributes: {[_: string]: number};
Expand All @@ -67,10 +61,10 @@ class Program<Us: UniformBindings> {
terrainUniforms: ?TerrainUniformsType;
fogUniforms: ?FogUniformsType;

static cacheKey(source: {fragmentSource: string, vertexSource: string, staticAttributes: Array<string>}, name: string, defines: string[], programConfiguration: ?ProgramConfiguration): string {
static cacheKey(source: ShaderSource, name: string, defines: string[], programConfiguration: ?ProgramConfiguration): string {
let key = `${name}${programConfiguration ? programConfiguration.cacheKey : ''}`;
for (const define of defines) {
if (isDefineUsed(source, define)) {
if (source.usedDefines.includes(define)) {
key += `/${define}`;
}
}
Expand All @@ -79,7 +73,7 @@ class Program<Us: UniformBindings> {

constructor(context: Context,
name: string,
source: {fragmentSource: string, vertexSource: string, staticAttributes: Array<string>},
source: ShaderSource,
configuration: ?ProgramConfiguration,
fixedUniforms: (Context) => Us,
fixedDefines: string[]) {
Expand Down Expand Up @@ -115,7 +109,7 @@ class Program<Us: UniformBindings> {
}
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
// assert(gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS), (gl.getShaderInfoLog(fragmentShader): any));
assert(gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS), (gl.getShaderInfoLog(fragmentShader): any));
gl.attachShader(this.program, fragmentShader);

const vertexShader = gl.createShader(gl.VERTEX_SHADER);
Expand All @@ -125,7 +119,7 @@ class Program<Us: UniformBindings> {
}
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
// assert(gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS), (gl.getShaderInfoLog(vertexShader): any));
assert(gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS), (gl.getShaderInfoLog(vertexShader): any));
gl.attachShader(this.program, vertexShader);

this.attributes = {};
Expand All @@ -140,7 +134,7 @@ class Program<Us: UniformBindings> {
}

gl.linkProgram(this.program);
// assert(gl.getProgramParameter(this.program, gl.LINK_STATUS), (gl.getProgramInfoLog(this.program): any));
assert(gl.getProgramParameter(this.program, gl.LINK_STATUS), (gl.getProgramInfoLog(this.program): any));

gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
Expand Down
34 changes: 33 additions & 1 deletion src/shaders/shaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ import atmosphereVert from './atmosphere.vertex.glsl';
export let preludeTerrain = {};
export let preludeFog = {};

const commonDefines = [];
parseUsedPreprocessorDefines(preludeCommon, commonDefines);
parseUsedPreprocessorDefines(preludeTerrainVert, commonDefines);
parseUsedPreprocessorDefines(preludeFogVert, commonDefines);
parseUsedPreprocessorDefines(preludeFogFrag, commonDefines);

preludeTerrain = compile('', preludeTerrainVert);
preludeFog = compile(preludeFogFrag, preludeFogVert);
// Shadow prelude is not compiled until GL-JS implements shadows
Expand Down Expand Up @@ -150,6 +156,28 @@ export default {
globeAtmosphere: compile(atmosphereFrag, atmosphereVert)
};

function parseUsedPreprocessorDefines(source, defines) {
const lines = source.replace(/\s*\/\/[^\n]*\n/g, '\n').split('\n');
for (let line of lines) {
line = line.trim();
if (line[0] === '#') {
if (line.includes('if') && !line.includes('endif')) {
line = line.replace('#', '')
.replace(/ifdef|ifndef|elif|if/g, '')
.replace(/!|defined|\(|\)|\|\||&&/g, '')
.replace(/\s+/g, ' ').trim();

const newDefines = line.split(' ');
for (const define of newDefines) {
if (!defines.includes(define)) {
defines.push(define);
}
}
}
}
}
}

// Expand #pragmas to #ifdefs.
export function compile(fragmentSource, vertexSource) {
const pragmaRegex = /#pragma mapbox: ([\w]+) ([\w]+) ([\w]+) ([\w]+)/g;
Expand All @@ -158,6 +186,10 @@ export function compile(fragmentSource, vertexSource) {
const staticAttributes = vertexSource.match(attributeRegex);
const fragmentPragmas = {};

const usedDefines = [...commonDefines];
parseUsedPreprocessorDefines(fragmentSource, usedDefines);
parseUsedPreprocessorDefines(vertexSource, usedDefines);

fragmentSource = fragmentSource.replace(pragmaRegex, (match, operation, precision, type, name) => {
fragmentPragmas[name] = true;
if (operation === 'define') {
Expand Down Expand Up @@ -245,5 +277,5 @@ uniform ${precision} ${type} u_${name};
}
});

return {fragmentSource, vertexSource, staticAttributes};
return {fragmentSource, vertexSource, staticAttributes, usedDefines};
}

0 comments on commit 7fe3bb1

Please sign in to comment.