Haskell と OpenCL でパストレーサーを作成していますが、image2d_t をカーネルに渡して出力を書き込む際に問題が発生しています。つまり、get_image_*
image2d_t で OpenCL の関数を呼び出すと、無意味な値 (通常は 0 または 2^24-1) が返され、何も行われwrite_imagef
ません。これは、GPU で実行している場合にのみ発生します。CPU は正常に実行されます。ホストで呼び出すclGetImageInfo
と、正しい値が返されます。OpenCL の Haskell バインディングはエラー コードを例外に変換するため、エラーのチェックを忘れることはありません。clinfo は私のバージョンを「OpenCL 1.2 AMD-APP (1084.2)」と報告します。OpenCL コンパイラで segfault やリンクの失敗を引き起こす複数のバグを経験 (および報告) したことに注意してください。これは、私のコードのバグではなく、その結果である可能性があります。
OpenCL を次のように初期化します (Haskell を知らない人にも比較的わかりやすいはずです)。
(platform:_) <- clGetPlatformIDs
(device:_) <- clGetDeviceIDs platform CL_DEVICE_TYPE_GPU
glContext <- glXGetCurrentContext
glDisplay <- glXGetCurrentDisplay
context <- clCreateContext [CL_GL_CONTEXT_KHR glContext, CL_GLX_DISPLAY_KHR glDisplay] [device] putStrLn
queue <- clCreateCommandQueue context device []
source <- readFile "pt.cl"
program <- clCreateProgramWithSource context source
clBuildProgram program [device] "-cl-strict-aliasing"
`catch` (λe -> case (e :: CLError) of
CL_BUILD_PROGRAM_FAILURE -> putStrLn "Building OpenCL program failed:"
>> clGetProgramBuildLog program device >>= putStrLn
>> throw e
_ -> return ())
kernel <- clCreateKernel program "sample"
pCorners <- mallocArray 4
buffer <- clCreateBuffer context [CL_MEM_READ_ONLY, CL_MEM_USE_HOST_PTR] (4*sizeOf (undefined :: V.Vec4F), castPtr pCorners)
clSetKernelArgSto kernel 1 buffer
tex@(TextureObject texid) <- head <$> (genObjectNames 1)
activeTexture $= TextureUnit 0
textureBinding Texture2D $= Just tex
textureFilter Texture2D $= ((Nearest, Nothing), Nearest)
textureWrapMode Texture2D S $= (Repeated, Clamp)
textureWrapMode Texture2D T $= (Repeated, Clamp)
texImage2D Nothing NoProxy 0 RGBA′ (TextureSize2D initialWidth initialHeight) 0 (PixelData RGBA UnsignedByte nullPtr)
image <- clCreateFromGLTexture2D context [CL_MEM_READ_WRITE] gl_TEXTURE_2D 0 texid
clSetKernelArgSto kernel 2 image
そして、これを (少し簡略化して) 呼び出して、カーネルを実行し、結果をレンダリングします。
clSetKernelArgSto kernel 0 position
pokeArray pCorners orientedCorners -- update the pCorners array
finish -- This is glFinish()
clEnqueueAcquireGLObjects queue [image] []
clEnqueueNDRangeKernel queue kernel [width, height] [] []
clEnqueueReleaseGLObjects queue [image] []
clFinish queue
drawElements TriangleFan 4 UnsignedInt offset0
swapBuffers
最後に、テスト カーネル:
__kernel void sample(float3 position, __constant float3 corner[4], image2d_t output) {
write_imagef(output, (int2)(get_global_id(0), get_global_id(1)), (float4)(0, 0.5f, 1, 1));
}
この出力は、GPU メモリのランダムな初期化されていない領域を表示するフルスクリーン クワッドです。フルスクリーンのシアンのクワッドにする必要があります。printf
関数の結果を表示するためにいくつかの s がありget_image_*
ましたが、それらが原因でプログラムがハングし始めました。