459 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			459 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								"use strict";
							 | 
						||
| 
								 | 
							
								Object.defineProperty(exports, "__esModule", { value: true });
							 | 
						||
| 
								 | 
							
								exports.ShaderCompiler = exports.CompiledShader = void 0;
							 | 
						||
| 
								 | 
							
								const child_process = require("child_process");
							 | 
						||
| 
								 | 
							
								const fs = require("fs-extra");
							 | 
						||
| 
								 | 
							
								const os = require("os");
							 | 
						||
| 
								 | 
							
								const path = require("path");
							 | 
						||
| 
								 | 
							
								const chokidar = require("chokidar");
							 | 
						||
| 
								 | 
							
								const Throttle = require("promise-parallel-throttle");
							 | 
						||
| 
								 | 
							
								const GraphicsApi_1 = require("./GraphicsApi");
							 | 
						||
| 
								 | 
							
								const Platform_1 = require("./Platform");
							 | 
						||
| 
								 | 
							
								const AssetConverter_1 = require("./AssetConverter");
							 | 
						||
| 
								 | 
							
								const log = require("./log");
							 | 
						||
| 
								 | 
							
								class CompiledShader {
							 | 
						||
| 
								 | 
							
								    constructor() {
							 | 
						||
| 
								 | 
							
								        this.files = [];
							 | 
						||
| 
								 | 
							
								        this.inputs = [];
							 | 
						||
| 
								 | 
							
								        this.outputs = [];
							 | 
						||
| 
								 | 
							
								        this.uniforms = [];
							 | 
						||
| 
								 | 
							
								        this.types = [];
							 | 
						||
| 
								 | 
							
								        this.noembed = false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								exports.CompiledShader = CompiledShader;
							 | 
						||
| 
								 | 
							
								class ShaderCompiler {
							 | 
						||
| 
								 | 
							
								    constructor(exporter, platform, compiler, to, temp, builddir, options, shaderMatchers) {
							 | 
						||
| 
								 | 
							
								        this.exporter = exporter;
							 | 
						||
| 
								 | 
							
								        if (platform.endsWith('-native'))
							 | 
						||
| 
								 | 
							
								            platform = platform.substr(0, platform.length - '-native'.length);
							 | 
						||
| 
								 | 
							
								        if (platform.endsWith('-hl'))
							 | 
						||
| 
								 | 
							
								            platform = platform.substr(0, platform.length - '-hl'.length);
							 | 
						||
| 
								 | 
							
								        this.platform = platform;
							 | 
						||
| 
								 | 
							
								        this.compiler = compiler;
							 | 
						||
| 
								 | 
							
								        this.type = ShaderCompiler.findType(platform, options);
							 | 
						||
| 
								 | 
							
								        this.options = options;
							 | 
						||
| 
								 | 
							
								        this.to = to;
							 | 
						||
| 
								 | 
							
								        this.temp = temp;
							 | 
						||
| 
								 | 
							
								        this.builddir = builddir;
							 | 
						||
| 
								 | 
							
								        this.shaderMatchers = shaderMatchers;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    close() {
							 | 
						||
| 
								 | 
							
								        if (this.watcher)
							 | 
						||
| 
								 | 
							
								            this.watcher.close();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    static findType(platform, options) {
							 | 
						||
| 
								 | 
							
								        switch (platform) {
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.Empty:
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.Node:
							 | 
						||
| 
								 | 
							
								                return 'glsl';
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.Flash:
							 | 
						||
| 
								 | 
							
								                return 'agal';
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.Android:
							 | 
						||
| 
								 | 
							
								                if (options.graphics === GraphicsApi_1.GraphicsApi.Vulkan || options.graphics === GraphicsApi_1.GraphicsApi.Default) {
							 | 
						||
| 
								 | 
							
								                    return 'spirv';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.OpenGL) {
							 | 
						||
| 
								 | 
							
								                    return 'essl';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else {
							 | 
						||
| 
								 | 
							
								                    throw new Error('Unsupported shader language.');
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.HTML5:
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.DebugHTML5:
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.HTML5Worker:
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.Pi:
							 | 
						||
| 
								 | 
							
								                return 'essl';
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.tvOS:
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.iOS:
							 | 
						||
| 
								 | 
							
								                if (options.graphics === GraphicsApi_1.GraphicsApi.Metal || options.graphics === GraphicsApi_1.GraphicsApi.Default) {
							 | 
						||
| 
								 | 
							
								                    return 'metal';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.OpenGL) {
							 | 
						||
| 
								 | 
							
								                    return 'essl';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else {
							 | 
						||
| 
								 | 
							
								                    throw new Error('Unsupported shader language.');
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.Windows:
							 | 
						||
| 
								 | 
							
								                if (options.graphics === GraphicsApi_1.GraphicsApi.Vulkan) {
							 | 
						||
| 
								 | 
							
								                    return 'spirv';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.OpenGL) {
							 | 
						||
| 
								 | 
							
								                    return 'glsl';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.Direct3D11 || options.graphics === GraphicsApi_1.GraphicsApi.Direct3D12 || options.graphics === GraphicsApi_1.GraphicsApi.Default) {
							 | 
						||
| 
								 | 
							
								                    return 'd3d11';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.Direct3D9) {
							 | 
						||
| 
								 | 
							
								                    return 'd3d9';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else {
							 | 
						||
| 
								 | 
							
								                    throw new Error('Unsupported shader language.');
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.WindowsApp:
							 | 
						||
| 
								 | 
							
								                return 'd3d11';
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.Xbox360:
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.PlayStation3:
							 | 
						||
| 
								 | 
							
								                return 'd3d9';
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.Linux:
							 | 
						||
| 
								 | 
							
								                if (options.graphics === GraphicsApi_1.GraphicsApi.Vulkan || options.graphics === GraphicsApi_1.GraphicsApi.Default) {
							 | 
						||
| 
								 | 
							
								                    return 'spirv';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.OpenGL) {
							 | 
						||
| 
								 | 
							
								                    return 'glsl';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else {
							 | 
						||
| 
								 | 
							
								                    throw new Error('Unsupported shader language.');
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.OSX:
							 | 
						||
| 
								 | 
							
								                if (options.graphics === GraphicsApi_1.GraphicsApi.Metal || options.graphics === GraphicsApi_1.GraphicsApi.Default) {
							 | 
						||
| 
								 | 
							
								                    return 'metal';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.OpenGL) {
							 | 
						||
| 
								 | 
							
								                    return 'glsl';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else {
							 | 
						||
| 
								 | 
							
								                    throw new Error('Unsupported shader language.');
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.Krom:
							 | 
						||
| 
								 | 
							
								                if (options.graphics === GraphicsApi_1.GraphicsApi.Default) {
							 | 
						||
| 
								 | 
							
								                    if (process.platform === 'win32') {
							 | 
						||
| 
								 | 
							
								                        return 'd3d11';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    else if (process.platform === 'darwin') {
							 | 
						||
| 
								 | 
							
								                        return 'metal';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    else {
							 | 
						||
| 
								 | 
							
								                        return 'glsl';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.Vulkan) {
							 | 
						||
| 
								 | 
							
								                    return 'spirv';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.Metal) {
							 | 
						||
| 
								 | 
							
								                    return 'metal';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.OpenGL) {
							 | 
						||
| 
								 | 
							
								                    return 'glsl';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.Direct3D11 || options.graphics === GraphicsApi_1.GraphicsApi.Direct3D12) {
							 | 
						||
| 
								 | 
							
								                    return 'd3d11';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (options.graphics === GraphicsApi_1.GraphicsApi.Direct3D9) {
							 | 
						||
| 
								 | 
							
								                    return 'd3d9';
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else {
							 | 
						||
| 
								 | 
							
								                    throw new Error('Unsupported shader language.');
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            case Platform_1.Platform.FreeBSD:
							 | 
						||
| 
								 | 
							
								                return 'glsl';
							 | 
						||
| 
								 | 
							
								            default:
							 | 
						||
| 
								 | 
							
								                return platform;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    watch(watch, match, options, recompileAll) {
							 | 
						||
| 
								 | 
							
								        return new Promise((resolve, reject) => {
							 | 
						||
| 
								 | 
							
								            let shaders = [];
							 | 
						||
| 
								 | 
							
								            let ready = false;
							 | 
						||
| 
								 | 
							
								            this.watcher = chokidar.watch(match, { ignored: /[\/\\]\.(git|DS_Store)/, persistent: watch });
							 | 
						||
| 
								 | 
							
								            this.watcher.on('add', (filepath) => {
							 | 
						||
| 
								 | 
							
								                let file = path.parse(filepath);
							 | 
						||
| 
								 | 
							
								                if (ready) {
							 | 
						||
| 
								 | 
							
								                    switch (file.ext) {
							 | 
						||
| 
								 | 
							
								                        case '.glsl':
							 | 
						||
| 
								 | 
							
								                            if (!file.name.endsWith('.inc') && this.isSupported(file.name)) {
							 | 
						||
| 
								 | 
							
								                                log.info('Compiling ' + file.name);
							 | 
						||
| 
								 | 
							
								                                this.compileShader(filepath, options, recompileAll);
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else {
							 | 
						||
| 
								 | 
							
								                    switch (file.ext) {
							 | 
						||
| 
								 | 
							
								                        case '.glsl':
							 | 
						||
| 
								 | 
							
								                            if (!file.name.endsWith('.inc')) {
							 | 
						||
| 
								 | 
							
								                                shaders.push(filepath);
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								            if (watch) {
							 | 
						||
| 
								 | 
							
								                this.watcher.on('change', (filepath) => {
							 | 
						||
| 
								 | 
							
								                    let file = path.parse(filepath);
							 | 
						||
| 
								 | 
							
								                    switch (file.ext) {
							 | 
						||
| 
								 | 
							
								                        case '.glsl':
							 | 
						||
| 
								 | 
							
								                            if (!file.name.endsWith('.inc') && this.isSupported(file.name)) {
							 | 
						||
| 
								 | 
							
								                                log.info('Recompiling ' + file.name);
							 | 
						||
| 
								 | 
							
								                                this.compileShader(filepath, options, recompileAll);
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            this.watcher.on('unlink', (file) => {
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								            this.watcher.on('ready', async () => {
							 | 
						||
| 
								 | 
							
								                ready = true;
							 | 
						||
| 
								 | 
							
								                let compiledShaders = [];
							 | 
						||
| 
								 | 
							
								                const self = this;
							 | 
						||
| 
								 | 
							
								                async function compile(shader, index) {
							 | 
						||
| 
								 | 
							
								                    let parsed = path.parse(shader);
							 | 
						||
| 
								 | 
							
								                    if (self.isSupported(shader)) {
							 | 
						||
| 
								 | 
							
								                        log.info('Compiling shader ' + (index + 1) + ' of ' + shaders.length + ' (' + parsed.base + ').');
							 | 
						||
| 
								 | 
							
								                        let compiledShader = null;
							 | 
						||
| 
								 | 
							
								                        try {
							 | 
						||
| 
								 | 
							
								                            compiledShader = await self.compileShader(shader, options, recompileAll);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        catch (error) {
							 | 
						||
| 
								 | 
							
								                            log.error('Compiling shader ' + (index + 1) + ' of ' + shaders.length + ' (' + parsed.base + ') failed:');
							 | 
						||
| 
								 | 
							
								                            log.error(error);
							 | 
						||
| 
								 | 
							
								                            return Promise.reject(error);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        if (compiledShader === null) {
							 | 
						||
| 
								 | 
							
								                            compiledShader = new CompiledShader();
							 | 
						||
| 
								 | 
							
								                            compiledShader.noembed = options.noembed;
							 | 
						||
| 
								 | 
							
								                            // mark variables as invalid, so they are loaded from previous compilation
							 | 
						||
| 
								 | 
							
								                            compiledShader.files = null;
							 | 
						||
| 
								 | 
							
								                            compiledShader.inputs = null;
							 | 
						||
| 
								 | 
							
								                            compiledShader.outputs = null;
							 | 
						||
| 
								 | 
							
								                            compiledShader.uniforms = null;
							 | 
						||
| 
								 | 
							
								                            compiledShader.types = null;
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        if (compiledShader.files != null && compiledShader.files.length === 0) {
							 | 
						||
| 
								 | 
							
								                            // TODO: Remove when krafix has been recompiled everywhere
							 | 
						||
| 
								 | 
							
								                            compiledShader.files.push(parsed.name + '.' + self.type);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        compiledShader.name = AssetConverter_1.AssetConverter.createExportInfo(parsed, false, options, self.exporter.options.from).name;
							 | 
						||
| 
								 | 
							
								                        compiledShaders.push(compiledShader);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    else {
							 | 
						||
| 
								 | 
							
								                        log.info('Skipping shader ' + (index + 1) + ' of ' + shaders.length + ' (' + parsed.base + ').');
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    ++index;
							 | 
						||
| 
								 | 
							
								                    return Promise.resolve();
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                if (this.options.parallelAssetConversion !== 0) {
							 | 
						||
| 
								 | 
							
								                    let todo = shaders.map((shader, index) => {
							 | 
						||
| 
								 | 
							
								                        return async () => {
							 | 
						||
| 
								 | 
							
								                            await compile(shader, index);
							 | 
						||
| 
								 | 
							
								                        };
							 | 
						||
| 
								 | 
							
								                    });
							 | 
						||
| 
								 | 
							
								                    let processes = this.options.parallelAssetConversion === -1
							 | 
						||
| 
								 | 
							
								                        ? require('os').cpus().length - 1
							 | 
						||
| 
								 | 
							
								                        : this.options.parallelAssetConversion;
							 | 
						||
| 
								 | 
							
								                    await Throttle.all(todo, {
							 | 
						||
| 
								 | 
							
								                        maxInProgress: processes,
							 | 
						||
| 
								 | 
							
								                    });
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else {
							 | 
						||
| 
								 | 
							
								                    let index = 0;
							 | 
						||
| 
								 | 
							
								                    for (let shader of shaders) {
							 | 
						||
| 
								 | 
							
								                        try {
							 | 
						||
| 
								 | 
							
								                            await compile(shader, index);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        catch (err) {
							 | 
						||
| 
								 | 
							
								                            reject();
							 | 
						||
| 
								 | 
							
								                            return;
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        index += 1;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                resolve(compiledShaders);
							 | 
						||
| 
								 | 
							
								                return;
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    async run(watch, recompileAll) {
							 | 
						||
| 
								 | 
							
								        let shaders = [];
							 | 
						||
| 
								 | 
							
								        for (let matcher of this.shaderMatchers) {
							 | 
						||
| 
								 | 
							
								            shaders = shaders.concat(await this.watch(watch, matcher.match, matcher.options, recompileAll));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return shaders;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    isSupported(file) {
							 | 
						||
| 
								 | 
							
								        if (file.endsWith('.frag.glsl') || file.endsWith('.vert.glsl')) {
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return this.type !== 'essl' && this.type !== 'agal';
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    compileShader(file, options, recompile) {
							 | 
						||
| 
								 | 
							
								        return new Promise((resolve, reject) => {
							 | 
						||
| 
								 | 
							
								            if (!this.compiler)
							 | 
						||
| 
								 | 
							
								                reject('No shader compiler found.');
							 | 
						||
| 
								 | 
							
								            if (this.type === 'none') {
							 | 
						||
| 
								 | 
							
								                resolve(new CompiledShader());
							 | 
						||
| 
								 | 
							
								                return;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            let fileinfo = path.parse(file);
							 | 
						||
| 
								 | 
							
								            let from = file;
							 | 
						||
| 
								 | 
							
								            let to = path.join(this.to, fileinfo.name + '.' + this.type);
							 | 
						||
| 
								 | 
							
								            let temp = to + '.temp';
							 | 
						||
| 
								 | 
							
								            fs.stat(from, (fromErr, fromStats) => {
							 | 
						||
| 
								 | 
							
								                fs.stat(to, (toErr, toStats) => {
							 | 
						||
| 
								 | 
							
								                    if (options.noprocessing) {
							 | 
						||
| 
								 | 
							
								                        if (!toStats || toStats.mtime.getTime() < fromStats.mtime.getTime()) {
							 | 
						||
| 
								 | 
							
								                            fs.copySync(from, to, { overwrite: true });
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        let compiledShader = new CompiledShader();
							 | 
						||
| 
								 | 
							
								                        compiledShader.noembed = options.noembed;
							 | 
						||
| 
								 | 
							
								                        resolve(compiledShader);
							 | 
						||
| 
								 | 
							
								                        return;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    fs.stat(this.compiler, (compErr, compStats) => {
							 | 
						||
| 
								 | 
							
								                        if (!recompile && (fromErr || (!toErr && toStats.mtime.getTime() > fromStats.mtime.getTime() && toStats.mtime.getTime() > compStats.mtime.getTime()))) {
							 | 
						||
| 
								 | 
							
								                            if (fromErr)
							 | 
						||
| 
								 | 
							
								                                log.error('Shader compiler error: ' + fromErr);
							 | 
						||
| 
								 | 
							
								                            resolve(null);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        else {
							 | 
						||
| 
								 | 
							
								                            if (this.type === 'metal' && this.platform !== Platform_1.Platform.Krom) {
							 | 
						||
| 
								 | 
							
								                                fs.ensureDirSync(path.join(this.builddir, 'Sources'));
							 | 
						||
| 
								 | 
							
								                                let funcname = fileinfo.name;
							 | 
						||
| 
								 | 
							
								                                funcname = funcname.replace(/-/g, '_');
							 | 
						||
| 
								 | 
							
								                                funcname = funcname.replace(/\./g, '_');
							 | 
						||
| 
								 | 
							
								                                funcname += '_main';
							 | 
						||
| 
								 | 
							
								                                fs.writeFileSync(to, '>' + funcname, 'utf8');
							 | 
						||
| 
								 | 
							
								                                to = path.join(this.builddir, 'Sources', fileinfo.name + '.' + this.type);
							 | 
						||
| 
								 | 
							
								                                temp = to;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            let parameters = [this.type === 'hlsl' ? 'd3d9' : this.type, from, temp, this.temp, this.platform];
							 | 
						||
| 
								 | 
							
								                            if (this.options.shaderversion) {
							 | 
						||
| 
								 | 
							
								                                parameters.push('--version');
							 | 
						||
| 
								 | 
							
								                                parameters.push(this.options.shaderversion);
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            else if (this.platform === Platform_1.Platform.Krom && os.platform() === 'linux') {
							 | 
						||
| 
								 | 
							
								                                parameters.push('--version');
							 | 
						||
| 
								 | 
							
								                                parameters.push('110');
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            if (this.options.glsl2) {
							 | 
						||
| 
								 | 
							
								                                parameters.push('--glsl2');
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            if (this.options.debug) {
							 | 
						||
| 
								 | 
							
								                                parameters.push('--debug');
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            if (options.defines) {
							 | 
						||
| 
								 | 
							
								                                for (let define of options.defines) {
							 | 
						||
| 
								 | 
							
								                                    parameters.push('-D' + define);
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            if (this.platform === Platform_1.Platform.HTML5 || this.platform === Platform_1.Platform.HTML5Worker || this.platform === Platform_1.Platform.Android) {
							 | 
						||
| 
								 | 
							
								                                parameters.push('--relax');
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            parameters[1] = path.resolve(parameters[1]);
							 | 
						||
| 
								 | 
							
								                            parameters[2] = path.resolve(parameters[2]);
							 | 
						||
| 
								 | 
							
								                            parameters[3] = path.resolve(parameters[3]);
							 | 
						||
| 
								 | 
							
								                            let child = child_process.spawn(this.compiler, parameters);
							 | 
						||
| 
								 | 
							
								                            let errorLine = '';
							 | 
						||
| 
								 | 
							
								                            let newErrorLine = true;
							 | 
						||
| 
								 | 
							
								                            let errorData = false;
							 | 
						||
| 
								 | 
							
								                            let compiledShader = new CompiledShader();
							 | 
						||
| 
								 | 
							
								                            compiledShader.noembed = options.noembed;
							 | 
						||
| 
								 | 
							
								                            function parseData(data) {
							 | 
						||
| 
								 | 
							
								                                data = data.replace(':\\', '#\\'); // Filter out absolute paths on Windows
							 | 
						||
| 
								 | 
							
								                                let parts = data.split(':');
							 | 
						||
| 
								 | 
							
								                                if (parts.length >= 3) {
							 | 
						||
| 
								 | 
							
								                                    if (parts[0] === 'uniform') {
							 | 
						||
| 
								 | 
							
								                                        compiledShader.uniforms.push({ name: parts[1], type: parts[2] });
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    else if (parts[0] === 'input') {
							 | 
						||
| 
								 | 
							
								                                        compiledShader.inputs.push({ name: parts[1], type: parts[2] });
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    else if (parts[0] === 'output') {
							 | 
						||
| 
								 | 
							
								                                        compiledShader.outputs.push({ name: parts[1], type: parts[2] });
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    else if (parts[0] === 'type') {
							 | 
						||
| 
								 | 
							
								                                        let type = data.substring(data.indexOf(':') + 1);
							 | 
						||
| 
								 | 
							
								                                        let name = type.substring(0, type.indexOf(':'));
							 | 
						||
| 
								 | 
							
								                                        let typedata = type.substring(type.indexOf(':') + 2);
							 | 
						||
| 
								 | 
							
								                                        typedata = typedata.substr(0, typedata.length - 1);
							 | 
						||
| 
								 | 
							
								                                        let members = typedata.split(',');
							 | 
						||
| 
								 | 
							
								                                        let memberdecls = [];
							 | 
						||
| 
								 | 
							
								                                        for (let member of members) {
							 | 
						||
| 
								 | 
							
								                                            let memberparts = member.split(':');
							 | 
						||
| 
								 | 
							
								                                            memberdecls.push({ type: memberparts[1], name: memberparts[0] });
							 | 
						||
| 
								 | 
							
								                                        }
							 | 
						||
| 
								 | 
							
								                                        compiledShader.types.push({ name: name, members: memberdecls });
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                                else if (parts.length >= 2) {
							 | 
						||
| 
								 | 
							
								                                    if (parts[0] === 'file') {
							 | 
						||
| 
								 | 
							
								                                        const parsed = path.parse(parts[1].replace('#\\', ':\\'));
							 | 
						||
| 
								 | 
							
								                                        let name = parsed.name;
							 | 
						||
| 
								 | 
							
								                                        if (parsed.ext !== '.temp')
							 | 
						||
| 
								 | 
							
								                                            name += parsed.ext;
							 | 
						||
| 
								 | 
							
								                                        compiledShader.files.push(name);
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            let stdOutString = '';
							 | 
						||
| 
								 | 
							
								                            child.stdout.on('data', (data) => {
							 | 
						||
| 
								 | 
							
								                                stdOutString += data.toString();
							 | 
						||
| 
								 | 
							
								                            });
							 | 
						||
| 
								 | 
							
								                            child.stderr.on('data', (data) => {
							 | 
						||
| 
								 | 
							
								                                let str = data.toString();
							 | 
						||
| 
								 | 
							
								                                for (let char of str) {
							 | 
						||
| 
								 | 
							
								                                    if (char === '\n') {
							 | 
						||
| 
								 | 
							
								                                        if (errorData) {
							 | 
						||
| 
								 | 
							
								                                            parseData(errorLine.trim());
							 | 
						||
| 
								 | 
							
								                                        }
							 | 
						||
| 
								 | 
							
								                                        else {
							 | 
						||
| 
								 | 
							
								                                            log.error(errorLine.trim());
							 | 
						||
| 
								 | 
							
								                                        }
							 | 
						||
| 
								 | 
							
								                                        errorLine = '';
							 | 
						||
| 
								 | 
							
								                                        newErrorLine = true;
							 | 
						||
| 
								 | 
							
								                                        errorData = false;
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    else if (newErrorLine && char === '#') {
							 | 
						||
| 
								 | 
							
								                                        errorData = true;
							 | 
						||
| 
								 | 
							
								                                        newErrorLine = false;
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    else {
							 | 
						||
| 
								 | 
							
								                                        errorLine += char;
							 | 
						||
| 
								 | 
							
								                                        newErrorLine = false;
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            });
							 | 
						||
| 
								 | 
							
								                            child.on('close', (code) => {
							 | 
						||
| 
								 | 
							
								                                if (stdOutString) {
							 | 
						||
| 
								 | 
							
								                                    if (code === 0) {
							 | 
						||
| 
								 | 
							
								                                        log.info(stdOutString);
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    else {
							 | 
						||
| 
								 | 
							
								                                        log.error(stdOutString);
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                                if (errorLine.trim().length > 0) {
							 | 
						||
| 
								 | 
							
								                                    if (errorData) {
							 | 
						||
| 
								 | 
							
								                                        parseData(errorLine.trim());
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    else {
							 | 
						||
| 
								 | 
							
								                                        log.error(errorLine.trim());
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                                if (code === 0) {
							 | 
						||
| 
								 | 
							
								                                    if (this.type !== 'metal' || this.platform === Platform_1.Platform.Krom) {
							 | 
						||
| 
								 | 
							
								                                        if (compiledShader.files === null || compiledShader.files.length === 0) {
							 | 
						||
| 
								 | 
							
								                                            fs.renameSync(temp, to);
							 | 
						||
| 
								 | 
							
								                                        }
							 | 
						||
| 
								 | 
							
								                                        for (let file of compiledShader.files) {
							 | 
						||
| 
								 | 
							
								                                            fs.renameSync(path.join(this.to, file + '.temp'), path.join(this.to, file));
							 | 
						||
| 
								 | 
							
								                                        }
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    resolve(compiledShader);
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                                else {
							 | 
						||
| 
								 | 
							
								                                    process.exitCode = 1;
							 | 
						||
| 
								 | 
							
								                                    reject('Shader compiler error.');
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            });
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    });
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								exports.ShaderCompiler = ShaderCompiler;
							 | 
						||
| 
								 | 
							
								//# sourceMappingURL=ShaderCompiler.js.map
							 |