我在玩新的 OptiX-7 版本。为了显示启动结果(从 raygen 编写的简单单色),我创建了一个 OpenGL 纹理,对其进行映射并通过 cuGraphicsSubResourceGetMappedArray 获取映射数组,最后创建一个以该数组为背景的 CUDA 表面。然而,从 OptiX 内核写入表面既不会改变(显示的)纹理,也不会产生错误,而几乎相同的常规 CUDA 内核具有明显的效果。
CUDA 代码:
__global__ void test_kernel(::CUsurfObject surface) {
const uint2 imageIndex{
threadIdx.x + blockDim.x * blockIdx.x,
threadIdx.y + blockDim.y * blockIdx.y
};
if(imageIndex.x < 800 && imageIndex.y < 100)
::surf2Dwrite(::make_float4(1.f, 0.f, 1.f, 1.f), surface,
imageIndex.x * sizeof(float4), imageIndex.y);
}
OptiX 内核:
struct Params {
::CUsurfObject image;
};
extern "C" {
__constant__ Params params;
}
extern "C" __global__ void __raygen__solid_color() {
const uint3 launchIndex = ::optixGetLaunchIndex();
const auto imageIndex = ::make_uint2(launchIndex.x, launchIndex.y);
::surf2Dwrite(::make_float4(1.f, 0.f, 1.f, 1.f), params.image,
imageIndex.x * sizeof(float4), imageIndex.y);
}
表面句柄通过启动参数传递:
cuMemAlloc(&devParamBuf, sizeof(Params));
cuMemcpyHtoD(devParamBuf, &hostParamBuf);
...
optixLaunch(pipeline, stream, devParamBuf, sizeof(Params), &sbt, 800, 600, 1);
内核本身执行得很好。OptiX 示例包含一个纹理显示示例,并简单地使用 cudaTextureObject_t。但是,它们也使用普通缓冲区和 PBO 来显示渲染图像。是否根本不可能直接写入 CUDA 表面?
编辑:澄清表面是如何创建的:采用现有的 OpenGL 纹理,我注册并映射它
GLuint texture{};
glGenTextures(...);
...
cuGraphicsGLRegisterImage(&resource, texture, GL_TEXTURE_2D, CU_GRAPHICS_REGISTER_FLAGS_SURFACE_LDST);
cuGraphicsMapResources(1u, &resource, stream);
CUarray surfaceArray{};
cuGraphicsSubResourceGetMappedArray(&surfaceArray, resource, 0u, 0u);
CUsurfObject surface{};
CUDA_RESOURCE_DESC surfDesc{};
surfDesc.resType = CU_RESOURCE_TYPE_ARRAY;
surfDesc.res.array.hArray = surfaceArray;
cuSurfObjectCreate(&surface, &surfDesc);
为简洁起见,所有调用都包含错误检查。