使用 CUDA-OpenGL 互操作时,NPOT 纹理会导致渲染效果不佳
When using CUDA-OpenGL interop,NPOT texture results in bad rendering
这是代码,只是暂时尝试渲染渐变。
我想要最终完成的是使用 CUDA 渲染光线追踪场景,然后将其显示在屏幕上,并能够四处移动。
我 运行 遇到的主要问题是让我的计算图像正确显示,因为现在我正在用渐变测试它,当我的屏幕不是两个正方形。
#define width 1024
#define height 256
struct cudaGraphicsResource* screen;
uchar4* rendered;
GLFWwindow* window;
GLuint image;
__global__ void computeFrame(uchar4* rendered){
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
if (x > width || y > height) return;
int index = y * height + x;
rendered[index] = make_uchar4(y/(height*1.0f)*255, 0, 0, 255);
}
void createTexture(){
glGenTextures(1, &image);
glBindTexture(GL_TEXTURE_2D, image);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
}
int renderFrame() {
cudaDeviceSynchronize();
cudaGraphicsMapResources(1, &screen, 0);
cudaArray* dstArray;
cudaGraphicsSubResourceGetMappedArray(&dstArray, screen, 0, 0);
dim3 block(16, 16);
dim3 grid((width + block.x - 1) / block.x, (height + block.y - 1) / block.y);
computeFrame << <grid, block >> > (rendered);
cudaMemcpyToArray(dstArray,0,0, rendered, width * height * sizeof(uchar4),
cudaMemcpyDeviceToDevice);
cudaDeviceSynchronize();
cudaGraphicsUnmapResources(1, &screen, 0);
return 0;
}
void displayFrame() {
static int frno = 0;
frno++;
if (frno > 60) {
frno = 0;
printf("60frames passed\n");
}
renderFrame();
glBindTexture(GL_TEXTURE_2D, image);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-width,width, -height, height, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0, width, height);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-width, -height, 0.5);
glTexCoord2f(1, 0.0); glVertex3f(width, -height, 0.5);
glTexCoord2f(1, 1); glVertex3f(width, height, 0.5);
glTexCoord2f(0.0, 1); glVertex3f(-width, height, 0.5);
glEnd();
glDisable(GL_TEXTURE_2D);
glfwSwapBuffers(window);
}
int main(int argc, char** argv){
glfwInit();
glewInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(width,height, "Rotaru Leonard Claudiu", NULL, NULL);
glfwMakeContextCurrent(window);
cudaSetDevice(0);
createTexture();
cudaGraphicsGLRegisterImage(&screen, image, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsNone);
cudaMalloc(&rendered, width * height * sizeof(uchar4));
while (true) {
displayFrame();
}
glfwTerminate();
}
这里是运行宽度和高度1024的结果:
width 1024 height 1024
这是 运行 宽度 1024 和高度 512 的结果:
width 1024 height 512
以后请提供完整的代码。剥离包含 headers.
时没有帮助
根据我的测试,你至少有几个问题。
在您的一个屏幕截图中,您可以看到编译器告诉您 cudaMemcpyToArray
是 deprecated。此外,无论如何在此设置中使用它都是不正确的。所以我们将用 cudaMemcpy2DToArray
替换它。而不是这个:
cudaMemcpyToArray(dstArray,0,0, rendered, width * height * sizeof(uchar4),
cudaMemcpyDeviceToDevice);
使用这个:
cudaMemcpy2DToArray(dstArray,0,0, rendered, width * sizeof(uchar4), width * sizeof(uchar4), height,
cudaMemcpyDeviceToDevice);
您内核中的边界检查不正确:
if (x > width || y > height) return;
应该是:
if (x >= width || y >= height) return;
这是标准的计算机科学 off-by-one 错误。
您对 index
的内核计算不正确:
int index = y * height + x;
应该是:
int index = y * width + x;
y
是您的高度变量,我们必须将它乘以每条线的宽度以获得合适的一维索引。
通过这些更改,您的代码对我来说似乎 运行 正确,如您所显示的高度为 256。
这是代码,只是暂时尝试渲染渐变。 我想要最终完成的是使用 CUDA 渲染光线追踪场景,然后将其显示在屏幕上,并能够四处移动。 我 运行 遇到的主要问题是让我的计算图像正确显示,因为现在我正在用渐变测试它,当我的屏幕不是两个正方形。
#define width 1024
#define height 256
struct cudaGraphicsResource* screen;
uchar4* rendered;
GLFWwindow* window;
GLuint image;
__global__ void computeFrame(uchar4* rendered){
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
if (x > width || y > height) return;
int index = y * height + x;
rendered[index] = make_uchar4(y/(height*1.0f)*255, 0, 0, 255);
}
void createTexture(){
glGenTextures(1, &image);
glBindTexture(GL_TEXTURE_2D, image);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
}
int renderFrame() {
cudaDeviceSynchronize();
cudaGraphicsMapResources(1, &screen, 0);
cudaArray* dstArray;
cudaGraphicsSubResourceGetMappedArray(&dstArray, screen, 0, 0);
dim3 block(16, 16);
dim3 grid((width + block.x - 1) / block.x, (height + block.y - 1) / block.y);
computeFrame << <grid, block >> > (rendered);
cudaMemcpyToArray(dstArray,0,0, rendered, width * height * sizeof(uchar4),
cudaMemcpyDeviceToDevice);
cudaDeviceSynchronize();
cudaGraphicsUnmapResources(1, &screen, 0);
return 0;
}
void displayFrame() {
static int frno = 0;
frno++;
if (frno > 60) {
frno = 0;
printf("60frames passed\n");
}
renderFrame();
glBindTexture(GL_TEXTURE_2D, image);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-width,width, -height, height, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0, width, height);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-width, -height, 0.5);
glTexCoord2f(1, 0.0); glVertex3f(width, -height, 0.5);
glTexCoord2f(1, 1); glVertex3f(width, height, 0.5);
glTexCoord2f(0.0, 1); glVertex3f(-width, height, 0.5);
glEnd();
glDisable(GL_TEXTURE_2D);
glfwSwapBuffers(window);
}
int main(int argc, char** argv){
glfwInit();
glewInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(width,height, "Rotaru Leonard Claudiu", NULL, NULL);
glfwMakeContextCurrent(window);
cudaSetDevice(0);
createTexture();
cudaGraphicsGLRegisterImage(&screen, image, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsNone);
cudaMalloc(&rendered, width * height * sizeof(uchar4));
while (true) {
displayFrame();
}
glfwTerminate();
}
这里是运行宽度和高度1024的结果: width 1024 height 1024 这是 运行 宽度 1024 和高度 512 的结果: width 1024 height 512
以后请提供完整的代码。剥离包含 headers.
时没有帮助根据我的测试,你至少有几个问题。
在您的一个屏幕截图中,您可以看到编译器告诉您
cudaMemcpyToArray
是 deprecated。此外,无论如何在此设置中使用它都是不正确的。所以我们将用cudaMemcpy2DToArray
替换它。而不是这个:cudaMemcpyToArray(dstArray,0,0, rendered, width * height * sizeof(uchar4), cudaMemcpyDeviceToDevice);
使用这个:
cudaMemcpy2DToArray(dstArray,0,0, rendered, width * sizeof(uchar4), width * sizeof(uchar4), height, cudaMemcpyDeviceToDevice);
您内核中的边界检查不正确:
if (x > width || y > height) return;
应该是:
if (x >= width || y >= height) return;
这是标准的计算机科学 off-by-one 错误。
您对
index
的内核计算不正确:int index = y * height + x;
应该是:
int index = y * width + x;
y
是您的高度变量,我们必须将它乘以每条线的宽度以获得合适的一维索引。
通过这些更改,您的代码对我来说似乎 运行 正确,如您所显示的高度为 256。