CreateNeuralNetworkShaders

function CreateNeuralNetworkShaders()

ソース

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));
}