Advertisement
Guest User

Untitled

a guest
May 25th, 2019
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.93 KB | None | 0 0
  1. #include <cmath>
  2. #include <vector>
  3. #include <string>
  4. #include <limits>
  5. #include <iomanip>
  6. #include <iostream>
  7. // glad.h is generated by the following command:
  8. // glad --out-path=. --generator=c --omit-khrplatform --api="gl=3.3" --profile=core --extensions=
  9. #include "glad/glad.h"
  10. #include <GL/freeglut.h>
  11. #include <glm/glm.hpp>
  12. using glm::vec4;
  13.  
  14. GLuint vao, vbo;
  15. GLuint texFBO;
  16. GLuint inputTextures[2];
  17. GLuint program;
  18. GLuint fbo;
  19. int width=1, height=2;
  20.  
  21. void printShaderOutput(int texW, int texH)
  22. {
  23.     glActiveTexture(GL_TEXTURE0);
  24.     glBindTexture(GL_TEXTURE_2D, texFBO);
  25.  
  26.     std::vector<vec4> data(texW*texH);
  27.     glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, data.data());
  28.     std::cout << "a,b,sum,product,relError(sum),relError(product),note\n";
  29.     for(int i=0;i<width;++i)
  30.     {
  31.         const auto a=double(data[i+width*0].x)+double(data[i+width*0].y);
  32.         const auto b=double(data[i+width*0].z)+double(data[i+width*0].w);
  33.         const auto sum=double(data[i+width*1].x)+double(data[i+width*1].y);
  34.         const auto product=double(data[i+width*1].z)+double(data[i+width*1].w);
  35.         const auto trueSum=a+b, trueProduct=a*b;
  36.         const auto sumErr=(sum-trueSum)/trueSum;
  37.         const auto prodErr=(product-trueProduct)/trueProduct;
  38.         std::cout << std::setprecision(std::numeric_limits<double>::max_digits10)
  39.                   << a << ',' << b << ','
  40.                   << sum << ',' << product << ','
  41.                   << std::setprecision(3)
  42.                   << sumErr << ',' << prodErr << ','
  43.                   << (std::abs(sumErr)>1e-14 || std::abs(prodErr)>1e-14 ? "WARN" : "OK")
  44.                   << '\n';
  45.     }
  46.     std::cout.flush();
  47. }
  48.  
  49. GLuint makeShader(GLenum type, std::string const& srcStr)
  50. {
  51.     const auto shader=glCreateShader(type);
  52.     const GLint srcLen=srcStr.size();
  53.     const GLchar*const src=srcStr.c_str();
  54.     glShaderSource(shader, 1, &src, &srcLen);
  55.     glCompileShader(shader);
  56.     GLint status=-1;
  57.     glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
  58.     assert(glGetError()==GL_NO_ERROR);
  59.     assert(status);
  60.     return shader;
  61. }
  62.  
  63. void loadShaders()
  64. {
  65.     program=glCreateProgram();
  66.  
  67.     const auto vertexShader=makeShader(GL_VERTEX_SHADER, 1+R"(
  68. #version 330
  69. in vec4 vertex;
  70. void main() { gl_Position=vertex; }
  71. )");
  72.     glAttachShader(program, vertexShader);
  73.  
  74.     const auto fragmentShader=makeShader(GL_FRAGMENT_SHADER, 1+R"(
  75. #version 330
  76. #extension GL_ARB_gpu_shader5 : require
  77.  
  78. // Emulation based on Fortran-90 double-single package. See http://crd-legacy.lbl.gov/~dhbailey/mpdist/
  79. // Add: res = ds_add(a, b) => res = a + b
  80. vec2 ds_add(vec2 dsa, vec2 dsb)
  81. {
  82.    precise float t1 = dsa.x + dsb.x;
  83.    precise float e = t1 - dsa.x;
  84.    precise float t2 = ((dsb.x - e) + (dsa.x - (t1 - e))) + dsa.y + dsb.y;
  85.  
  86.    precise vec2 dsc;
  87.    dsc.x = t1 + t2;
  88.    dsc.y = t2 - (dsc.x - t1);
  89.    return dsc;
  90. }
  91.  
  92. // Multiply: res = ds_mul(a, b) => res = a * b
  93. vec2 ds_mul(vec2 dsa, vec2 dsb)
  94. {
  95.    const float split = 8193.;
  96.  
  97.    precise float cona = dsa.x * split;
  98.    precise float conb = dsb.x * split;
  99.    precise float a1 = cona - (cona - dsa.x);
  100.    precise float b1 = conb - (conb - dsb.x);
  101.    precise float a2 = dsa.x - a1;
  102.    precise float b2 = dsb.x - b1;
  103.  
  104.    precise float c11 = dsa.x * dsb.x;
  105.    precise float c21 = a2 * b2 + (a2 * b1 + (a1 * b2 + (a1 * b1 - c11)));
  106.  
  107.    precise float c2 = dsa.x * dsb.y + dsa.y * dsb.x;
  108.  
  109.    precise float t1 = c11 + c2;
  110.    precise float e = t1 - c11;
  111.    precise float t2 = dsa.y * dsb.y + ((c2 - e) + (c11 - (t1 - e))) + c21;
  112.  
  113.    precise vec2 dsc;
  114.    dsc.x = t1 + t2;
  115.    dsc.y = t2 - (dsc.x - t1);
  116.  
  117.    return dsc;
  118. }
  119.  
  120. uniform sampler1D opA, opB;
  121. uniform float rtWidth;
  122. out vec4 color;
  123.  
  124. void main()
  125. {
  126.    float texCoord=gl_FragCoord.x/rtWidth;
  127.    vec2 a=texture(opA,texCoord).xy;
  128.    vec2 b=texture(opB,texCoord).xy;
  129.    if(gl_FragCoord.y<1)   // first row
  130.        color=vec4(a,b);
  131.    else if(gl_FragCoord.y<2)   // second row
  132.        color=vec4(ds_add(a,b),ds_mul(a,b));
  133. }
  134.  
  135. )");
  136.     glAttachShader(program, fragmentShader);
  137.  
  138.     glLinkProgram(program);
  139.     GLint status=0;
  140.     glGetProgramiv(program, GL_LINK_STATUS, &status);
  141.     assert(glGetError()==GL_NO_ERROR);
  142.     assert(status);
  143.  
  144.     glDetachShader(program, fragmentShader);
  145.     glDeleteShader(fragmentShader);
  146.  
  147.     glDetachShader(program, vertexShader);
  148.     glDeleteShader(vertexShader);
  149. }
  150.  
  151. void setupBuffers()
  152. {
  153.     glGenVertexArrays(1, &vao);
  154.     glBindVertexArray(vao);
  155.     glGenBuffers(1, &vbo);
  156.     glBindBuffer(GL_ARRAY_BUFFER, vbo);
  157.     const GLfloat vertices[]=
  158.     {
  159.         -1, -1,
  160.          1, -1,
  161.         -1,  1,
  162.          1,  1,
  163.     };
  164.     glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW);
  165.     constexpr GLuint attribIndex=0;
  166.     constexpr int coordsPerVertex=2;
  167.     glVertexAttribPointer(attribIndex, coordsPerVertex, GL_FLOAT, false, 0, 0);
  168.     glEnableVertexAttribArray(attribIndex);
  169.     glBindVertexArray(0);
  170. }
  171.  
  172. void setupRenderTarget()
  173. {
  174.     glGenTextures(1, &texFBO);
  175.     glGenFramebuffers(1,&fbo);
  176. }
  177.  
  178. void setupInputTextures()
  179. {
  180.     glGenTextures(2, inputTextures);
  181.     {
  182.         glBindTexture(GL_TEXTURE_1D, inputTextures[0]);
  183.         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  184.         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  185. #define SPLIT_DOUBLE_TO_FLOATS(x) GLfloat(x),GLfloat(x-GLfloat(x))
  186.         static constexpr GLfloat data[]=
  187.         {
  188.             SPLIT_DOUBLE_TO_FLOATS(3.1415926535897932),
  189.         };
  190.         glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, sizeof data/sizeof*data/2, 0, GL_RG, GL_FLOAT, data);
  191.     }
  192.     {
  193.         glBindTexture(GL_TEXTURE_1D, inputTextures[1]);
  194.         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  195.         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  196.         static constexpr GLfloat data[]=
  197.         {
  198.             SPLIT_DOUBLE_TO_FLOATS(2.7182818284590452),
  199.         };
  200.         glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, sizeof data/sizeof*data/2, 0, GL_RG, GL_FLOAT, data);
  201.     }
  202. }
  203.  
  204. bool init()
  205. {
  206.     if(!gladLoadGL())
  207.     {
  208.         std::cerr << "Failed to initialize GLAD\n";
  209.         return false;
  210.     }
  211.     if(!GLAD_GL_VERSION_3_3)
  212.     {
  213.         std::cerr << "OpenGL 3.3 not supported\n";
  214.         return false;
  215.     }
  216.  
  217.     setupRenderTarget();
  218.     setupInputTextures();
  219.     loadShaders();
  220.     setupBuffers();
  221.  
  222.     glViewport(0,0,width,height);
  223.  
  224.     glBindTexture(GL_TEXTURE_2D,texFBO);
  225.     glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32F,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,nullptr);
  226.     glBindTexture(GL_TEXTURE_2D,0);
  227.     glBindFramebuffer(GL_FRAMEBUFFER,fbo);
  228.     glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,texFBO,0);
  229.     const auto status=glCheckFramebufferStatus(GL_FRAMEBUFFER);
  230.     assert(status==GL_FRAMEBUFFER_COMPLETE);
  231.     glBindFramebuffer(GL_FRAMEBUFFER,0);
  232.  
  233.     return true;
  234. }
  235.  
  236. void display()
  237. {
  238.     const static bool inited=init();
  239.     if(!inited) std::exit(1);
  240.  
  241.     glBindFramebuffer(GL_FRAMEBUFFER,fbo);
  242.  
  243.     glUseProgram(program);
  244.     glActiveTexture(GL_TEXTURE0);
  245.     glBindTexture(GL_TEXTURE_1D, inputTextures[0]);
  246.     glActiveTexture(GL_TEXTURE1);
  247.     glBindTexture(GL_TEXTURE_1D, inputTextures[1]);
  248.     glUniform1i(glGetUniformLocation(program,"opA"),0);
  249.     glUniform1i(glGetUniformLocation(program,"opB"),1);
  250.     glUniform1f(glGetUniformLocation(program,"rtWidth"),width);
  251.  
  252.     glBindVertexArray(vao);
  253.     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  254.     glBindVertexArray(0);
  255.  
  256.     printShaderOutput(width, height);
  257.     std::exit(0);
  258.  
  259.     glFinish();
  260. }
  261.  
  262. int main(int argc, char** argv)
  263. {
  264.     glutInitContextVersion(3,3);
  265.     glutInitContextProfile(GLUT_CORE_PROFILE);
  266.     glutInit(&argc, argv);
  267.  
  268.     glutInitDisplayMode(GLUT_RGB);
  269.  
  270.     glutInitWindowSize(width, height);
  271.     glutCreateWindow("Test");
  272.     glutDisplayFunc(display);
  273.  
  274.     glutMainLoop();
  275. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement