我一直试图在CUDA中使用表面引用来处理OpenGL互操作。我能够毫无问题地使用表面对象来做到这一点,但我想支持不支持表面对象的旧硬件(计算< 2.5)。
请注意:昨天我有一个similar question,有人建议我写一个简单的问题证明。在这样做时,我遇到了一个稍微不同的问题,所以我问了一个新问题。在这种情况下,在下面列出的代码中,当我调用cudaBindSurfaceToArray
时,我收到错误
CUDA error at test.cu:75 code=37(cudaErrorInvalidSurface) "cudaBindSurfaceToArray(outputSurface, textureArray)"
不幸的是,由于GL interop,这个“最小”示例代码相当长。它没有外部依赖关系,只有CUDA开发文件和CUDA示例。它使用命令
在Linux中编译nvcc -m64 -ccbin g++ -gencode arch=compute_20,code=sm_20 -I<samples_path>/NVIDIA_CUDA-7.0_Samples/common/inc -lGL -lglut test.cu -o test
此代码与CUDA示例simpleSurfaceWrite
非常相似。我不明白我的代码中的表面引用与该示例中的表面引用有何不同。为了记录,我能够成功编译并运行simpleSurfaceWrite
。请注意,这使用了来自CUDA C ++ API的cudaBindSurfaceToArray
simpleSurfaceWrite
,就像#define GL_GLEXT_PROTOTYPES
#include <GL/freeglut.h>
#include <cuda_runtime.h>
#include <cuda_gl_interop.h>
#include <helper_functions.h>
#include <helper_cuda.h>
#include <helper_cuda_gl.h>
GLuint texID;
GLuint bufID;
GLenum passthroughVertexShaderID;
GLenum simpleFragmentShaderID;
GLenum simpleProgramID;
GLint fragmentShaderTextureID;
cudaGraphicsResource *texResource;
const int width = 640;
const int height = 480;
const int blockSize = 8;
// Define a CUDA surface reference
surface<void, cudaSurfaceType2D> outputSurface;
// Define some simple GL shaders
const GLchar *passthroughVertexSource =
"#version 130"
"in vec3 positionAttrib;"
"in vec2 textureAttrib;"
"out vec2 texCoord;"
"void main()"
"{"
" gl_Position = vec4(positionAttrib,1.0f);"
" texoord = textureAttrib;"
"}";
const GLchar *simpleFragmentSource =
"#version 130"
"uniform sampler2DRect tex;"
"in vec2 texCoord;"
"out vec4 fragColor;"
"void main()"
"{"
" fragColor = texture2DRect(tex, texCoord);"
"}";
__global__ void cudaTestKernel() {
int x = blockIdx.x*blockDim.x + threadIdx.x;
int y = blockIdx.y*blockDim.y + threadIdx.y;
float4 sample = make_float4(0.0f, 1.0f, 0.0f, 1.0f);
surf2Dwrite(sample, outputSurface, (int)sizeof(float4)*x, y, cudaBoundaryModeClamp);
}
void displayFunc() {
// Clear the screen (if nothing else is drawn, screen will be blue)
glClear(GL_COLOR_BUFFER_BIT);
// Make the OpenGL texture available to CUDA through the `outputSurface' surface reference
checkCudaErrors(cudaGraphicsMapResources(1, &texResource, 0));
cudaArray *textureArray;
checkCudaErrors(cudaGraphicsSubResourceGetMappedArray(&textureArray, texResource, 0, 0));
// Bind the array to the surface. This is where I'm getting an error
checkCudaErrors(cudaBindSurfaceToArray(outputSurface, textureArray));
// Call the CUDA kernel
dim3 grid = dim3(blockSize,blockSize,1);
dim3 block = dim3(width/blockSize, height/blockSize, 1);
cudaTestKernel<<<grid,block>>>();
checkCudaErrors(cudaGraphicsUnmapResources(1, &texResource, 0));
// Call the OpenGL shaders to draw the texture
// If the CUDA kernel was successful, the screen will be green
// If not, it will be gray.
glActiveTexture(GL_TEXTURE0);
glUseProgram(simpleProgramID);
glUniform1i(fragmentShaderTextureID, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, texID);
glBindBuffer(GL_ARRAY_BUFFER, bufID);
glDrawArrays(GL_QUADS, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
glutSwapBuffers();
}
int main(int argc, char **argv) {
float *floatBuf;
// Initialize GLUT/GL
glutInit (&argc, argv);
glutInitWindowSize(width,height);
glutCreateWindow("Surface Test");
glutDisplayFunc(displayFunc);
// Initialize CUDA
findCudaGLDevice(argc, (const char**)argv);
// Create Texture
floatBuf = new float[width*height*4];
for(unsigned int i=0;i<width*height*4;i++)
floatBuf[i]=0.5f;
glGenTextures(1, &texID);
glEnable(GL_TEXTURE_RECTANGLE_NV);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, texID);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA32F_ARB, width, height, 0, GL_RGBA, GL_FLOAT, floatBuf);
delete [] floatBuf;
// Map Texture into CUDA
checkCudaErrors(cudaGraphicsGLRegisterImage(&texResource, texID, GL_TEXTURE_RECTANGLE_NV, cudaGraphicsRegisterFlagsSurfaceLoadStore));
// Create shader program
simpleProgramID = glCreateProgram();
simpleFragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
passthroughVertexShaderID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(simpleFragmentShaderID, 1, &simpleFragmentSource, NULL);
glShaderSource(passthroughVertexShaderID, 1, &passthroughVertexSource, NULL);
glCompileShader(simpleFragmentShaderID);
glCompileShader(passthroughVertexShaderID);
glAttachShader(simpleProgramID, simpleFragmentShaderID);
glAttachShader(simpleProgramID, passthroughVertexShaderID);
glBindAttribLocation(simpleProgramID, 0, "positionAttrib");
glBindAttribLocation(simpleProgramID, 1, "textureAttrib");
glLinkProgram(simpleProgramID);
fragmentShaderTextureID = glGetUniformLocation(simpleProgramID, "tex");
// Create Vertex Array Buffer for rendering texture on screen
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
float v[] = {-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
0.0f, 0.0f,
width, 0.0f,
width, height,
0.0f, height
};
glGenBuffers(1, &bufID);
glBindBuffer(GL_ARRAY_BUFFER, bufID);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4+sizeof(float)*2*4, v, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(float)*3*4));
glClearColor(0.f,0.f,1.f,1.f);
glutMainLoop();
}
一样。我收到运行时错误,而不是编译错误。
以下是代码:
var controllerElement = angular.element('[ng-controller="' + controllerName + '"]');
var controller = controllerElement.controller();