UNPKG

5.17 kBJavaScriptView Raw
1import { ExtensionType, extensions } from '@pixi/extensions';
2import './utils/index.mjs';
3import { generateProgram } from './utils/generateProgram.mjs';
4import { generateUniformBufferSync } from './utils/generateUniformBufferSync.mjs';
5import { unsafeEvalSupported } from './utils/unsafeEvalSupported.mjs';
6import { generateUniformsSync } from './utils/generateUniformsSync.mjs';
7
8let UID = 0;
9const defaultSyncData = { textureCount: 0, uboCount: 0 };
10class ShaderSystem {
11 constructor(renderer) {
12 this.destroyed = false;
13 this.renderer = renderer;
14 this.systemCheck();
15 this.gl = null;
16 this.shader = null;
17 this.program = null;
18 this.cache = {};
19 this._uboCache = {};
20 this.id = UID++;
21 }
22 systemCheck() {
23 if (!unsafeEvalSupported()) {
24 throw new Error("Current environment does not allow unsafe-eval, please use @pixi/unsafe-eval module to enable support.");
25 }
26 }
27 contextChange(gl) {
28 this.gl = gl;
29 this.reset();
30 }
31 bind(shader, dontSync) {
32 shader.disposeRunner.add(this);
33 shader.uniforms.globals = this.renderer.globalUniforms;
34 const program = shader.program;
35 const glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateProgram(shader);
36 this.shader = shader;
37 if (this.program !== program) {
38 this.program = program;
39 this.gl.useProgram(glProgram.program);
40 }
41 if (!dontSync) {
42 defaultSyncData.textureCount = 0;
43 defaultSyncData.uboCount = 0;
44 this.syncUniformGroup(shader.uniformGroup, defaultSyncData);
45 }
46 return glProgram;
47 }
48 setUniforms(uniforms) {
49 const shader = this.shader.program;
50 const glProgram = shader.glPrograms[this.renderer.CONTEXT_UID];
51 shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer);
52 }
53 syncUniformGroup(group, syncData) {
54 const glProgram = this.getGlProgram();
55 if (!group.static || group.dirtyId !== glProgram.uniformDirtyGroups[group.id]) {
56 glProgram.uniformDirtyGroups[group.id] = group.dirtyId;
57 this.syncUniforms(group, glProgram, syncData);
58 }
59 }
60 syncUniforms(group, glProgram, syncData) {
61 const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group);
62 syncFunc(glProgram.uniformData, group.uniforms, this.renderer, syncData);
63 }
64 createSyncGroups(group) {
65 const id = this.getSignature(group, this.shader.program.uniformData, "u");
66 if (!this.cache[id]) {
67 this.cache[id] = generateUniformsSync(group, this.shader.program.uniformData);
68 }
69 group.syncUniforms[this.shader.program.id] = this.cache[id];
70 return group.syncUniforms[this.shader.program.id];
71 }
72 syncUniformBufferGroup(group, name) {
73 const glProgram = this.getGlProgram();
74 if (!group.static || group.dirtyId !== 0 || !glProgram.uniformGroups[group.id]) {
75 group.dirtyId = 0;
76 const syncFunc = glProgram.uniformGroups[group.id] || this.createSyncBufferGroup(group, glProgram, name);
77 group.buffer.update();
78 syncFunc(glProgram.uniformData, group.uniforms, this.renderer, defaultSyncData, group.buffer);
79 }
80 this.renderer.buffer.bindBufferBase(group.buffer, glProgram.uniformBufferBindings[name]);
81 }
82 createSyncBufferGroup(group, glProgram, name) {
83 const { gl } = this.renderer;
84 this.renderer.buffer.bind(group.buffer);
85 const uniformBlockIndex = this.gl.getUniformBlockIndex(glProgram.program, name);
86 glProgram.uniformBufferBindings[name] = this.shader.uniformBindCount;
87 gl.uniformBlockBinding(glProgram.program, uniformBlockIndex, this.shader.uniformBindCount);
88 this.shader.uniformBindCount++;
89 const id = this.getSignature(group, this.shader.program.uniformData, "ubo");
90 let uboData = this._uboCache[id];
91 if (!uboData) {
92 uboData = this._uboCache[id] = generateUniformBufferSync(group, this.shader.program.uniformData);
93 }
94 if (group.autoManage) {
95 const data = new Float32Array(uboData.size / 4);
96 group.buffer.update(data);
97 }
98 glProgram.uniformGroups[group.id] = uboData.syncFunc;
99 return glProgram.uniformGroups[group.id];
100 }
101 getSignature(group, uniformData, preFix) {
102 const uniforms = group.uniforms;
103 const strings = [`${preFix}-`];
104 for (const i in uniforms) {
105 strings.push(i);
106 if (uniformData[i]) {
107 strings.push(uniformData[i].type);
108 }
109 }
110 return strings.join("-");
111 }
112 getGlProgram() {
113 if (this.shader) {
114 return this.shader.program.glPrograms[this.renderer.CONTEXT_UID];
115 }
116 return null;
117 }
118 generateProgram(shader) {
119 const gl = this.gl;
120 const program = shader.program;
121 const glProgram = generateProgram(gl, program);
122 program.glPrograms[this.renderer.CONTEXT_UID] = glProgram;
123 return glProgram;
124 }
125 reset() {
126 this.program = null;
127 this.shader = null;
128 }
129 disposeShader(shader) {
130 if (this.shader === shader) {
131 this.shader = null;
132 }
133 }
134 destroy() {
135 this.renderer = null;
136 this.destroyed = true;
137 }
138}
139ShaderSystem.extension = {
140 type: ExtensionType.RendererSystem,
141 name: "shader"
142};
143extensions.add(ShaderSystem);
144
145export { ShaderSystem };
146//# sourceMappingURL=ShaderSystem.mjs.map