计算着色器的双精度(完整代码)

时间:2015-08-24 06:00:37

标签: opengl glsl double-precision

我使用ssbo将双精度数据发送到我的计算着色器,但不知何故在着色器中某处丢失了精度。我发布了此问题here但尚未收到回复。

我读了一个包含我在计算中使用的4个双打的位置。如果我在着色器的开头将位置写入缓冲区,则值是正确的。如果我在计算后写入缓冲区,则会出现精度损失。我永远不会改变位置的值。在我的测试中,我甚至可以改变" true"到"变量==变量"并且只有那个松散的精度。部分代码显示在我链接的帖子中。

我的常量有类似的问题,用LF后缀解决了。是否有类似的变量修复?

我试图找出问题,这是我的代码:

我的.csh文件:

#version 430

struct aVec4 {
  double x, y, z, w;
};

struct FT {
  aVec4 force;
  aVec4 torque;
};

struct Triangle {
  aVec4 position;
  aVec4 normal;
  aVec4 depth;
};

layout( std430, binding = 0 ) buffer abc { Triangle bs[]; };
layout( std430, binding = 1 ) buffer def { FT forces[]; };
layout( local_size_x = 1 ) in;

dvec3 toVec3( in aVec4 vector ) {
  dvec3 v = dvec3( vector.x, vector.y, vector.z );
  return v;
}

aVec4 function1( inout Triangle triangles[2], inout int numTriangles ) {
  Triangle anotherTriangle = bs[gl_GlobalInvocationID.x];
  int numBelow = 1;

  if ( anotherTriangle.depth.x < 0.0LF ) {
    numBelow++;
  }

  if ( numBelow == numBelow ) {
    numTriangles = 1;

    aVec4 result = anotherTriangle.position;
    return result;
  }
}

FT function2( in Triangle triangles[2], in int numTriangles ) {
  FT ft;
  dvec3 force = dvec3( 0.0LF, 0.0LF, 0.0LF );

  for ( int i = 0; i < numTriangles; i++ ){
    dvec3 normal  = toVec3( triangles[i].normal );
    force  += - normal;
  }

  ft.force = triangles[0].position;
  return ft;
}

void main()
{
  Triangle triangles[2];
  triangles[0] = bs[gl_GlobalInvocationID.x];
  int numTriangles = 1;

  aVec4 result = function1( triangles, numTriangles );
  FT ft = function2( triangles, numTriangles );
  ft.torque = result;

  forces[gl_GlobalInvocationID.x] = ft;
}

我的.cpp文件:

#include <GL/glew.h>
#include <GL/freeglut.h>

#include <vector>

#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>

#include <cmath>

class Vec3
{
public:
  Vec3()
    : x(0)
    , y(0)
    , z(0)
    , w(0)
  {
  }

  Vec3(double x, double y, double z)
    : x(x)
    , y(y)
    , z(z)
    , w(0)
  {
  }

  double x, y, z, w;
};


std::ostream& operator<<(std::ostream& stream, const Vec3& v)
{
  stream << std::setprecision(20) << std::setw(20) << std::scientific;
  stream << "Vec3(" <<
    std::setw(23) << v.x << ", " <<
    std::setw(23) << v.y << ", " <<
    std::setw(23) << v.z << ") (" <<
    std::setw(23) << v.w << ")";
  return stream;
}


GLuint loadShader( std::string fileName )
{
  GLuint program = glCreateProgram( );
  GLuint shader = glCreateShader( GL_COMPUTE_SHADER );

  std::ifstream shaderStream(fileName.c_str(), std::ios::in );
  if (!shaderStream.is_open())
  {
    std::cout << "Could not open shader source file '" << fileName << "'." << std::endl;
    exit(1);
  }

  std::string src;
  std::string line = "";
  while ( getline( shaderStream, line ) )
    src += "\n" + line;

  char const* srcPointer = src.c_str( );
  glShaderSource( shader, 1, &srcPointer, NULL );
  glCompileShader( shader );

  int rValue;
  glGetShaderiv( shader, GL_COMPILE_STATUS, &rValue );
  if (!rValue)
  {
    std::cout << "Unable to compile compute shader" << std::endl;
    GLchar log[ 10240 ];
    GLsizei length;
    glGetShaderInfoLog( shader, 10239, &length, log );
    fprintf( stderr, "Compiler log:\n%s\n", log );
    exit( 40 );
  }

  glAttachShader(program, shader);
  glLinkProgram(program);

  glGetProgramiv( program, GL_LINK_STATUS, &rValue );
  if (!rValue)
  {
    std::cout << "Unable to link compute shader program" << std::endl;
    GLchar log[ 10240 ];
    GLsizei length;
    glGetProgramInfoLog( program, 10239, &length, log );
    fprintf( stderr, "Linker log:\n%s\n", log );
    exit( 41 );
  }

  glDeleteShader( shader );

  return program;
}

struct ShaderData
{
  Vec3 position;
  Vec3 normal;
  Vec3 depth;
};



int main( int argc, char **argv ) {

  glutInit( &argc, argv );
  glutCreateWindow( "TEST1" ); //TODO: Why?

  glewInit( );

  std::string shaderFileName = "tutorial_computeShaderBugSearch.csh";
  GLuint program = loadShader( shaderFileName );

  GLuint ssbo;
  GLuint result;

  glGenBuffers( 1, &ssbo );
  glGenBuffers( 1, &result );

  glUseProgram( program );

  std::vector< ShaderData > buf;
  buf.resize( 1 );

  ShaderData shaderData;
  shaderData.position = Vec3( double(1) / double(3), 0, 0 );
  shaderData.normal = Vec3( 1, 1, 1 );
  shaderData.depth.x = 1;
  buf[ 0 ] = shaderData;

  glBindBuffer( GL_SHADER_STORAGE_BUFFER, ssbo );
  glBufferData( GL_SHADER_STORAGE_BUFFER, buf.size( ) * sizeof(ShaderData), buf.data( ), GL_STATIC_DRAW );

  std::vector< Vec3 > forces;
  forces.resize( 2 ); // 1 for the forces + 1 for the torques

  glBindBuffer( GL_SHADER_STORAGE_BUFFER, result );
  glBufferData( GL_SHADER_STORAGE_BUFFER, forces.size( ) * sizeof(Vec3), forces.data( ), GL_STATIC_DRAW );

  glUseProgram( program );
  glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 0, ssbo );
  glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 1, result );
  glDispatchCompute( 1, 1, 1 );
  glMemoryBarrier( GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT );

  glBindBuffer( GL_SHADER_STORAGE_BUFFER, result );
  Vec3* ptr = (Vec3*)glMapBuffer( GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY );

  Vec3 a = ptr[ 0 ];
  Vec3 b = ptr[ 1 ];

  std::cout << "a: " << std::setprecision(20) << a.x << std::endl;
  std::cout << "b: " << std::setprecision(20) << b.x << std::endl;
  std::cout << "diff: " << std::abs(a.x-b.x) << std::endl;
}

这会产生输出:

a: 0.3333333432674408
b: 0.33333333333333331
diff: 9.9341074810688212e-099

0 个答案:

没有答案