|
|
@ -3,179 +3,184 @@ |
|
|
|
#include <sstream>
|
|
|
|
#include <variant>
|
|
|
|
#include <chrono>
|
|
|
|
#include "commander.hpp"
|
|
|
|
#include "nlohmann/json.hpp"
|
|
|
|
#include <GL/glew.h>
|
|
|
|
#define GLFW_DLL
|
|
|
|
#include <GLFW/glfw3.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::variant<std::array<float,18>, std::vector<float>> points = std::array<float,18> { |
|
|
|
-1.0f, 1.0f, 0.0f, |
|
|
|
1.0f, -1.0f, 0.0f, |
|
|
|
-1.0f, -1.0f, 0.0f, |
|
|
|
1.0f, -1.0f, 0.0f, |
|
|
|
1.0f, 1.0f, 0.0f, |
|
|
|
-1.0f, 1.0f, 0.0f |
|
|
|
}; |
|
|
|
|
|
|
|
std::string check_shader(GLuint shader) |
|
|
|
#include <algorithm>
|
|
|
|
#include "database.hpp"
|
|
|
|
#include "network.hpp"
|
|
|
|
#include <memory>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
|
|
int main( |
|
|
|
[[maybe_unused]] int argc, |
|
|
|
[[maybe_unused]] char** argv |
|
|
|
) |
|
|
|
{ |
|
|
|
std::array<char,4096> text_buffer; |
|
|
|
GLsizei size; |
|
|
|
glGetShaderInfoLog(shader, text_buffer.size(),&size,text_buffer.data()); |
|
|
|
return std::string{text_buffer.begin(), text_buffer.begin()+size}; |
|
|
|
} |
|
|
|
|
|
|
|
std::string vertex_shader = |
|
|
|
"#version 400\n" |
|
|
|
"in vec3 vp;" |
|
|
|
"void main() {" |
|
|
|
" gl_Position = vec4(vp, 1.0);" |
|
|
|
"}"; |
|
|
|
|
|
|
|
std::string fragment_shader = |
|
|
|
"#version 400\n" |
|
|
|
"out vec4 frag_colour;" |
|
|
|
"void main() {" |
|
|
|
" frag_colour = vec4(1.0, 0.0, 0.0, 1.0);" |
|
|
|
"}"; |
|
|
|
|
|
|
|
std::pair<int,int> parse_resolution(const std::string& str) |
|
|
|
{ |
|
|
|
auto x_it = std::find(str.begin(),str.end(),'x'); |
|
|
|
auto x_str = std::string{str.begin(),x_it}; |
|
|
|
auto y_str = std::string(x_it+1,str.end()); |
|
|
|
return std::make_pair(std::stoi(x_str),std::stoi(y_str)); |
|
|
|
} |
|
|
|
|
|
|
|
std::string slurp_file(const std::string& path) |
|
|
|
{ |
|
|
|
std::ifstream input(path); |
|
|
|
std::stringstream sstr; |
|
|
|
|
|
|
|
while(input >> sstr.rdbuf()); |
|
|
|
#ifdef UNITTEST
|
|
|
|
{ |
|
|
|
database db(database::create("/tmp/", 4096)); |
|
|
|
|
|
|
|
return sstr.str(); |
|
|
|
} |
|
|
|
db_page v; |
|
|
|
v.fill(1); |
|
|
|
|
|
|
|
int main(int argc, char** argv) |
|
|
|
{ |
|
|
|
// start GL context and O/S window using the GLFW helper library
|
|
|
|
if (!glfwInit()) { |
|
|
|
std::cerr<<"ERROR: could not start GLFW3\n"; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
record_identifier tar; |
|
|
|
|
|
|
|
CMD::commander cli_args{argc,argv}; |
|
|
|
auto res_str = cli_args.getFlagValue("-r"); |
|
|
|
auto res = parse_resolution(res_str.empty()?"800x800":res_str); |
|
|
|
auto mesh_path = cli_args.getFlagValue("--mesh"); |
|
|
|
auto begin = std::chrono::high_resolution_clock::now(); |
|
|
|
|
|
|
|
if(!mesh_path.empty()) { |
|
|
|
auto mesh = nlohmann::json::parse(slurp_file(mesh_path)); |
|
|
|
assert(mesh.is_array()); |
|
|
|
points = std::vector<float>{mesh.begin(), mesh.end()}; |
|
|
|
} |
|
|
|
size_t tot = 2048; |
|
|
|
for(size_t idx=0;idx<tot;idx++) |
|
|
|
{ |
|
|
|
tar.y.internal = idx; |
|
|
|
db.write(tar, v); |
|
|
|
} |
|
|
|
|
|
|
|
auto vertshad_path = cli_args.getFlagValue("--vshader"); |
|
|
|
auto durr = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - begin)/tot; |
|
|
|
|
|
|
|
if(!vertshad_path.empty()) { |
|
|
|
vertex_shader = slurp_file(vertshad_path); |
|
|
|
} |
|
|
|
std::cerr << "durr/elem = " << durr.count() << "ns/op" << std::endl; |
|
|
|
|
|
|
|
auto fragshad_path = cli_args.getFlagValue("--fshader"); |
|
|
|
auto a = db.read(tar); |
|
|
|
|
|
|
|
if(o">!fragshad_path.empty()) { |
|
|
|
fragment_shader = slurp_file(fragshad_path); |
|
|
|
} |
|
|
|
if(a.second[0] != 1) { |
|
|
|
std::cerr << "read failed" << std::endl; |
|
|
|
} |
|
|
|
|
|
|
|
// uncomment these lines if on Apple OS X
|
|
|
|
/*glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); |
|
|
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); |
|
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);*/ |
|
|
|
db.remove(tar); |
|
|
|
|
|
|
|
GLFWwindow* window = glfwCreateWindow(res.first, res.second, "sh_render", NULL, NULL); |
|
|
|
a = db.read(tar); |
|
|
|
if(a.second[0] == 1) { |
|
|
|
std::cerr << "remove failed" << std::endl; |
|
|
|
} |
|
|
|
|
|
|
|
{ |
|
|
|
db.write(tar, v); |
|
|
|
a = db.read(tar); |
|
|
|
if(a.second[0] != 1) { |
|
|
|
std::cerr << "read failed" << std::endl; |
|
|
|
} |
|
|
|
db.remove(tar); |
|
|
|
a = db.read(tar); |
|
|
|
if(a.second[0] != 0) { |
|
|
|
std::cerr << "remove failed" << std::endl; |
|
|
|
} |
|
|
|
v.fill(2); |
|
|
|
db.write(tar, v); |
|
|
|
} |
|
|
|
|
|
|
|
if (!window) { |
|
|
|
std::cerr<<"ERROR: could not open window with GLFW3\n"; |
|
|
|
glfwTerminate(); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
database reop(database::open("/tmp/")); |
|
|
|
|
|
|
|
glfwMakeContextCurrent(window); |
|
|
|
{ |
|
|
|
a = reop.read(tar); |
|
|
|
|
|
|
|
// start GLEW extension handler
|
|
|
|
glewExperimental = GL_TRUE; |
|
|
|
glewInit(); |
|
|
|
if(a.second[0] != 2) { |
|
|
|
std::cerr << "reopen read failed" << std::endl; |
|
|
|
} |
|
|
|
|
|
|
|
// get version info
|
|
|
|
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
|
|
|
|
const GLubyte* version = glGetString(GL_VERSION); // version as a string
|
|
|
|
std::cout <<"Renderer: "<<renderer<<"\n" |
|
|
|
<<"OpenGL version supported "<<version<<"\n"; |
|
|
|
v.fill(3); |
|
|
|
|
|
|
|
// tell GL to only draw onto a pixel if the shape is closer to the viewer
|
|
|
|
glEnable(GL_DEPTH_TEST); // enable depth-testing
|
|
|
|
glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
|
|
|
|
reop.write(tar, v); |
|
|
|
|
|
|
|
{ |
|
|
|
GLuint vbo = 0; |
|
|
|
glGenBuffers(1, &vbo); |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo); |
|
|
|
glBufferData( |
|
|
|
GL_ARRAY_BUFFER, |
|
|
|
std::visit([](auto& v)->size_t{return v.size();},points) * sizeof(float), |
|
|
|
std::visit([](auto& v)->float* {return (float*)v.data();},points), |
|
|
|
GL_STATIC_DRAW |
|
|
|
); |
|
|
|
auto num_triangles = std::visit([](auto& v)->size_t{return v.size();},points)/9; |
|
|
|
|
|
|
|
GLuint vao = 0; |
|
|
|
glGenVertexArrays(1, &vao); |
|
|
|
glBindVertexArray(vao); |
|
|
|
glEnableVertexAttribArray(0); |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo); |
|
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); |
|
|
|
|
|
|
|
GLuint vs = glCreateShader(GL_VERTEX_SHADER); |
|
|
|
auto vsh = vertex_shader.data(); |
|
|
|
glShaderSource(vs, 1, &vsh, NULL); |
|
|
|
glCompileShader(vs); |
|
|
|
std::cout<<"Vertex shader:"<<check_shader(vs)<<"\n"; |
|
|
|
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); |
|
|
|
auto fsh = fragment_shader.data(); |
|
|
|
glShaderSource(fs, 1, &fsh, NULL); |
|
|
|
glCompileShader(fs); |
|
|
|
std::cout<<"Fragment shader:"<<check_shader(fs)<<"\n"; |
|
|
|
|
|
|
|
GLuint shader_programme = glCreateProgram(); |
|
|
|
glAttachShader(shader_programme, fs); |
|
|
|
glAttachShader(shader_programme, vs); |
|
|
|
glLinkProgram(shader_programme); |
|
|
|
|
|
|
|
while(!glfwWindowShouldClose(window)) { |
|
|
|
// wipe the drawing surface clear
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
|
|
|
glUseProgram(shader_programme); |
|
|
|
glBindVertexArray(vao); |
|
|
|
|
|
|
|
// draw points 0-4 from the currently bound VAO with current in-use shader
|
|
|
|
for(size_t tri_it = 0; tri_it<num_triangles; tri_it++) { |
|
|
|
glDrawArrays(GL_TRIANGLES, tri_it*3, 3); |
|
|
|
a = reop.read(tar); |
|
|
|
if(a.second[0] != 3) { |
|
|
|
std::cerr << "reopen write failed" << std::endl; |
|
|
|
} |
|
|
|
|
|
|
|
// update other events like input handling
|
|
|
|
glfwPollEvents(); |
|
|
|
// put the stuff we've been drawing onto the display
|
|
|
|
glfwSwapBuffers(window); |
|
|
|
} |
|
|
|
|
|
|
|
reop.pages.clear(); |
|
|
|
reop.metadata.clear(); |
|
|
|
reop.records.clear(); |
|
|
|
reop.delete_table.clear(); |
|
|
|
|
|
|
|
db.pages.clear(); |
|
|
|
db.metadata.clear(); |
|
|
|
db.records.clear(); |
|
|
|
db.delete_table.clear(); |
|
|
|
} |
|
|
|
#endif
|
|
|
|
database run_db(database::create("/tmp/", 4096)); |
|
|
|
auto soc = socket(AF_INET, SOCK_DGRAM, 0); |
|
|
|
struct sockaddr_in addr; |
|
|
|
addr.sin_family = AF_INET; |
|
|
|
addr.sin_port = htons(20450); |
|
|
|
memset((void*)&addr.sin_addr, 0, sizeof(addr.sin_addr)); |
|
|
|
bind(soc,(struct sockaddr*)&addr,sizeof(addr)); |
|
|
|
|
|
|
|
do{ |
|
|
|
received_data recv; |
|
|
|
sending_data reply; |
|
|
|
sockaddr_in client; |
|
|
|
socklen_t packet_sz; |
|
|
|
size_t reply_size; |
|
|
|
recvfrom( |
|
|
|
soc, |
|
|
|
(void*)&recv, |
|
|
|
sizeof(received_data), |
|
|
|
MSG_WAITFORONE, |
|
|
|
(struct sockaddr*)&client, |
|
|
|
&packet_sz |
|
|
|
); |
|
|
|
|
|
|
|
if(packet_sz < sizeof(db_op)) continue; |
|
|
|
|
|
|
|
switch (static_cast<db_op>(recv.op)) |
|
|
|
{ |
|
|
|
case db_op::version: |
|
|
|
reply.rep_id = recv.rep_id; |
|
|
|
reply.identifier.x = 1; |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier.x); |
|
|
|
break; |
|
|
|
case db_op::read: |
|
|
|
{ |
|
|
|
reply.rep_id = recv.rep_id; |
|
|
|
auto req = run_db.read(recv.identifier); |
|
|
|
if(req.first != 0) |
|
|
|
{ |
|
|
|
reply.identifier = recv.identifier; |
|
|
|
reply.page = req.second; |
|
|
|
reply_size = sizeof(reply); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
case db_op::write: |
|
|
|
{ |
|
|
|
reply.rep_id = recv.rep_id; |
|
|
|
try{ |
|
|
|
run_db.write(recv.identifier, recv.page); |
|
|
|
reply.identifier = recv.identifier; |
|
|
|
} catch (...) { |
|
|
|
|
|
|
|
} |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier); |
|
|
|
} |
|
|
|
break; |
|
|
|
case db_op::remove: |
|
|
|
{ |
|
|
|
reply.rep_id = recv.rep_id; |
|
|
|
run_db.remove(recv.identifier); |
|
|
|
reply.identifier = recv.identifier; |
|
|
|
reply_size = sizeof(reply.rep_id) + sizeof(reply.identifier); |
|
|
|
} |
|
|
|
break; |
|
|
|
default: |
|
|
|
std::cerr << "bad_request " << (uint32_t)static_cast<db_op>(recv.op) << std::endl; |
|
|
|
continue; |
|
|
|
break; |
|
|
|
} |
|
|
|
sendto( |
|
|
|
soc, |
|
|
|
(void*)&reply, |
|
|
|
reply_size, |
|
|
|
0, |
|
|
|
(struct sockaddr*)&client, |
|
|
|
(socklen_t)sizeof(client) |
|
|
|
); |
|
|
|
//std::cerr << "reply to " << (uint32_t)static_cast<db_op>(recv.op) << std::endl;
|
|
|
|
}while(true); |
|
|
|
|
|
|
|
// close GL context and any other GLFW resources
|
|
|
|
glfwTerminate(); |
|
|
|
return 0; |
|
|
|
} |