@@ -57,23 +57,78 @@ class WebgpuDebug {
5757     * End the previous error scope, and print errors if any. 
5858     * 
5959     * @param  {WebgpuGraphicsDevice } device - The graphics device. 
60+      * @param  {string } label - The label for the error scope. 
6061     * @param  {...any } args - Additional parameters that form the error message. 
6162     */ 
62-     static  end ( device ,  ...args )  { 
63+     static  async   end ( device ,   label ,  ...args )  { 
6364        const  header  =  WebgpuDebug . _scopes . pop ( ) ; 
6465        const  marker  =  WebgpuDebug . _markers . pop ( ) ; 
6566        Debug . assert ( header ,  'Non matching end.' ) ; 
6667
67-         device . wgpu . popErrorScope ( ) . then ( ( error )  =>  { 
68-             if  ( error )  { 
69-                 const  count  =  WebgpuDebug . _loggedMessages . get ( error . message )  ??  0 ; 
70-                 if  ( count  <  MAX_DUPLICATES )  { 
71-                     const  tooMany  =  count  ===  MAX_DUPLICATES  -  1  ? ' (Too many errors, ignoring this one from now)'  : '' ; 
72-                     WebgpuDebug . _loggedMessages . set ( error . message ,  count  +  1 ) ; 
73-                     console . error ( `WebGPU ${ header }   error: ${ error . message }  ` ,  tooMany ,  'while rendering' ,  marker ,  ...args ) ; 
74-                 } 
68+         const  error  =  await  device . wgpu . popErrorScope ( ) ; 
69+         if  ( error )  { 
70+             const  count  =  WebgpuDebug . _loggedMessages . get ( error . message )  ??  0 ; 
71+             if  ( count  <  MAX_DUPLICATES )  { 
72+                 const  tooMany  =  count  ===  MAX_DUPLICATES  -  1  ? ' (Too many errors, ignoring this one from now)'  : '' ; 
73+                 WebgpuDebug . _loggedMessages . set ( error . message ,  count  +  1 ) ; 
74+                 console . error ( `WebGPU ${ label }   ${ header }   error: ${ error . message }  ` ,  tooMany ,  'while rendering' ,  marker ,  ...args ) ; 
7575            } 
76-         } ) ; 
76+         } 
77+     } 
78+ 
79+     /** 
80+      * Ends the shader validation scope by retrieving and logging any compilation errors 
81+      * or warnings from the shader module. Also handles WebGPU validation errors, while 
82+      * avoiding duplicate error messages. 
83+      * 
84+      * @param  {WebgpuGraphicsDevice } device - The WebGPU graphics device. 
85+      * @param  {GPUShaderModule } shaderModule - The compiled WebGPU shader module. 
86+      * @param  {string } source - The original shader source code. 
87+      * @param  {number } [contextLines] - The number of lines before and after the error to log. 
88+      * @param  {...any } args - Additional parameters providing context about the shader. 
89+      */ 
90+     static  async  endShader ( device ,  shaderModule ,  source ,  contextLines  =  2 ,  ...args )  { 
91+         const  header  =  WebgpuDebug . _scopes . pop ( ) ; 
92+         const  marker  =  WebgpuDebug . _markers . pop ( ) ; 
93+         Debug . assert ( header ,  'Non-matching error scope end.' ) ; 
94+ 
95+         // Capture popErrorScope error (if any) 
96+         const  error  =  await  device . wgpu . popErrorScope ( ) ; 
97+         let  errorMessage  =  '' ; 
98+ 
99+         if  ( error )  { 
100+             errorMessage  +=  `WebGPU ShaderModule creation ${ header }   error: ${ error . message }  ` ; 
101+             errorMessage  +=  ` - While rendering ${ marker }  \n` ; 
102+         } 
103+ 
104+         // Get shader compilation errors 
105+         const  compilationInfo  =  await  shaderModule . getCompilationInfo ( ) ; 
106+ 
107+         if  ( compilationInfo . messages . length  >  0 )  { 
108+             // split source into lines 
109+             const  sourceLines  =  source . split ( '\n' ) ; 
110+ 
111+             compilationInfo . messages . forEach ( ( message ,  index )  =>  { 
112+                 const  {  type,  lineNum,  linePos,  message : msg  }  =  message ; 
113+                 const  lineIndex  =  lineNum  -  1 ;  // Convert to zero-based index 
114+ 
115+                 errorMessage  +=  `\n----- ${ type . toUpperCase ( ) }   ${ index  +  1 }   context: :${ lineNum }  :${ linePos }   ${ type }  : ${ msg }  \n` ; 
116+ 
117+                 // Extract surrounding lines for context 
118+                 const  startLine  =  Math . max ( 0 ,  lineIndex  -  contextLines ) ; 
119+                 const  endLine  =  Math . min ( sourceLines . length ,  lineIndex  +  contextLines  +  1 ) ; 
120+ 
121+                 for  ( let  i  =  startLine ;  i  <  endLine ;  i ++ )  { 
122+                     const  linePrefix  =  i  ===  lineIndex  ? '> '  : '  ' ; 
123+                     errorMessage  +=  `${ linePrefix } ${ i  +  1 }  : ${ sourceLines [ i ] }  \n` ; 
124+                 } 
125+             } ) ; 
126+         } 
127+ 
128+         // only log if there are errors or messages 
129+         if  ( errorMessage )  { 
130+             console . error ( errorMessage ,  ...args ) ; 
131+         } 
77132    } 
78133} 
79134
0 commit comments