Skip to content

Commit a59a6a9

Browse files
committed
refactor(webgl): change nhwc dataLayout to nchw
1 parent 33b44c0 commit a59a6a9

File tree

13 files changed

+125
-234
lines changed

13 files changed

+125
-234
lines changed

e2e/dist/assets/imgs/seg.png

-620 Bytes
Loading

e2e/tests/humanseg.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ describe('e2e test humanseg model', () => {
4040
return diffPixelsNum / backImageData.length;
4141
});
4242

43-
const expectedMAP = 0.02;
43+
const expectedMAP = 0.05;
4444
await expect(mAP).toBeLessThanOrEqual(expectedMAP);
4545
});
4646
});

packages/paddlejs-backend-webgl/src/backend.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { GLTexture, TextureConfig } from './webgl/WebGLTexture';
1010
import { vShaderSource, vShaderData } from './ops/vShader';
1111
import buildShader from './webgl/buildShader';
1212
import GLProgram from './webgl/WebGLProgram';
13-
import { getSizeFromShape, nhwc2nchw } from './utils/dataProcess';
13+
import { getSizeFromShape } from './utils/dataProcess';
1414
import queryProcess from './utils/queryProcess';
1515

1616
export default class WebGLBackend extends PaddlejsBackend {
@@ -157,19 +157,13 @@ export default class WebGLBackend extends PaddlejsBackend {
157157
const pbo = this.createPBO();
158158
await this.createAndWaitForFence();
159159
const result = this.downloadFloat32TensorFromBuffer(pbo);
160-
let shape = fetchInfo ? fetchInfo.shape : [];
161160

161+
const shape = fetchInfo ? fetchInfo.shape : [];
162162
if (env.get('webgl_pack_output')) {
163163
return result.slice(0, getSizeFromShape(shape));
164164
}
165165

166-
shape = env.get('debug') && env.get('shape')
167-
? env.get('shape')
168-
: (this.program as GLProgram).shape as number[];
169-
170-
const [N, C, H, W] = shape;
171-
const nhwcFetchShape = [N, H, W, C];
172-
return nhwc2nchw(result, nhwcFetchShape);
166+
return result;
173167
}
174168

175169
createPBO() {

packages/paddlejs-backend-webgl/src/ops/atom/common_func_with_texture.ts

Lines changed: 23 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -3,159 +3,52 @@
33
* @author yueshuangyan
44
*/
55

6-
import { GLHelper } from '../../webgl/WebGLUtils';
7-
8-
function getValueFromTensorPosNoLimit(textureName: string, { channel, height_shape, width_texture, height_texture }) {
9-
return `
10-
// 根据tensor坐标获取这个tensor位置的值
11-
float getValueFromTensorPos_${textureName}(int r, int g, int b, int a) {
12-
vec4 pixels = TEXTURE2D(texture_${textureName},
13-
vec2(
14-
(float(a * ${channel} + g) + 0.5) / float(${width_texture}),
15-
(float(r * ${height_shape} + b) + 0.5) / float(${height_texture})
16-
)
17-
);
18-
// 只用了r通道
19-
return pixels.r;
20-
}`;
21-
}
22-
23-
function getValueFromTensorPosPackingNoLimit(
24-
textureName: string,
25-
{ channel, height_shape, width_texture, height_texture }
26-
) {
27-
return `
28-
// 根据tensor坐标获取这个tensor位置的值
29-
vec4 getValueFromTensorPosPacking_${textureName}(int r, int g, int b, int a) {
30-
vec4 pixels = TEXTURE2D(texture_${textureName},
31-
vec2(
32-
(float(a * ${channel} + g) + 0.5) / float(${width_texture}),
33-
(float(r * ${height_shape} + b) + 0.5) / float(${height_texture})
34-
)
35-
);
36-
return pixels;
37-
}`;
38-
}
39-
40-
function genOffsetYIfConditions(cut, height) {
41-
const curIndexArr = Array.from({ length: cut }, (_, i) => i).reverse();
42-
43-
return curIndexArr.reduce((acc, cur, idx) => {
44-
const curIf = cur > 0
45-
? idx === 0
46-
? `
47-
if (float(a) / float(pieceW) >= float(${cur})) {
48-
offsetY = int(${cur}) * ${height};
49-
}
50-
`
51-
: `
52-
else if (float(a) / float(pieceW) >= float(${cur})) {
53-
offsetY = int(${cur}) * ${height};
54-
}
55-
`
56-
: '';
57-
return acc + curIf;
58-
}, '');
59-
}
60-
61-
function getValueFromTensorPosLimit(
6+
export function getValueFromTensorPos(
627
textureName: string,
638
{ width_shape, height_shape, channel, width_texture, height_texture }
649
) {
65-
const limitCut = GLHelper.getWebglTextureLimitCut();
10+
const chw = width_shape * height_shape * channel;
11+
const hw = width_shape * height_shape;
6612
return `
67-
// 超限布局根据tensor坐标获取这个tensor位置的值
68-
float getValueFromTensorPos_${textureName}(int r, int g, int b, int a) {
69-
int limitCut = ${limitCut};
70-
int pieceW = calCeil(${width_shape}, ${limitCut});
71-
int x = calMod(a, pieceW);
72-
int offsetY = 0;
73-
74-
${genOffsetYIfConditions(limitCut, height_shape)}
75-
13+
// 根据tensor坐标获取这个tensor位置的值
14+
float getValueFromTensorPos_${textureName}(int n, int c, int h, int w) {
15+
int index = n * ${chw} + c * ${hw} + h * ${width_shape} + w;
16+
int pos_w = int(mod(float(index), float(${width_texture})));
17+
int pos_h = index / int(${width_texture});
7618
vec4 pixels = TEXTURE2D(texture_${textureName},
7719
vec2(
78-
(float(x * ${channel} + g) + 0.5) / float(${width_texture}),
79-
(float(r * limitCut * ${height_shape} + b + offsetY) + 0.5) / float(${height_texture})
20+
(float(pos_w) + 0.5) / float(${width_texture}),
21+
(float(pos_h) + 0.5) / float(${height_texture})
8022
)
8123
);
24+
// 只用了r通道
8225
return pixels.r;
8326
}`;
8427
}
8528

86-
function getValueFromTensorPosPackingLimit(
29+
export function getValueFromTensorPosPacking(
8730
textureName: string,
88-
{ width_shape, height_shape, channel, width_texture, height_texture }
31+
{ channel, height_shape, width_texture, height_texture, width_shape }
8932
) {
33+
const chw = width_shape * height_shape * channel;
34+
const hw = width_shape * height_shape;
9035
return `
91-
// 超限布局根据tensor坐标获取这个tensor位置的值
92-
vec4 getValueFromTensorPosPacking_${textureName}(int r, int g, int b, int a) {
93-
float pieceW = ceil(float(${width_shape}) / 4.0);
94-
int x = calMod(a, int(pieceW));
95-
int offsetY = 0;
96-
97-
if ((float(a) / pieceW) >= 3.0) {
98-
offsetY = 3 * ${height_shape};
99-
}
100-
else if (float(a) / pieceW >= 2.0) {
101-
offsetY = 2 * ${height_shape};
102-
}
103-
else if (float(a) >= pieceW) {
104-
offsetY = ${height_shape};
105-
}
36+
// 根据tensor坐标获取这个tensor位置的值
37+
vec4 getValueFromTensorPosPacking_${textureName}(int n, int c, int h, int w) {
38+
int index = n * ${chw} + c * ${hw} + h * ${width_shape} + w;
39+
int pos_w = int(mod(float(index), float(${width_texture})));
40+
int pos_h = index / int(${width_texture});
10641
vec4 pixels = TEXTURE2D(texture_${textureName},
10742
vec2(
108-
(float(x * ${channel} + g) + 0.5) / float(${width_texture}),
109-
(float(r * 4 * ${height_shape} + b + offsetY) + 0.5) / float(${height_texture})
43+
(float(pos_w) + 0.5) / float(${width_texture}),
44+
(float(pos_h) + 0.5) / float(${height_texture})
11045
)
11146
);
47+
// 只用了r通道
11248
return pixels;
11349
}`;
11450
}
11551

116-
export function getValueFromTensorPos(textureName: string, textureParams) {
117-
return textureParams.limit
118-
? getValueFromTensorPosLimit(textureName, textureParams)
119-
: getValueFromTensorPosNoLimit(textureName, textureParams);
120-
}
121-
122-
export function getValueFromTensorPosPacking(textureName: string, textureParams) {
123-
return textureParams.limit
124-
? getValueFromTensorPosPackingLimit(textureName, textureParams)
125-
: getValueFromTensorPosPackingNoLimit(textureName, textureParams);
126-
127-
}
128-
129-
export function getValueFromTensorPosPacked(
130-
textureName: string,
131-
{ offset_y, height_shape, width_texture, height_texture }
132-
) {
133-
return `
134-
// 超限布局根据tensor坐标获取这个tensor位置的值
135-
float getValueFromTensorPosPacked_${textureName}(int r, int g, int b, int a) {
136-
int y = b / 2;
137-
int yOffset = calMod(b, 2);
138-
int x = a / 2;
139-
int xOffset = calMod(a, 2);
140-
int height = ${height_shape} + ${offset_y};
141-
vec4 pixels = TEXTURE2D(
142-
texture_${textureName},
143-
vec2((float(x) + 0.5) / float(${width_texture}),
144-
(float(g * height / 2 + y) + 0.5) / float(${height_texture}))
145-
);
146-
int index = 0;
147-
if (xOffset == 0 && yOffset == 0) {
148-
return pixels[0];
149-
}
150-
else if (xOffset == 1 && yOffset == 0) {
151-
return pixels[1];
152-
}
153-
else if (xOffset == 0 && yOffset == 1) {
154-
return pixels[2];
155-
}
156-
return pixels[3];
157-
}`;
158-
}
15952

16053
export function getTensorPosFromArrayIndex(
16154
textureName: string,

packages/paddlejs-backend-webgl/src/ops/atom/suffix.ts

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,27 @@
22
* @file suffix code obtaining output position
33
*/
44

5-
6-
import { GLHelper } from '../../webgl/WebGLUtils';
7-
85
interface OutParams {
96
height_shape: number;
107
width_shape: number;
118
channel: number;
129
width_texture: number;
1310
height_texture: number;
14-
limit?: string;
1511
}
1612

17-
function getOutputTensorPos({ height_shape, channel }: OutParams): string {
13+
function getOutputTensorPos({ height_shape, width_shape, width_texture, channel }: OutParams): string {
14+
const chw = width_shape * height_shape * channel;
15+
const hw = width_shape * height_shape;
1816
return `
1917
ivec4 getOutputTensorPos() {
2018
vec2 outCoord = vCoord.xy * (_2d_shape_texture_out);
21-
int x = int(outCoord.x / float(${channel}));
22-
int c = calMod(int(outCoord.x), ${channel});
23-
int y = calMod(int(outCoord.y), ${height_shape});
24-
int b = int(outCoord.y / float(${height_shape}));
25-
return ivec4(b, c, y, x);
26-
}
27-
`;
28-
}
19+
int index = int(outCoord.x) + int(outCoord.y) * int(${width_texture});
2920
30-
function getOutputTensorPosLimit({ height_shape, width_shape, channel }: OutParams): string {
31-
return `
32-
ivec4 getOutputTensorPos() {
33-
float limitCut = float(${GLHelper.getWebglTextureLimitCut()});
34-
// 获取原始长度
35-
vec2 outCoord = vCoord.xy * _2d_shape_texture_out;
36-
float offsetY = floor(outCoord.y / float(${height_shape}));
37-
int x = int(outCoord.x / float(${channel}));
38-
if (mod(offsetY, limitCut) > 0.0) {
39-
x += calMod(int(offsetY), int(limitCut)) * calCeil(${width_shape}, int(limitCut));
40-
}
41-
int y = calMod(int(outCoord.y), ${height_shape});
42-
int c = calMod(int(outCoord.x), ${channel});
43-
int b = int(outCoord.y / float(int(limitCut) * ${height_shape}));
44-
return ivec4(b, c, y, x);
21+
int n1 = int(index / ${chw});
22+
int c1 = int(calMod(index, ${chw}) / ${hw});
23+
int h1 = int(calMod(index, ${hw}) / ${width_shape});
24+
int w1 = calMod(index, ${width_shape});
25+
return ivec4(n1, c1, h1, w1);
4526
}
4627
`;
4728
}
@@ -50,7 +31,7 @@ export default function genSuffix(params: OutParams) {
5031
const header = `
5132
vec2 _2d_shape_texture_out = vec2(float(${params.width_texture}), float(${params.height_texture}));
5233
`;
53-
const getOutputTensorPosFunc = params.limit ? getOutputTensorPosLimit(params) : getOutputTensorPos(params);
34+
const getOutputTensorPosFunc = getOutputTensorPos(params);
5435

5536
return `
5637
${header}

packages/paddlejs-backend-webgl/src/ops/shader/custom/feedPost.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,26 @@
33
*/
44

55
function mainFunc(
6-
{},
6+
{ out },
77
{ mean = [0, 0, 0], std = [1, 1, 1] }
88
) {
9+
const { total_shape, height_shape, width_shape, channel } = out;
910
return `
1011
// start函数
1112
void main(void) {
12-
ivec4 oPos = getOutputTensorPos();
13+
ivec4 nhwcPos = getOutputTensorPos();
14+
int sumVal = nhwcPos.a
15+
+ nhwcPos.b * ${width_shape}
16+
+ nhwcPos.g * ${height_shape} * ${width_shape}
17+
+ nhwcPos.r * ${channel} * ${width_shape} * ${height_shape};
18+
19+
ivec4 oPos = transferFromNHWCtoNCHW(
20+
sumVal,
21+
${channel},
22+
${width_shape},
23+
${height_shape},
24+
${total_shape}
25+
);
1326
float res = 0.0;
1427
int c1 = int(mod(float(oPos[1]), 4.0));
1528
int c = oPos[1];
@@ -40,5 +53,6 @@ export default {
4053
mainFunc,
4154
textureFuncConf: {
4255
origin: ['getValueFromTensorPosPacking']
43-
}
56+
},
57+
commonFuncConf: ['transferFromNHWCtoNCHW']
4458
};

packages/paddlejs-backend-webgl/src/ops/shader/pool2d_winograd.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,39 @@ function mainFunc(
88
) {
99
const [stride_v = 1, stride_h = 1] = strides;
1010
const [padTop = 0, padLeft = 0] = paddings;
11+
const {
12+
height_shape,
13+
width_texture,
14+
height_texture,
15+
offset_y
16+
} = origin;
17+
1118
return `
19+
20+
float getValueFromTensorPosPacked_origin(int r, int g, int b, int a) {
21+
int y = b / 2;
22+
int yOffset = calMod(b, 2);
23+
int x = a / 2;
24+
int xOffset = calMod(a, 2);
25+
int height = ${height_shape} + ${offset_y};
26+
vec4 pixels = TEXTURE2D(
27+
texture_origin,
28+
vec2((float(x) + 0.5) / float(${width_texture}),
29+
(float(g * height / 2 + y) + 0.5) / float(${height_texture}))
30+
);
31+
int index = 0;
32+
if (xOffset == 0 && yOffset == 0) {
33+
return pixels[0];
34+
}
35+
else if (xOffset == 1 && yOffset == 0) {
36+
return pixels[1];
37+
}
38+
else if (xOffset == 0 && yOffset == 1) {
39+
return pixels[2];
40+
}
41+
return pixels[3];
42+
}
43+
1244
// start函数
1345
void main(void) {
1446
float res = (-1.0 / exp(-20.0));
@@ -61,9 +93,6 @@ function mainFunc(
6193
}
6294
export default {
6395
mainFunc,
64-
textureFuncConf: {
65-
origin: ['getValueFromTensorPosPacked']
66-
},
6796
behaviors: [
6897
'isMax',
6998
'setPacked',

packages/paddlejs-backend-webgl/src/ops/utils.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ const tensorParams = [
1818
'height_texture',
1919
'offset_x',
2020
'offset_y',
21-
'limit',
2221
'channel',
2322
'total_shape',
2423
'numbers_shape'

0 commit comments

Comments
 (0)