簡體   English   中英

更改cuda內核時,為什么cudaGraphicsGLRegisterBuffer出現段錯誤?

[英]Why does cudaGraphicsGLRegisterBuffer segfault when I change my cuda kernel?

我正在使用帶有cuda工具包6.5,nvidia驅動程序版本340.29的Ubuntu 14.04。 我的應用程序從openGL注冊一個像素緩沖區,並在每個循環中將圖像寫入緩沖區,使用glTexSubImage2D將PBO復制到紋理,然后繪制紋理。 在更改圖像生成內核之前,這一切都可以正常工作,然后我的gdb報告cudaGraphicsGLRegisterBuffer中的分段錯誤。 我的猜測是這是一個錯誤,因為cuda內核與cudaGraphicsGLRegisterBuffer完全無關,后者在任何處理之前都會被調用。

生成文件

CUDA=nvcc
CPP=g++

OUT=out

INC=-I/usr/local/cuda-6.5/include

LINK=-lcudart -lglfw -lGLEW -lGL

FLAGS=-std=gnu++11
CUFLAGS=-std=c++11

all: main.cu GLdisplay.cu
    $(CUDA) main.cu GLdisplay.cu -o $(OUT) $(CUFLAGS) $(INC) $(LINK)

clean:
    rm ./$(OUT)

add:
    git add -A
    git status

main.cu

#define  GLEW_STATIC

// C++ headers
#include <iostream>
#include <fstream>
#include <cstring>

// openGL headers
#include <GL/glew.h>
#include <GLFW/glfw3.h>

// CUDA headers
#include <cuda_runtime.h>
#include <cuda_gl_interop.h>

#include "GLdisplay.h"

#define WINDOW_WIDTH  640
#define WINDOW_HEIGHT 480

#define TEX_WIDTH     1920
#define TEX_HEIGHT    1080

using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::ifstream;

GLFWwindow* window;
GLuint vao, vbo, pbo;
GLuint vtx, frg, shaders;
GLuint tex;

uint8_t* cudaPBOptr;
size_t cudaPBOsize;

cudaGraphicsResource_t cuGfxPBO;

string loadTxtFileAsString( string filename )
{
    string source;
    string buf = "";
    ifstream file( filename, std::ios::in );

    while( file.good( ) )
    {
        std::getline( file, buf );
        source.append( buf + "\n" );
    }

    file.close( );

    return source;
}

void shaderCompileCheck( void )
{
    GLint status;

    // vertex
    glGetShaderiv( vtx, GL_COMPILE_STATUS, &status );

    if( GL_TRUE != status )
    {
        char buffer[ 512 ];
        glGetShaderInfoLog( vtx, 512, NULL, buffer );
        cerr << "vtx err | " << buffer << endl;
    }

    // fragment
    glGetShaderiv( frg, GL_COMPILE_STATUS, &status );

    if( GL_TRUE != status )
    {
        char buffer[ 512 ];
        glGetShaderInfoLog( frg, 512, NULL, buffer );
        cerr << "frg err | " << buffer << endl;
    }
}

// added exit on !cudaSuccess
#define cudaErr(err) cudaError( err, __FILE__, __LINE__ )
inline void cudaError( cudaError_t err, const char* file, uint32_t line, bool abort=true )
{
    if( cudaSuccess != err )
    {
        cerr << "[" << file << ":" << line << "] ";
        cerr << cudaGetErrorName( err ) << endl; // print the name instead of description
        if( abort ) exit( err );
    }
}

// added GL error checking
#define glErr( ) glError( glGetError( ), __FILE__, __LINE__ )
inline void glError( GLenum err, const char* file, uint32_t line, bool abort=false )
{
    if( GL_NO_ERROR != err )
    {
        cerr << "[" << file << ":" << line << "] ";
        cerr << glewGetErrorString( err ) << endl;
        if( abort ) exit( err );
    }
}

// main function
int main( int argc, char* argv[] )
{
    string vString = loadTxtFileAsString( "vert.glsl" );
    string fString = loadTxtFileAsString( "frag.glsl" );

    const GLchar* vtxSource = vString.c_str( );
    const GLchar* frgSource = fString.c_str( );

/////////////////////////////////////////////////

    glfwInit( );

    glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
    glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 2 );
    glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
    glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );

    glfwWindowHint( GLFW_RESIZABLE, GL_FALSE );

    window = glfwCreateWindow( WINDOW_WIDTH, WINDOW_HEIGHT, "CUDA-GL", NULL, NULL );

    glfwMakeContextCurrent( window );

    glewExperimental = GL_TRUE;
    glewInit( );
    glErr(); // added GL error checking

    cudaErr( cudaSetDevice( 0 ) );
    glErr(); // added GL error checking

/////////////////////////////////////////////////

    GLfloat vertices[] = {
    //   X      Y     U     V
        -1.0f,  1.0f, 0.0f, 1.0f, // t l
         1.0f,  1.0f, 1.0f, 1.0f, // t r
        -1.0f, -1.0f, 0.0f, 0.0f, // b l

        -1.0f, -1.0f, 0.0f, 0.0f, // b l
         1.0f, -1.0f, 1.0f, 0.0f, // b r
         1.0f,  1.0f, 1.0f, 1.0f  // t r
    };

    GLbyte pboInit[ TEX_WIDTH * TEX_HEIGHT * 4 ];
    memset( pboInit, 127, sizeof( pboInit ) );

/////////////////////////////////////////////////

    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );
    glErr(); // added GL error checking

    glGenBuffers( 1, &pbo );
    glBindBuffer( GL_PIXEL_UNPACK_BUFFER, pbo );
    glBufferData( GL_PIXEL_UNPACK_BUFFER, TEX_WIDTH * TEX_HEIGHT * 4, pboInit, GL_STREAM_DRAW );
    glBindBuffer( GL_PIXEL_UNPACK_BUFFER, 0 );
    glErr(); // added GL error checking

    glActiveTexture( GL_TEXTURE0 );
    glGenTextures( 1, &tex );
    glBindTexture( GL_TEXTURE_2D, tex );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glErr(); // added GL error checking

    glGenBuffers( 1, &vbo );
    glBindBuffer( GL_ARRAY_BUFFER, vbo );
    glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
    glErr(); // added GL error checking

/////////////////////////////////////////////////

    cudaErr( cudaGraphicsGLRegisterBuffer( &cuGfxPBO, pbo, cudaGraphicsMapFlagsNone ) );
    glErr(); // added GL error checking

/////////////////////////////////////////////////

    vtx = glCreateShader( GL_VERTEX_SHADER );
    glShaderSource( vtx, 1, &vtxSource, NULL );
    glCompileShader( vtx );

    frg = glCreateShader( GL_FRAGMENT_SHADER );
    glShaderSource( frg, 1, &frgSource, NULL );
    glCompileShader( frg );

    shaderCompileCheck( );

    shaders = glCreateProgram( );
    glAttachShader( shaders, vtx );
    glAttachShader( shaders, frg );

    glBindFragDataLocation( shaders, 0, "outColor" );

    glLinkProgram( shaders );
    glUseProgram( shaders );

/////////////////////////////////////////////////

    GLuint posAtt = glGetAttribLocation( shaders, "position" );
    glEnableVertexAttribArray( posAtt );
    glVertexAttribPointer( posAtt, 2, GL_FLOAT, GL_FALSE, 4 * sizeof( GLfloat ), NULL );

    GLuint texAtt = glGetAttribLocation( shaders, "texcoord" );
    glEnableVertexAttribArray( texAtt );
    glVertexAttribPointer( texAtt, 2, GL_FLOAT, GL_FALSE, 4 * sizeof( GLfloat ), ( void* )( 2 * sizeof( GLfloat ) ) );

/////////////////////////////////////////////////

    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );

    while( !glfwWindowShouldClose( window ) )
    {
        cudaErr( cudaGraphicsMapResources( 1, &cuGfxPBO, 0 ) );
        cudaErr( cudaGraphicsResourceGetMappedPointer( ( void** )&cudaPBOptr, &cudaPBOsize, cuGfxPBO ) );
        glErr(); // added GL error checking

        dim3 gridDim( ( int32_t )ceil( ( float )TEX_WIDTH / 16 ), ( int32_t )ceil( ( float )TEX_HEIGHT / 16 ) );
        dim3 blockDim( 16, 16 );

        makeImage<<< gridDim, blockDim >>>( cudaPBOptr, TEX_WIDTH, TEX_HEIGHT );
        cudaDeviceSynchronize( ); cudaErr( cudaGetLastError( ) );
        glErr(); // added GL error checking

        cudaErr( cudaGraphicsUnmapResources( 1, &cuGfxPBO, 0 ) );
        glErr(); // added GL error checking

/////////////////////////////////////////////////

        glBindBuffer( GL_PIXEL_UNPACK_BUFFER, pbo );
        glErr(); // added GL error checking

        glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, TEX_WIDTH, TEX_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
        glErr(); // added GL error checking

        glBindBuffer( GL_PIXEL_UNPACK_BUFFER, 0 );
        glErr(); // added GL error checking

/////////////////////////////////////////////////

        glClear( GL_COLOR_BUFFER_BIT );

        glDrawArrays( GL_TRIANGLES, 0, 6 );
        glErr(); // added GL error checking

        glfwSwapBuffers( window );

        glfwPollEvents( );
    }

/////////////////////////////////////////////////

    glDeleteTextures( 1, &tex );

    glDeleteProgram( shaders );
    glDeleteShader( frg );
    glDeleteShader( vtx );

    glDeleteBuffers( 1, &pbo );
    glDeleteBuffers( 1, &vbo );

    glDeleteVertexArrays( 1, &vao );

    return 0;
}

GLdisplay.cu

#include <cuda_runtime.h>
#include <stdint.h>

#include "GLdisplay.h"

__global__ void makeImage( uint8_t* output, uint32_t width, uint32_t height )
{
    uint32_t xIdx = threadIdx.x + blockIdx.x * blockDim.x;
    uint32_t yIdx = threadIdx.y + blockIdx.y * blockDim.y;
    uint32_t oIdx = ( xIdx + yIdx * width ) * 4;

    if( xIdx >= width || yIdx >= height ) return;

// segfault occurs if any of the lines below are commented or set to write 0
    uint8_t red = ( uint8_t )( 255.0f * ( float )( xIdx + yIdx * width ) / ( width * height ) );
    uint8_t gre = ( uint8_t )( 255.0f * ( 1.0f - ( float )( xIdx + yIdx * width ) / ( width * height ) ) );
    uint8_t blu = ( uint8_t )( 510.0f * abs( ( float )( xIdx + yIdx * width ) / ( width * height ) ) - 0.5f );

    output[ oIdx + 0 ] = red;
    output[ oIdx + 1 ] = gre;
    output[ oIdx + 2 ] = blu;
    output[ oIdx + 3 ] = 255;

 }

GLdisplay.h

#ifndef GL_DISPLAY_H
#define GL_DISPLAY_H

__global__ void makeImage( uint8_t*, uint32_t, uint32_t );

#endif

vert.glsl

#version 150

in vec2 position;
in vec2 texcoord;

out vec2 Texcoord;

void main( )
{
    Texcoord = texcoord;
    gl_Position = vec4( position, 0.0, 1.0 );
}

frag.glsl

#version 150

in vec2 Texcoord;

out vec4 outColor;

uniform sampler2D tex;

void main( )
{
    outColor = texture( tex, Texcoord );
}

您的代碼缺少錯誤條件檢查。 首先,我建議您在每次調用OpenGL和CUDA之后檢查錯誤代碼的狀態。 我很清楚問題是什么,添加錯誤檢查將告訴您是否是這種情況。

因此:我發現您在嘗試將PBO映射到CUDA指針之前從未將其與OpenGL解除綁定。 根據您的程序所采用的路徑,這可能會導致PBO實際上沒有被映射,因此給您一個無效的指針,如果從CUDA內核或主機進行訪問,將導致segfault。

要確定問題所在,請檢查每個OpenGL和CUDA操作的錯誤狀態。 CUDA會告訴您是否由於某種原因無法映射OpenGL資源(例如該資源仍綁定到OpenGL功能單元)。

更新為nvidia顯示驅動器346.47完全解決了我的問題。 不確定,請在終端窗口中運行nvidia-smi ,如果看不到NVIDIA-SMI 346.xx (xx是任意數字),請使用nvidia的最新驅動程序進行更新。 在撰寫本文時,CUDA工具包6.5附帶了過時的圖形驅動程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM