@pixi/core
Version:
Core PixiJS
151 lines (146 loc) • 5.34 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var extensions = require('@pixi/extensions');
require('./utils/index.js');
var generateProgram = require('./utils/generateProgram.js');
var generateUniformBufferSync = require('./utils/generateUniformBufferSync.js');
var unsafeEvalSupported = require('./utils/unsafeEvalSupported.js');
var generateUniformsSync = require('./utils/generateUniformsSync.js');
let UID = 0;
const defaultSyncData = { textureCount: 0, uboCount: 0 };
class ShaderSystem {
constructor(renderer) {
this.destroyed = false;
this.renderer = renderer;
this.systemCheck();
this.gl = null;
this.shader = null;
this.program = null;
this.cache = {};
this._uboCache = {};
this.id = UID++;
}
systemCheck() {
if (!unsafeEvalSupported.unsafeEvalSupported()) {
throw new Error("Current environment does not allow unsafe-eval, please use @pixi/unsafe-eval module to enable support.");
}
}
contextChange(gl) {
this.gl = gl;
this.reset();
}
bind(shader, dontSync) {
shader.disposeRunner.add(this);
shader.uniforms.globals = this.renderer.globalUniforms;
const program = shader.program;
const glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateProgram(shader);
this.shader = shader;
if (this.program !== program) {
this.program = program;
this.gl.useProgram(glProgram.program);
}
if (!dontSync) {
defaultSyncData.textureCount = 0;
defaultSyncData.uboCount = 0;
this.syncUniformGroup(shader.uniformGroup, defaultSyncData);
}
return glProgram;
}
setUniforms(uniforms) {
const shader = this.shader.program;
const glProgram = shader.glPrograms[this.renderer.CONTEXT_UID];
shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer);
}
syncUniformGroup(group, syncData) {
const glProgram = this.getGlProgram();
if (!group.static || group.dirtyId !== glProgram.uniformDirtyGroups[group.id]) {
glProgram.uniformDirtyGroups[group.id] = group.dirtyId;
this.syncUniforms(group, glProgram, syncData);
}
}
syncUniforms(group, glProgram, syncData) {
const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group);
syncFunc(glProgram.uniformData, group.uniforms, this.renderer, syncData);
}
createSyncGroups(group) {
const id = this.getSignature(group, this.shader.program.uniformData, "u");
if (!this.cache[id]) {
this.cache[id] = generateUniformsSync.generateUniformsSync(group, this.shader.program.uniformData);
}
group.syncUniforms[this.shader.program.id] = this.cache[id];
return group.syncUniforms[this.shader.program.id];
}
syncUniformBufferGroup(group, name) {
const glProgram = this.getGlProgram();
if (!group.static || group.dirtyId !== 0 || !glProgram.uniformGroups[group.id]) {
group.dirtyId = 0;
const syncFunc = glProgram.uniformGroups[group.id] || this.createSyncBufferGroup(group, glProgram, name);
group.buffer.update();
syncFunc(glProgram.uniformData, group.uniforms, this.renderer, defaultSyncData, group.buffer);
}
this.renderer.buffer.bindBufferBase(group.buffer, glProgram.uniformBufferBindings[name]);
}
createSyncBufferGroup(group, glProgram, name) {
const { gl } = this.renderer;
this.renderer.buffer.bind(group.buffer);
const uniformBlockIndex = this.gl.getUniformBlockIndex(glProgram.program, name);
glProgram.uniformBufferBindings[name] = this.shader.uniformBindCount;
gl.uniformBlockBinding(glProgram.program, uniformBlockIndex, this.shader.uniformBindCount);
this.shader.uniformBindCount++;
const id = this.getSignature(group, this.shader.program.uniformData, "ubo");
let uboData = this._uboCache[id];
if (!uboData) {
uboData = this._uboCache[id] = generateUniformBufferSync.generateUniformBufferSync(group, this.shader.program.uniformData);
}
if (group.autoManage) {
const data = new Float32Array(uboData.size / 4);
group.buffer.update(data);
}
glProgram.uniformGroups[group.id] = uboData.syncFunc;
return glProgram.uniformGroups[group.id];
}
getSignature(group, uniformData, preFix) {
const uniforms = group.uniforms;
const strings = [`${preFix}-`];
for (const i in uniforms) {
strings.push(i);
if (uniformData[i]) {
strings.push(uniformData[i].type);
}
}
return strings.join("-");
}
getGlProgram() {
if (this.shader) {
return this.shader.program.glPrograms[this.renderer.CONTEXT_UID];
}
return null;
}
generateProgram(shader) {
const gl = this.gl;
const program = shader.program;
const glProgram = generateProgram.generateProgram(gl, program);
program.glPrograms[this.renderer.CONTEXT_UID] = glProgram;
return glProgram;
}
reset() {
this.program = null;
this.shader = null;
}
disposeShader(shader) {
if (this.shader === shader) {
this.shader = null;
}
}
destroy() {
this.renderer = null;
this.destroyed = true;
}
}
ShaderSystem.extension = {
type: extensions.ExtensionType.RendererSystem,
name: "shader"
};
extensions.extensions.add(ShaderSystem);
exports.ShaderSystem = ShaderSystem;
//# sourceMappingURL=ShaderSystem.js.map