Last active
May 31, 2020 12:50
-
-
Save kig/2ed6b51ecff5605a72bf4b502c793a48 to your computer and use it in GitHub Desktop.
A GLSL web server? Maybe?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define CHR_NULL 0 | |
#define CHR_SOH 1 | |
#define CHR_STX 2 | |
#define CHR_ETX 3 | |
#define CHR_EOT 4 | |
#define CHR_ENQ 5 | |
#define CHR_ACK 6 | |
#define CHR_BELL 7 | |
#define CHR_BACKSPACE 8 | |
#define CHR_TAB 9 | |
#define CHR_LF 10 | |
#define CHR_VT 11 | |
#define CHR_FF 12 | |
#define CHR_CR 13 | |
#define CHR_SO 14 | |
#define CHR_SI 15 | |
#define CHR_DLE 16 | |
#define CHR_DC1 17 | |
#define CHR_DC2 18 | |
#define CHR_DC3 19 | |
#define CHR_DC4 20 | |
#define CHR_NAK 21 | |
#define CHR_SYN 22 | |
#define CHR_ETB 23 | |
#define CHR_CAN 24 | |
#define CHR_EM 25 | |
#define CHR_SUB 26 | |
#define CHR_ESC 27 | |
#define CHR_FS 28 | |
#define CHR_GS 29 | |
#define CHR_RS 30 | |
#define CHR_US 31 | |
#define CHR_SPACE 32 | |
#define CHR_EXCLAMATION_MARK 33 | |
#define CHR_DOUBLE_QUOTE 34 | |
#define CHR_HASH 35 | |
#define CHR_DOLLAR 36 | |
#define CHR_PERCENT 37 | |
#define CHR_AMPERSAND 38 | |
#define CHR_SINGLE_QUOTE 39 | |
#define CHR_OPEN_PAREN 40 | |
#define CHR_CLOSE_PAREN 41 | |
#define CHR_TIMES 42 | |
#define CHR_PLUS 43 | |
#define CHR_COMMA 44 | |
#define CHR_DASH 45 | |
#define CHR_DOT 46 | |
#define CHR_SLASH 47 | |
#define CHR_0 48 | |
#define CHR_1 49 | |
#define CHR_2 50 | |
#define CHR_3 51 | |
#define CHR_4 52 | |
#define CHR_5 53 | |
#define CHR_6 54 | |
#define CHR_7 55 | |
#define CHR_8 56 | |
#define CHR_9 57 | |
#define CHR_COLON 58 | |
#define CHR_SEMICOLON 59 | |
#define CHR_OPEN_ANGLE_BRACKET 60 | |
#define CHR_EQUAL 61 | |
#define CHR_CLOSE_ANGLE_BRACKET 62 | |
#define CHR_QUESTION_MARK 63 | |
#define CHR_AT 64 | |
#define CHR_A 65 | |
#define CHR_B 66 | |
#define CHR_C 67 | |
#define CHR_D 68 | |
#define CHR_E 69 | |
#define CHR_F 70 | |
#define CHR_G 71 | |
#define CHR_H 72 | |
#define CHR_I 73 | |
#define CHR_J 74 | |
#define CHR_K 75 | |
#define CHR_L 76 | |
#define CHR_M 77 | |
#define CHR_N 78 | |
#define CHR_O 79 | |
#define CHR_P 80 | |
#define CHR_Q 81 | |
#define CHR_R 82 | |
#define CHR_S 83 | |
#define CHR_T 84 | |
#define CHR_U 85 | |
#define CHR_V 86 | |
#define CHR_W 87 | |
#define CHR_X 88 | |
#define CHR_Y 89 | |
#define CHR_Z 90 | |
#define CHR_OPEN_SQUARE_BRACKET 91 | |
#define CHR_BACKSLASH 92 | |
#define CHR_CLOSE_SQUARE_BRACKET 93 | |
#define CHR_CARET 94 | |
#define CHR_UNDERSCORE 95 | |
#define CHR_BACKTICK 96 | |
#define CHR_a 97 | |
#define CHR_b 98 | |
#define CHR_c 99 | |
#define CHR_d 100 | |
#define CHR_e 101 | |
#define CHR_f 102 | |
#define CHR_g 103 | |
#define CHR_h 104 | |
#define CHR_i 105 | |
#define CHR_j 106 | |
#define CHR_k 107 | |
#define CHR_l 108 | |
#define CHR_m 109 | |
#define CHR_n 110 | |
#define CHR_o 111 | |
#define CHR_p 112 | |
#define CHR_q 113 | |
#define CHR_r 114 | |
#define CHR_s 115 | |
#define CHR_t 116 | |
#define CHR_u 117 | |
#define CHR_v 118 | |
#define CHR_w 119 | |
#define CHR_x 120 | |
#define CHR_y 121 | |
#define CHR_z 122 | |
#define CHR_OPEN_CURLY_BRACKET 123 | |
#define CHR_PIPE 124 | |
#define CHR_CLOSE_CURLY_BRACKET 125 | |
#define CHR_TILDE 126 | |
#define CHR_DEL 127 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compile with | |
// cpp httpd.glsl - | node preprocess.js > out.comp && glslangValidator -V out.comp -o httpd.spv | |
#define version #version | |
version 450 | |
#include "chr.glsl" | |
#define strCopy(SRC, DST, i, start, end) uint _s = start; uint _e = end; while (_s < _e) (DST)[i++] = (SRC)[_s++]; | |
#define strCopyAll(SRC, DST, i) uint _str[] = SRC; strCopy(_str, DST, i, 0, _str.length()) | |
#define A_OK if (i > 1024) error(index); return | |
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1 ) in; | |
layout(std430, binding = 0) readonly buffer inputBuffer { uint inputBytes[]; }; | |
layout(std430, binding = 1) buffer outputBuffer { uint outputBytes[]; }; | |
layout(std430, binding = 2) buffer heapBuffer { uint heap[]; }; | |
layout(std430, binding = 3) buffer requestBuffer { uint request[]; }; | |
layout(std430, binding = 4) buffer responseBuffer { uint response[]; }; | |
const uint METHOD_UNKNOWN = 0; | |
const uint METHOD_GET = 1; | |
const uint METHOD_POST = 2; | |
const uint METHOD_OPTION = 3; | |
const uint PROTOCOL_UNKNOWN = 0; | |
const uint PROTOCOL_HTTP10 = 1; | |
const uint PROTOCOL_HTTP11 = 2; | |
const uint MIME_TEXT_PLAIN = 0; | |
const uint MIME_TEXT_HTML = 1; | |
struct header { | |
uvec2 name; | |
uvec2 value; | |
}; | |
void readRequestUntilChar(inout uint i, uint index, uint endChar, out uvec2 str) { | |
str.x = index + i; | |
while (i < 1024 && request[index+i] != endChar) { | |
i++; | |
} | |
str.y = index + i; | |
i++; | |
} | |
void readMethod(inout uint i, uint index, out uint method) { | |
uint j = index + i; | |
uint c = request[j]; | |
if ( | |
request[j] == CHR_G && | |
request[j+1] == CHR_E && | |
request[j+2] == CHR_T && | |
request[j+3] == CHR_SPACE | |
) { | |
method = METHOD_GET; | |
i += 4; | |
return; | |
} else if ( | |
request[j] == CHR_P && | |
request[j+1] == CHR_O && | |
request[j+2] == CHR_S && | |
request[j+3] == CHR_T && | |
request[j+4] == CHR_SPACE | |
) { | |
method = METHOD_POST; | |
i += 5; | |
return; | |
} else if (request[j] == CHR_O && request[j+6] == CHR_SPACE) { | |
method = METHOD_OPTION; | |
i += 7; | |
return; | |
} | |
method = METHOD_UNKNOWN; | |
i = 1024; | |
} | |
void readPath(inout uint i, uint index, out uvec2 path) { | |
readRequestUntilChar(i, index, CHR_SPACE, path); | |
} | |
void readProtocol(inout uint i, uint index, out uint protocol) { | |
uvec2 protocolString; | |
readRequestUntilChar(i, index, CHR_CR, protocolString); | |
if (i < 1024 && request[index+i] == CHR_LF) { | |
i++; | |
if (request[protocolString.y-1] == CHR_1) { | |
protocol = PROTOCOL_HTTP11; | |
} else { | |
protocol = PROTOCOL_HTTP10; | |
} | |
} else { | |
protocol = PROTOCOL_UNKNOWN; | |
i = 1024; | |
} | |
} | |
bool readHeader(inout uint i, uint index, out header hdr) { | |
if (request[index+i] == CHR_CR) { | |
i += 2; | |
return true; | |
} | |
readRequestUntilChar(i, index, CHR_COLON, hdr.name); | |
while (i < 1024 && request[index+i] == CHR_SPACE) i++; | |
readRequestUntilChar(i, index, CHR_CR, hdr.value); | |
i += 2; | |
return false; | |
} | |
void writeStatus(inout uint i, uint index, uint statusCode) { | |
uint j = i + index; | |
strCopyAll("HTTP/1.1 ", response, j); | |
if (statusCode == 200) { | |
strCopyAll("200 OK", response, j); | |
} else { | |
strCopyAll("500 Error", response, j); | |
} | |
response[j++] = CHR_CR; | |
response[j++] = CHR_LF; | |
i = j - index; | |
} | |
void writeContentType(inout uint i, uint index, uint contentType) { | |
uint j = i + index; | |
uint contentTypeString[] = "Content-Type: "; | |
strCopyAll(contentTypeString, response, j); | |
if (contentType == MIME_TEXT_PLAIN) { | |
strCopyAll("text/plain", response, j); | |
} else { | |
strCopyAll("text/html", response, j); | |
} | |
response[j++] = CHR_CR; | |
response[j++] = CHR_LF; | |
i = j - index; | |
} | |
void writeEndHeaders(inout uint i, uint index) { | |
uint j = i + index; | |
response[j++] = CHR_CR; | |
response[j++] = CHR_LF; | |
i = j - index; | |
} | |
void writeBody(inout uint i, uint index, uvec2 path) { | |
uint j = i + index; | |
strCopyAll("Hello, World!", response, j); | |
i = j - index; | |
} | |
void error(uint index) { | |
uint i = index; | |
writeStatus(i, index, 500); | |
writeContentType(i, index, MIME_TEXT_PLAIN); | |
writeEndHeaders(i, index); | |
response[i++] = 0; | |
} | |
void unpackRequest(uint index) { | |
for (uint j = 0; j < 256; j++) { | |
uint v = inputBytes[index + j]; | |
uint off = index + j * 4; | |
request[off + 0] = v & 0xFF; | |
request[off + 1] = (v >> 8) & 0xFF; | |
request[off + 2] = (v >> 16) & 0xFF; | |
request[off + 3] = v >> 24; | |
} | |
} | |
void packResponse(uint index) { | |
for (uint j = 0; j < 256; j++) { | |
uint off = index + j * 4; | |
outputBytes[index + j] = ( | |
((response[off + 3] & 0xFF) << 24) | | |
((response[off + 2] & 0xFF) << 16) | | |
((response[off + 1] & 0xFF) << 8) | | |
(response[off + 0] & 0xFF) | |
); | |
} | |
} | |
void handleRequest(uint index) { | |
uint i = 0; | |
uint method; | |
uvec2 path; | |
uint protocol; | |
header headers[32]; | |
uint headerCount = 0; | |
readMethod(i, index, method); A_OK; | |
readPath(i, index, path); A_OK; | |
readProtocol(i, index, protocol); A_OK; | |
for (uint j = 0; j < 32; j++) { | |
bool done = readHeader(i, index, headers[j]); A_OK; | |
if (done) break; | |
headerCount++; | |
} | |
i = 0; | |
writeStatus(i, index, 200); A_OK; | |
writeContentType(i, index, MIME_TEXT_PLAIN); A_OK; | |
writeEndHeaders(i, index); A_OK; | |
writeBody(i, index, path); A_OK; | |
response[i++] = 0; | |
} | |
void main() { | |
uint index = 1024 * (gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * (gl_NumWorkGroups.x * gl_WorkGroupSize.x)); | |
unpackRequest(index); | |
handleRequest(index); | |
packResponse(index); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Turn string literals into uint arrays. | |
// Quick hack, doesn't deal with comments or tokenize \\\" correctly. | |
// | |
const fs = require('fs'); | |
const source = fs.readFileSync(0); | |
const segments = source.toString().replace(/^# .*/mg, '').split(/(")/g); | |
let inString = false; | |
let lastSegment = ''; | |
let stringSegments = []; | |
const output = []; | |
for (segment of segments) { | |
if (segment === '"' && lastSegment[lastSegment.length-1] !== '\\') { | |
inString = !inString; | |
if (!inString) { | |
const str = stringSegments.join(''); | |
output.push(`{${Buffer.from(str).join(",")}}`); | |
} | |
stringSegments = []; | |
} else if (inString) { | |
stringSegments.push(segment); | |
} else { | |
output.push(segment); | |
} | |
lastSegment = segment; | |
} | |
console.log(output.join('')); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment