function CreateNeuralNetworkShaders() {
return {
FullyConnectedLayer_Forward:
`in float zero;
const int ActivationFunction_none = 0;
const int ActivationFunction_sigmoid = 1;
const int ActivationFunction_ReLU = 2;
uniform int activationFunction;
// 2次元配列のテクスチャ
uniform sampler2D W;
uniform sampler2D X;
uniform sampler2D Bias;
out float z;
out float y;
float sigmoid(float x){
return 1.0 / (1.0 + exp(-x));
}
void main() {
ivec2 X_sz = textureSize(X, 0);
ivec2 Bias_sz = textureSize(Bias, 0);
int batch_idx = gl_VertexID / Bias_sz.x;
int out_idx = gl_VertexID % Bias_sz.x;
float sum = 0.0f;
for(int i = 0; i < X_sz.x; i++) {
vec4 w = texelFetch(W, ivec2(i, out_idx), 0);
vec4 x = texelFetch(X, ivec2(i, batch_idx), 0);
sum += w.r * x.r;
}
vec4 bias = texelFetch(Bias, ivec2(out_idx, 0), 0);
sum += bias.r;
// 入力変数zeroの値は必要ないですが、使用しない変数はコンパイラが除去してしまいエラーになるので形の上だけ使用します。
// zeroの値は0なので計算結果には影響しません。
z = sum + zero;
switch(activationFunction){
case ActivationFunction_none:
y = z;
break;
case ActivationFunction_sigmoid:
y = sigmoid(z);
break;
case ActivationFunction_ReLU:
y = (0.0f < z ? z : 0.0f);
break;
}
}`
,
FullyConnectedLayer_DeltaWeight:
`in float zero;
// 2次元配列のテクスチャ
uniform sampler2D prev_y;
uniform sampler2D deltaZ;
out float deltaWeight;
void main() {
int row = gl_VertexID / WeightColSize;
int col = gl_VertexID % WeightColSize;
float sum = 0.0f;
int batch_idx;
for(batch_idx = 0; batch_idx < miniBatchSize; batch_idx++){
vec4 pa = texelFetch(prev_y, ivec2(col, batch_idx), 0);
vec4 dz = texelFetch(deltaZ, ivec2(row, batch_idx), 0);
sum += pa.r * dz.r;
}
deltaWeight = sum + zero;
}`
,
FullyConnectedLayer_DeltaX:
`in float zero;
// 2次元配列のテクスチャ
uniform sampler2D W;
uniform sampler2D deltaZ;
out float deltaX;
void main() {
ivec2 W_sz = textureSize(W, 0);
int batch_idx = gl_VertexID / W_sz.x;
int delta_x_idx = gl_VertexID % W_sz.x;
float sum = 0.0f;
for(int i = 0; i < W_sz.y; i++) {
vec4 w = texelFetch(W, ivec2(delta_x_idx, i), 0);
vec4 z = texelFetch(deltaZ, ivec2(i, batch_idx), 0);
sum += w.r * z.r;
}
deltaX = sum + zero;
}`
,
ConvolutionalLayer_Forward : `
precision highp sampler3D;
const int ActivationFunction_none = 0;
const int ActivationFunction_sigmoid = 1;
const int ActivationFunction_ReLU = 2;
uniform int activationFunction;
uniform float bias[numChannels];
uniform sampler3D weight;
uniform sampler3D prev_y;
in float zero;
out float z;
out float y;
float sigmoid(float x){
return 1.0 / (1.0 + exp(-x));
}