/* COPYRIGHT Esri - https://js.arcgis.com/5.1.2/LICENSE.txt */
import e from"../../../../../../core/Error.js";import r from"../../../../../../core/Logger.js";import{disposeMaybe as t}from"../../../../../../core/maybe.js";import{getDeepValue as o}from"../../../../../../core/object.js";import{createTexture as i}from"../../textureUtils.js";import{DisposableProgram as n}from"../../../../../webgl/Program.js";import{transpileShader as a}from"../../../../../webgl/ShaderTranspiler.js";const s=()=>r.getLogger("esri.views.2d.engine.webgl.shaderGraph.typed.TypedShaderProgram");function f(r,t,o){const i=t.length;if(i!==o){const n=new e("Invalid Uniform",`Invalid length, expected ${o} but got ${i}`,{uniformName:r,values:t});s().errorOnce(n)}}class m{constructor(e,r,t,o,i,n,a){this.debugName=e,this.vertexShader=r,this.fragmentShader=t,this._locations=o,this._uniformBindings=i,this._textureBindings=n,this._transformFeedbackBindings=a,this._vao=null,this._temporaryTextures=[]}destroy(){this._program=t(this._program),this.cleanupTemporaryTextures()}[Symbol.dispose](){this.destroy()}setUniforms(e){this._uniforms=e}setTextures(e){this._textures=e}validate(e){if(!this._validation){const r=this._validateWebGL2(e);"error"===r.type&&(r.error=`Validation failed for ShaderModule '${this.debugName}'\n${r.error}`),this._validation=r}return this._validation}cleanupTemporaryTextures(){for(const e of this._temporaryTextures)e.dispose();this._temporaryTextures=[]}prepare(e){if(!this._program){const r=[];for(const e of this._transformFeedbackBindings??[]){const{index:t,propertyKey:o}=e;r[t]=`v_${o}`}this._program=new n(e,this.vertexShader,this.fragmentShader,this._locations,new Map,r)}}get compiled(){return this._program?.compiled??!1}bind(e){const r=this._uniforms,t=this._textures;this.prepare(e);const n=this._program;e.useProgram(n);for(const i of this._uniformBindings){const{shaderModulePath:e,uniformName:t,uniformType:a,uniformArrayLength:s}=i,m=o(e,r);if(null==m)throw new Error(`Failed to find uniform value for ${e}`);switch("array"===a||"array-2d"===a?i.uniformArrayElementType:a){case"int":if(!s){n.setUniform1i(t,m);break}f(i.uniformName,m,s),n.setUniform1iv(t,m);break;case"float":if(!s){n.setUniform1f(t,m);break}f(i.uniformName,m,s),n.setUniform1fv(t,m);break;case"vec2":if(!s){n.setUniform2f(t,m[0],m[1]);break}f(i.uniformName,m,s),n.setUniform2fv(t,m.flat());break;case"vec3":if(!s){n.setUniform3f(t,m[0],m[1],m[2]);break}f(i.uniformName,m,s),n.setUniform3fv(t,m.flat());break;case"vec4":if(!s){n.setUniform4f(t,m[0],m[1],m[2],m[3]);break}f(i.uniformName,m,s),n.setUniform4fv(t,m.flat());break;case"mat3":n.setUniformMatrix3fv(t,m);break;case"mat4":n.setUniformMatrix4fv(t,m);break;default:throw new Error(`Unable to set uniform for type ${a}`)}}for(const a of this._textureBindings){const r=o(a.shaderModulePath,t);if(null==r)continue;const{unit:s,texture:f}=r;if(n.setUniform1i(a.textureName,s),"type"in f)e.bindTexture(f,s);else{const r=i(e,f.descriptor,f.data);e.bindTexture(r,s)}}}_validateWebGL2(e){const r=e.gl,t=d(r,35633,this.vertexShader);if("error"===t.type)return t;const o=d(r,35632,this.fragmentShader);if("error"===o.type)return o;const i=t.value,n=o.value,a=r.createProgram();if(r.attachShader(a,i),r.attachShader(a,n),r.linkProgram(a),!r.getProgramParameter(a,r.LINK_STATUS)){return{type:"error",error:`Failed to link shader:\nvalidated: ${r.getProgramParameter(a,r.VALIDATE_STATUS)}, gl error ${r.getError()}, vertex: ${r.getShaderParameter(i,r.COMPILE_STATUS)}, fragment: ${r.getShaderParameter(n,r.COMPILE_STATUS)}, info log: ${r.getProgramInfoLog(a)}, vertex source: ${this.vertexShader}, fragment source: ${this.fragmentShader}`}}return r.deleteProgram(a),{type:"ok",value:null}}}function h(e){const r=e.match(/\d+:(\d+):/);if(void 0!==r?.index&&r?.length>1){const e=r.index+r[0].length;return{lineNumber:parseInt(r[1],10),offset:e}}return null}function d(e,r,t){const o=e.createShader(r),i=a(t,r);if(e.shaderSource(o,i),e.compileShader(o),!e.getShaderParameter(o,e.COMPILE_STATUS)){const i=e.getShaderInfoLog(o)??"";let n="";const a=i.split("\n"),s=new Map,f=[];for(const e of a){const r=h(i);if(!r){f.push(e);continue}let t=s.get(r.lineNumber);t||(t=[],s.set(r.lineNumber,t)),t.push({text:e,offset:r.offset})}const m=Array.from(s.entries()).sort();for(const[e,r]of m){const o=t.split("\n"),i=Math.max(e-2,0),a=Math.min(e+2,o.length);for(let t=i;t!==a;t++){if(n+=`${(t+1).toString().padEnd(4)}${o[t]}\n`,t===e-1){const e=o[t].length;n+="    "+new Array(e).join("^")+"\n";for(const{text:t,offset:o}of r)n+="      "+t.slice(o).trim()+"\n"}}}for(const e of f)n+=e+"\n";const d=`Failed to compile ${35633===r?"vertex":"fragment"} shader:\n\n${n}`;return e.deleteShader(o),{type:"error",error:d}}return{type:"ok",value:o}}export{m as TypedShaderProgram};
