@@ -10,7 +10,9 @@ import {getGlsl} from '../glsl-source';
1010import { WebGLInferenceHandler } from '../inference-handler' ;
1111import { Artifact , ProgramInfo , RunData , TextureLayout , WebGLOperator } from '../types' ;
1212import { WebGLContext } from '../webgl-context' ;
13+
1314import { WebGLConvPacked } from './conv-pack' ;
15+ import { getActicationSnippet } from './fuse-utils' ;
1416
1517export class WebGLConv extends Conv {
1618 unpackedGroupedConvImpl : WebGLUnpackedGroupedConv ;
@@ -66,7 +68,7 @@ export class WebGLUnpackedGroupedConv extends Conv implements WebGLOperator {
6668
6769 createProgramInfo ( handler : WebGLInferenceHandler , inputs : Tensor [ ] ) : ProgramInfo {
6870 const hasBias = inputs . length > 2 ;
69- const processBias = hasBias ? 'dotProd += getBias(output_channel);' : '' ;
71+ const processBias = hasBias ? 'value += getBias(output_channel);' : '' ;
7072 const xShape = inputs [ 0 ] . dims . slice ( ) ;
7173 const wShape = inputs [ 1 ] . dims . slice ( ) ;
7274 const outputChannelsPerGroup = wShape [ 0 ] / this . group ;
@@ -85,18 +87,20 @@ export class WebGLUnpackedGroupedConv extends Conv implements WebGLOperator {
8587 const outputShape = WebGLConv . calcOutputShape ( xShape , wShape , this . dilations , this . pads , this . strides ) ;
8688 const glsl = getGlsl ( handler . session . backend . glContext . version ) ;
8789
90+ const { activationFunction, applyActivation} = getActicationSnippet ( this . activation ) ;
91+
8892 const shaderSource = `
8993 const ivec2 strides = ivec2(${ this . strides [ 0 ] } , ${ this . strides [ 1 ] } );
9094 const ivec2 pads = ivec2(${ this . pads [ 0 ] } , ${ this . pads [ 1 ] } );
91-
95+ ${ activationFunction }
9296 void main() {
9397 ivec4 coords = getOutputCoords();
9498 int batch = coords.x;
9599 int output_channel = coords.y;
96100 ivec2 xRCCorner = coords.zw * strides - pads;
97101 int group_id = output_channel / ${ outputChannelsPerGroup } ;
98102
99- float dotProd = 0.0;
103+ float value = 0.0;
100104 for (int wInChannel = 0; wInChannel < ${ wShape [ 1 ] } ; wInChannel++) {
101105 int input_channel = group_id * ${ wShape [ 1 ] } + wInChannel;
102106 for (int wHeight = 0; wHeight < ${ wShape [ 2 ] } ; wHeight++) {
@@ -114,12 +118,13 @@ export class WebGLUnpackedGroupedConv extends Conv implements WebGLOperator {
114118
115119 float xVal = getX(batch, input_channel, xWidth, xHeight);
116120 float wVal = getW(output_channel, wInChannel, wWidth, wHeight);
117- dotProd += xVal*wVal;
121+ value += xVal*wVal;
118122 }
119123 }
120124 }
121125 ${ processBias }
122- ${ glsl . output } = vec4(dotProd, .0, .0, .0);
126+ ${ applyActivation }
127+ ${ glsl . output } = vec4(value, .0, .0, .0);
123128 }
124129` ;
125130 return {
@@ -215,7 +220,6 @@ export class WebGLUnpackedConv extends Conv {
215220 let blend = false ;
216221 for ( let k = 0 ; k < sharedDim ; k += sharedDimReadSize ) {
217222 Logger . verbose ( 'MatMul2D' , `k = ${ k } , sharedDim: ${ sharedDim } , readSize = ${ sharedDimReadSize } ` ) ;
218-
219223 if ( k === sharedDimReadSize ) {
220224 blend = true ;
221225 gl . enable ( gl . BLEND ) ;
@@ -248,6 +252,7 @@ export class WebGLUnpackedConv extends Conv {
248252 const im2colDims = WebGLUnpackedConv . calcIm2ColDims ( xshape , kshape , outputShape , 4 ) ;
249253 const outputLayout = inferenceHandler . createTextureLayoutFromShape (
250254 im2colDims , 4 , [ im2colDims [ 0 ] , im2colDims [ 1 ] , im2colDims [ 2 ] , im2colDims [ 3 ] * 4 ] , { breakAxis : 3 } ) ;
255+
251256 const shaderSource = `
252257 const int XC = ${ xshape [ 1 ] } ;
253258 const int XH = ${ xshape [ 2 ] } ;
@@ -263,13 +268,12 @@ export class WebGLUnpackedConv extends Conv {
263268 const int KHKW = KH*KW;
264269 const int XCKHKW = XC * KHKW;
265270 const int outputChannels = 4;
266-
267271 vec4 process(int indices[${ rank } ]) {
268272 int b = indices[0]; // batch size
269273 int oh = indices[1] * strideH - padH; //output height
270274 int ow = indices[2] * strideW - padW; //output width
271275 int p = indices[3] * outputChannels; //patch
272- vec4 v = vec4(0.0);
276+ vec4 value = vec4(0.0);
273277 for(int i=0; i < outputChannels; ++i) {
274278 if(p < XCKHKW) {
275279 int patchC = p / KHKW;
@@ -286,12 +290,12 @@ export class WebGLUnpackedConv extends Conv {
286290 xh2 < XH &&
287291 xw2 >= 0 &&
288292 xw2 < XW) {
289- v [i] = _X(x);
293+ value [i] = _X(x);
290294 }
291295 }
292296 ++p;
293297 }
294- return v ;
298+ return value ;
295299 }
296300 ` ;
297301 return {
@@ -321,16 +325,20 @@ export class WebGLUnpackedConv extends Conv {
321325 const outputLayout = inferenceHandler . createTextureLayoutFromShape ( outputShape ) ;
322326 const initValue = ( inputs . length < 3 ) ? '0.0' : '_B(b)' ;
323327 const sharedDim = im2colLayout . shape [ 3 ] ;
324- const blendEnabled = inferenceHandler . session . backend . glContext . isBlendSupported ;
328+ const blendEnabled = inferenceHandler . session . backend . glContext . isBlendSupported && ! this . activation ;
325329 const sharedDimReadSize = blendEnabled && inferenceHandler . session . backend . matmulMaxBatchSize ?
326330 this . calcSharedDimReadSize ( inferenceHandler . session . backend . matmulMaxBatchSize , sharedDim ) :
327331 sharedDim ;
328332 const samplers = [ 'Im2Col' , 'K' ] ;
329333 if ( inputs . length === 3 ) {
330334 samplers . push ( 'B' ) ;
331335 }
336+
337+ const { activationFunction, applyActivation} = getActicationSnippet ( this . activation ) ;
338+
332339 const glsl = getGlsl ( inferenceHandler . session . backend . glContext . version ) ;
333340 const shaderSource = `
341+ ${ activationFunction }
334342 float process(int indices[${ rank } ]) {
335343 int b[1];
336344 b[0] = indices[1];
@@ -341,15 +349,16 @@ export class WebGLUnpackedConv extends Conv {
341349 int im2colOffset = im2col[0] * ${ im2colLayout . strides [ 0 ] } + im2col[1] * ${
342350 im2colLayout . strides [ 1 ] } + im2col[2] * ${ im2colLayout . strides [ 2 ] } + sharedDimOffset;
343351 int kernelOffset = indices[1] * ${ kLayout . strides [ 0 ] } + sharedDimOffset;
344- float sum = sharedDimOffset == 0 ? ${ initValue } : 0.0;
352+ float value = sharedDimOffset == 0 ? ${ initValue } : 0.0;
345353 for (int i = 0; i < ${ sharedDimReadSize } ; ++i) {
346354 vec2 im2colCoords = offsetToCoords(im2colOffset, ${ im2colLayout . width } , ${ im2colLayout . height } );
347355 vec2 kernelCoords = offsetToCoords(kernelOffset, ${ kLayout . width } , ${ kLayout . height } );
348- sum += dot(${ glsl . texture2D } (Im2Col, im2colCoords), ${ glsl . texture2D } (K, kernelCoords));
356+ value += dot(${ glsl . texture2D } (Im2Col, im2colCoords), ${ glsl . texture2D } (K, kernelCoords));
349357 ++im2colOffset;
350358 ++kernelOffset;
351359 }
352- return sum;
360+ ${ applyActivation }
361+ return value;
353362 }` ;
354363 return {
355364 inputLayouts : inputs . length === 3 ? [ im2colLayout , kLayout , bLayout ! ] : [ im2colLayout , kLayout ] ,
0 commit comments