/*
All material copyright Esri, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/5.0/esri/copyright.txt for details.
*/
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"../../../../../webgl/BufferObject.js";import"../../../../../webgl/FramebufferObject.js";import{Program as a}from"../../../../../webgl/Program.js";import"../../../../../../core/has.js";import"../../../../../webgl/Renderbuffer.js";import"../../../../../webgl/Texture.js";import"../../../../../webgl/enums.js";import"../../../../../webgl/Util.js";import{createTexture as i}from"../../textureUtils.js";import{transpileShader as n}from"../../../../../webgl/ShaderTranspiler.js";const s=()=>r.getLogger("esri.views.2d.engine.webgl.shaderGraph.typed.TypedShaderProgram");function f(r,t,o){const a=t.length;if(a!==o){const i=new e("Invalid Uniform",`Invalid length, expected ${o} but got ${a}`,{uniformName:r,values:t});s().errorOnce(i)}}class m{constructor(e,r,t,o,a,i){this.debugName=e,this.vertexShader=r,this.fragmentShader=t,this._locations=o,this._uniformBindings=a,this._transformFeedbackBindings=i,this._vao=null,this._temporaryTextures=[]}destroy(){this._program=t(this._program),this.cleanupTemporaryTextures()}[Symbol.dispose](){this.destroy()}setUniforms(e){this._uniforms=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=[]}bind(e){const r=this._uniforms;if(!this._program){const r=[];for(const e of this._transformFeedbackBindings??[]){const{index:t,propertyKey:o}=e;r[t]=`v_${o}`}this._program=new a(e,this.vertexShader,this.fragmentShader,this._locations,new Map,r)}const t=this._program;e.useProgram(t);for(const a of this._uniformBindings){const{shaderModulePath:n,uniformName:s,uniformType:m,uniformArrayLength:l}=a,c=o(n,r);if(null==c){if("sampler2D"===m)continue;throw new Error(`Failed to find uniform value for ${n}`)}switch("array"===m||"array-2d"===m?a.uniformArrayElementType:m){case"sampler2D":{const{unit:r,texture:o}=c;if(t.setUniform1i(s,r),"type"in o)e.bindTexture(o,r);else{const t=i(e,o.descriptor,o.data);e.bindTexture(t,r)}break}case"int":if(!l){t.setUniform1i(s,c);break}f(a.uniformName,c,l),t.setUniform1iv(s,c);break;case"float":if(!l){t.setUniform1f(s,c);break}f(a.uniformName,c,l),t.setUniform1fv(s,c);break;case"vec2":if(!l){t.setUniform2f(s,c[0],c[1]);break}f(a.uniformName,c,l),t.setUniform2fv(s,c.flat());break;case"vec3":if(!l){t.setUniform3f(s,c[0],c[1],c[2]);break}f(a.uniformName,c,l),t.setUniform3fv(s,c.flat());break;case"vec4":if(!l){t.setUniform4f(s,c[0],c[1],c[2],c[3]);break}f(a.uniformName,c,l),t.setUniform4fv(s,c.flat());break;case"mat3":t.setUniformMatrix3fv(s,c);break;case"mat4":t.setUniformMatrix4fv(s,c);break;default:throw new Error(`Unable to set uniform for type ${m}`)}}}_validateWebGL2(e){const r=e.gl,t=c(r,35633,this.vertexShader);if("error"===t.type)return t;const o=c(r,35632,this.fragmentShader);if("error"===o.type)return o;const a=t.value,i=o.value,n=r.createProgram();if(r.attachShader(n,a),r.attachShader(n,i),r.linkProgram(n),!r.getProgramParameter(n,r.LINK_STATUS)){return{type:"error",error:`Failed to link shader:\nvalidated: ${r.getProgramParameter(n,r.VALIDATE_STATUS)}, gl error ${r.getError()}, vertex: ${r.getShaderParameter(a,r.COMPILE_STATUS)}, fragment: ${r.getShaderParameter(i,r.COMPILE_STATUS)}, info log: ${r.getProgramInfoLog(n)}, vertex source: ${this.vertexShader}, fragment source: ${this.fragmentShader}`}}return r.deleteProgram(n),{type:"ok",value:null}}}function l(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 c(e,r,t){const o=e.createShader(r),a=n(t,r);if(e.shaderSource(o,a),e.compileShader(o),!e.getShaderParameter(o,e.COMPILE_STATUS)){const a=e.getShaderInfoLog(o)??"";let i="";const n=a.split("\n"),s=new Map,f=[];for(const e of n){const r=l(a);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"),a=Math.max(e-2,0),n=Math.min(e+2,o.length);for(let t=a;t!==n;t++){if(i+=`${(t+1).toString().padEnd(4)}${o[t]}\n`,t===e-1){const e=o[t].length;i+="    "+new Array(e).join("^")+"\n";for(const{text:t,offset:o}of r)i+="      "+t.slice(o).trim()+"\n"}}}for(const e of f)i+=e+"\n";const c=`Failed to compile ${35633===r?"vertex":"fragment"} shader:\n\n${i}`;return e.deleteShader(o),{type:"error",error:c}}return{type:"ok",value:o}}export{m as TypedShaderProgram};
