Skip to content

Instantly share code, notes, and snippets.

@robertleeplummerjr
Last active March 24, 2020 12:43
Show Gist options
  • Save robertleeplummerjr/bf101f6fa011ef2557762cf5beeaa2a5 to your computer and use it in GitHub Desktop.
Save robertleeplummerjr/bf101f6fa011ef2557762cf5beeaa2a5 to your computer and use it in GitHub Desktop.
function kernel(settings) {
const { context, constants } = settings;
const gl = context;
const glVariables0 = gl.getExtension('OES_texture_float');
const glVariables1 = gl.getExtension('OES_texture_float_linear');
const glVariables2 = gl.getExtension('OES_element_index_uint');
const glVariables3 = gl.getExtension('WEBGL_draw_buffers');
const glVariables4 = gl.getExtension('WEBGL_color_buffer_float');
const glVariable5 = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, glVariable5);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.enable(gl.SCISSOR_TEST);
gl.viewport(0, 0, 2, 3);
const glVariable6 = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(glVariable6, `precision lowp float;
precision lowp int;
precision lowp sampler2D;
attribute vec2 aPos;
attribute vec2 aTexCoord;
varying vec2 vTexCoord;
uniform vec2 ratio;
void main(void) {
gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);
vTexCoord = aTexCoord;
}`);
gl.compileShader(glVariable6);
const glVariable7 = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(glVariable7, `precision lowp float;
precision lowp int;
precision lowp sampler2D;
const int LOOP_MAX = 1000;
ivec3 uOutputDim = ivec3(5, 1, 1);
ivec2 uTexSize = ivec2(2, 3);
varying vec2 vTexCoord;
float acosh(float x) {
return log(x + sqrt(x * x - 1.0));
}
float sinh(float x) {
return (pow(2.718281828459045, x) - pow(2.718281828459045, -x)) / 2.0;
}
float asinh(float x) {
return log(x + sqrt(x * x + 1.0));
}
float atan2(float v1, float v2) {
if (v1 == 0.0 || v2 == 0.0) return 0.0;
return atan(v1 / v2);
}
float atanh(float x) {
x = (x + 1.0) / (x - 1.0);
if (x < 0.0) {
return 0.5 * log(-x);
}
return 0.5 * log(x);
}
float cbrt(float x) {
if (x >= 0.0) {
return pow(x, 1.0 / 3.0);
} else {
return -pow(x, 1.0 / 3.0);
}
}
float cosh(float x) {
return (pow(2.718281828459045, x) + pow(2.718281828459045, -x)) / 2.0;
}
float expm1(float x) {
return pow(2.718281828459045, x) - 1.0;
}
float fround(highp float x) {
return x;
}
float imul(float v1, float v2) {
return float(int(v1) * int(v2));
}
float log10(float x) {
return log2(x) * (1.0 / log2(10.0));
}
float log1p(float x) {
return log(1.0 + x);
}
float _pow(float v1, float v2) {
if (v2 == 0.0) return 1.0;
return pow(v1, v2);
}
float tanh(float x) {
float e = exp(2.0 * x);
return (e - 1.0) / (e + 1.0);
}
float trunc(float x) {
if (x >= 0.0) {
return floor(x);
} else {
return ceil(x);
}
}
vec4 _round(vec4 x) {
return floor(x + 0.5);
}
float _round(float x) {
return floor(x + 0.5);
}
const int BIT_COUNT = 32;
int modi(int x, int y) {
return x - y * (x / y);
}
int bitwiseOr(int a, int b) {
int result = 0;
int n = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {
result += n;
}
a = a / 2;
b = b / 2;
n = n * 2;
if(!(a > 0 || b > 0)) {
break;
}
}
return result;
}
int bitwiseXOR(int a, int b) {
int result = 0;
int n = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {
result += n;
}
a = a / 2;
b = b / 2;
n = n * 2;
if(!(a > 0 || b > 0)) {
break;
}
}
return result;
}
int bitwiseAnd(int a, int b) {
int result = 0;
int n = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {
result += n;
}
a = a / 2;
b = b / 2;
n = n * 2;
if(!(a > 0 && b > 0)) {
break;
}
}
return result;
}
int bitwiseNot(int a) {
int result = 0;
int n = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if (modi(a, 2) == 0) {
result += n;
}
a = a / 2;
n = n * 2;
}
return result;
}
int bitwiseZeroFillLeftShift(int n, int shift) {
int maxBytes = BIT_COUNT;
for (int i = 0; i < BIT_COUNT; i++) {
if (maxBytes >= n) {
break;
}
maxBytes *= 2;
}
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= shift) {
break;
}
n *= 2;
}
int result = 0;
int byteVal = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= maxBytes) break;
if (modi(n, 2) > 0) { result += byteVal; }
n = int(n / 2);
byteVal *= 2;
}
return result;
}
int bitwiseSignedRightShift(int num, int shifts) {
return int(floor(float(num) / pow(2.0, float(shifts))));
}
int bitwiseZeroFillRightShift(int n, int shift) {
int maxBytes = BIT_COUNT;
for (int i = 0; i < BIT_COUNT; i++) {
if (maxBytes >= n) {
break;
}
maxBytes *= 2;
}
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= shift) {
break;
}
n /= 2;
}
int result = 0;
int byteVal = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= maxBytes) break;
if (modi(n, 2) > 0) { result += byteVal; }
n = int(n / 2);
byteVal *= 2;
}
return result;
}
vec2 integerMod(vec2 x, float y) {
vec2 res = floor(mod(x, y));
return res * step(1.0 - floor(y), -res);
}
vec3 integerMod(vec3 x, float y) {
vec3 res = floor(mod(x, y));
return res * step(1.0 - floor(y), -res);
}
vec4 integerMod(vec4 x, vec4 y) {
vec4 res = floor(mod(x, y));
return res * step(1.0 - floor(y), -res);
}
float integerMod(float x, float y) {
float res = floor(mod(x, y));
return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);
}
int integerMod(int x, int y) {
return x - (y * int(x / y));
}
float divWithIntCheck(float x, float y) {
if (floor(x) == x && floor(y) == y && integerMod(x, y) == 0.0) {
return float(int(x) / int(y));
}
return x / y;
}
float integerCorrectionModulo(float number, float divisor) {
if (number < 0.0) {
number = abs(number);
if (divisor < 0.0) {
divisor = abs(divisor);
}
return -(number - (divisor * floor(divWithIntCheck(number, divisor))));
}
if (divisor < 0.0) {
divisor = abs(divisor);
}
return number - (divisor * floor(divWithIntCheck(number, divisor)));
}
// Here be dragons!
// DO NOT OPTIMIZE THIS CODE
// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE
// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME
const vec2 MAGIC_VEC = vec2(1.0, -256.0);
const vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);
const vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536
float decode32(vec4 texel) {
texel *= 255.0;
vec2 gte128;
gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;
gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;
float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);
float res = exp2(_round(exponent));
texel.b = texel.b - 128.0 * gte128.x;
res = dot(texel, SCALE_FACTOR) * exp2(_round(exponent-23.0)) + res;
res *= gte128.y * -2.0 + 1.0;
return res;
}
float decode16(vec4 texel, int index) {
int channel = integerMod(index, 2);
if (channel == 0) return texel.r * 255.0 + texel.g * 65280.0;
if (channel == 1) return texel.b * 255.0 + texel.a * 65280.0;
return 0.0;
}
float decode8(vec4 texel, int index) {
int channel = integerMod(index, 4);
if (channel == 0) return texel.r * 255.0;
if (channel == 1) return texel.g * 255.0;
if (channel == 2) return texel.b * 255.0;
if (channel == 3) return texel.a * 255.0;
return 0.0;
}
vec4 legacyEncode32(float f) {
float F = abs(f);
float sign = f < 0.0 ? 1.0 : 0.0;
float exponent = floor(log2(F));
float mantissa = (exp2(-exponent) * F);
// exponent += floor(log2(mantissa));
vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;
texel.rg = integerMod(texel.rg, 256.0);
texel.b = integerMod(texel.b, 128.0);
texel.a = exponent*0.5 + 63.5;
texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;
texel = floor(texel);
texel *= 0.003921569; // 1/255
return texel;
}
// https://github.com/gpujs/gpu.js/wiki/Encoder-details
vec4 encode32(float value) {
if (value == 0.0) return vec4(0, 0, 0, 0);
float exponent;
float mantissa;
vec4 result;
float sgn;
sgn = step(0.0, -value);
value = abs(value);
exponent = floor(log2(value));
mantissa = value*pow(2.0, -exponent)-1.0;
exponent = exponent+127.0;
result = vec4(0,0,0,0);
result.a = floor(exponent/2.0);
exponent = exponent - result.a*2.0;
result.a = result.a + 128.0*sgn;
result.b = floor(mantissa * 128.0);
mantissa = mantissa - result.b / 128.0;
result.b = result.b + exponent*128.0;
result.g = floor(mantissa*32768.0);
mantissa = mantissa - result.g/32768.0;
result.r = floor(mantissa*8388608.0);
return result/255.0;
}
// Dragons end here
int index;
ivec3 threadId;
ivec3 indexTo3D(int idx, ivec3 texDim) {
int z = int(idx / (texDim.x * texDim.y));
idx -= z * int(texDim.x * texDim.y);
int y = int(idx / texDim.x);
int x = int(integerMod(idx, texDim.x));
return ivec3(x, y, z);
}
float get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
return decode32(texel);
}
float get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x * 2;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize.x * 2, texSize.y));
return decode16(texel, index);
}
float get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x * 4;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize.x * 4, texSize.y));
return decode8(texel, index);
}
float getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int channel = integerMod(index, 4);
index = index / 4;
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
if (channel == 0) return texel.r;
if (channel == 1) return texel.g;
if (channel == 2) return texel.b;
if (channel == 3) return texel.a;
return 0.0;
}
vec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
return texture2D(tex, st / vec2(texSize));
}
float getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
vec4 result = getImage2D(tex, texSize, texDim, z, y, x);
return result[0];
}
vec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
vec4 result = getImage2D(tex, texSize, texDim, z, y, x);
return vec2(result[0], result[1]);
}
vec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + (texDim.x * (y + (texDim.y * z)));
int channel = integerMod(index, 2);
index = index / 2;
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
if (channel == 0) return vec2(texel.r, texel.g);
if (channel == 1) return vec2(texel.b, texel.a);
return vec2(0.0, 0.0);
}
vec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
vec4 result = getImage2D(tex, texSize, texDim, z, y, x);
return vec3(result[0], result[1], result[2]);
}
vec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));
int vectorIndex = fieldIndex / 4;
int vectorOffset = fieldIndex - vectorIndex * 4;
int readY = vectorIndex / texSize.x;
int readX = vectorIndex - readY * texSize.x;
vec4 tex1 = texture2D(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));
if (vectorOffset == 0) {
return tex1.xyz;
} else if (vectorOffset == 1) {
return tex1.yzw;
} else {
readX++;
if (readX >= texSize.x) {
readX = 0;
readY++;
}
vec4 tex2 = texture2D(tex, vec2(readX, readY) / vec2(texSize));
if (vectorOffset == 2) {
return vec3(tex1.z, tex1.w, tex2.x);
} else {
return vec3(tex1.w, tex2.x, tex2.y);
}
}
}
vec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
return getImage2D(tex, texSize, texDim, z, y, x);
}
vec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int channel = integerMod(index, 2);
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
return vec4(texel.r, texel.g, texel.b, texel.a);
}
vec4 actualColor;
void color(float r, float g, float b, float a) {
actualColor = vec4(r,g,b,a);
}
void color(float r, float g, float b) {
color(r,g,b,1.0);
}
void color(sampler2D image) {
actualColor = texture2D(image, vTexCoord);
}
float modulo(float number, float divisor) {
if (number < 0.0) {
number = abs(number);
if (divisor < 0.0) {
divisor = abs(divisor);
}
return -mod(number, divisor);
}
if (divisor < 0.0) {
divisor = abs(divisor);
}
return mod(number, divisor);
}
uniform sampler2D user_inputArray;
ivec2 user_inputArraySize = ivec2(4, 2);
ivec3 user_inputArrayDim = ivec3(5, 1, 1);
float kernelResult;
void kernel() {
kernelResult = get32(user_inputArray, user_inputArraySize, user_inputArrayDim, 0, 0, threadId.x);return;
}
void main(void) {
index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;
threadId = indexTo3D(index, uOutputDim);
kernel();
gl_FragData[0] = encode32(kernelResult);
}`);
gl.compileShader(glVariable7);
const glVariable8 = gl.getShaderParameter(glVariable6, gl.COMPILE_STATUS);
const glVariable9 = gl.getShaderParameter(glVariable7, gl.COMPILE_STATUS);
const glVariable10 = gl.createProgram();
gl.attachShader(glVariable10, glVariable6);
gl.attachShader(glVariable10, glVariable7);
gl.linkProgram(glVariable10);
const glVariable11 = gl.createFramebuffer();
const glVariable12 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glVariable12);
gl.bufferData(gl.ARRAY_BUFFER, 64, gl.STATIC_DRAW);
const glVariable13 = new Float32Array([-1,-1,1,-1,-1,1,1,1]);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, glVariable13);
const glVariable14 = new Float32Array([0,0,1,0,0,1,1,1]);
gl.bufferSubData(gl.ARRAY_BUFFER, 32, glVariable14);
const glVariable15 = gl.getAttribLocation(glVariable10, 'aPos');
gl.enableVertexAttribArray(glVariable15);
gl.vertexAttribPointer(glVariable15, 2, gl.FLOAT, false, 0, 0);
const glVariable16 = gl.getAttribLocation(glVariable10, 'aTexCoord');
gl.enableVertexAttribArray(glVariable16);
gl.vertexAttribPointer(glVariable16, 2, gl.FLOAT, false, 0, 32);
gl.bindFramebuffer(gl.FRAMEBUFFER, glVariable11);
gl.useProgram(glVariable10);
const glVariable17 = gl.createTexture();
gl.activeTexture(33985);
gl.bindTexture(gl.TEXTURE_2D, glVariable17);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 3, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, glVariable17, 0);
/** start of injected functions **/
function flattenTo(array, target) {
if (/*utils.*/isArray(array[0])) {
if (/*utils.*/isArray(array[0][0])) {
if (/*utils.*/isArray(array[0][0][0])) {
/*utils.*/flatten4dArrayTo(array, target);
} else {
/*utils.*/flatten3dArrayTo(array, target);
}
} else {
/*utils.*/flatten2dArrayTo(array, target);
}
} else {
target.set(array);
}
}
function flatten2dArrayTo(array, target) {
let offset = 0;
for (let y = 0; y < array.length; y++) {
target.set(array[y], offset);
offset += array[y].length;
}
}
function flatten3dArrayTo(array, target) {
let offset = 0;
for (let z = 0; z < array.length; z++) {
for (let y = 0; y < array[z].length; y++) {
target.set(array[z][y], offset);
offset += array[z][y].length;
}
}
}
function flatten4dArrayTo(array, target) {
let offset = 0;
for (let l = 0; l < array.length; l++) {
for (let z = 0; z < array[l].length; z++) {
for (let y = 0; y < array[l][z].length; y++) {
target.set(array[l][z][y], offset);
offset += array[l][z][y].length;
}
}
}
}
function isArray(array) {
return !isNaN(array.length);
}
const renderOutput = function (array, width) {
return array.subarray(0, width);
};
/** end of injected functions **/
const innerKernel = function (inputArray) {
/** start setup uploads for kernel values **/
const preUploadValue_inputArray = new Float32Array(8);
const uploadValue_inputArray = new Uint8Array(preUploadValue_inputArray.buffer);
flattenTo(inputArray, preUploadValue_inputArray);
/** end setup uploads for kernel values **/
gl.useProgram(glVariable10);
gl.scissor(0, 0, 2, 3);
const glVariable18 = gl.getUniformLocation(glVariable10, 'ratio');
gl.uniform2f(glVariable18, 1, 1);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, glVariable5);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 4, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, uploadValue_inputArray);
const glVariable19 = gl.getUniformLocation(glVariable10, 'user_inputArray');
gl.uniform1i(glVariable19, 0);
gl.bindFramebuffer(gl.FRAMEBUFFER, glVariable11);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
const glVariable20 = new Uint8Array(24);
gl.readPixels(0, 0, 2, 3, gl.RGBA, gl.UNSIGNED_BYTE, glVariable20);
return renderOutput(new Float32Array(glVariable20.buffer), 5);
};
return innerKernel;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment