私が達成しようとしていること:
OpenCL でいくつかのものをレンダリングし、それを OpenGL フレームバッファーに書き込もうとしています (Renderbuffers などを介して取得できる唯一のフレームバッファーであるため、使用できる他のものを喜んで受け入れます-あなたglsl シェーダーを使用するように指示しても役に立ちません)
問題:
タイトルにあるように、OpenCL 関数clBuildProgramがエラー -11 (CL_ BUILD_ PROGRAM_ FAILURE) で失敗します。これは問題にはなりませんが、CL コンパイラからのログは空です。ログ コードを再確認しましたが、問題ないはずです。あなたが自分自身を見ることができるように、私はそれを下に投稿しました.
私が修正しようとしたこと:
- もちろん、グーグル
- Khronos Groups のドキュメントを読む
- デバイスが「cl_khr_gl_sharing」拡張機能をサポートしているかどうかを確認しています (これは から返された文字列に含まれています
clGetDeviceInfo(device_id, CL_DEVICE_EXTENSIONS, retSize, extensions, &retSize);
) - シェーダー/カーネルの変更:
- ロギングコードが実際に機能するかどうかを確認するために、いくつかの意図的なエラーを作成しました(機能しています)
- そして、シェーダー/カーネルを縮小して、シェーダー内のいくつかのものが正常に機能しないかどうかを確認します (私が読んだように、いくつかの欠落が cl のコンパイラーをクラッシュさせる可能性があることを読んだ)
私が見つけたもの:
私が試した最後のポイントから、私は気づいた、write_imageui
とread_imageui
opencl 関数は、コンパイラが私のコードをコンパイルするのに失敗します (これが、「cl_khr_gl_sharing」拡張子をチェックした理由です)
さらに:
私のオペレーティングシステムはWindows 10で、使用しているCコンパイラはGCCです(ホストプログラムは正常にコンパイルされるため、それがどのように役立つかわかりませんが、それでもなおです)
いくつかのコード:
シェーダー/カーネル (問題を再現するために可能な限り縮小されています。あなたにもお願いします。呼び出しの最後の 2 行は、opencl コンパイラーが機能しない原因だと思います。他のものはそこにあります。これは、実際に何かを処理できるシェーダーです。
#define ScreenWidth 1000
#define ScreenHight 1000
const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;
__kernel void rainbow(__read_write image2d_t asd) {
int i = get_global_id(0);
unsigned int x = i%ScreenWidth;
unsigned int y = i/ScreenHight;
uint4 pixel;
pixel = read_imageui(asd, sampler, (int2)(x, y));
write_imageui(asd, (int2)(x, y), pixel);
}
必要なすべての初期化処理を実行する縮小された呼び出しコード (C) (注: ログ バッファは動的に変更可能です):
cl_program program = clCreateProgramWithSource(contextZ, 1, (const char **)&source_str, (const size_t *)&source_size, &ret);
size_t retSize = 0;
clGetDeviceInfo(device_id, CL_DEVICE_EXTENSIONS, 0, NULL, &retSize);
char extensions[retSize];
clGetDeviceInfo(device_id, CL_DEVICE_EXTENSIONS, retSize, extensions, &retSize);
printf("%s\n", extensions);
// Build the program
ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
if (ret == CL_BUILD_PROGRAM_FAILURE) {
l_logError("Could not build Kernel!");
// Determine the size of the log
size_t log_size;
printf(" reta: %i\n", clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size));
// Allocate memory for the log
char *log = (char *) malloc(log_size);
// Get the log
printf(" retb: %i\n", clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, log_size, log, NULL));
// Print the log
printf(" ret-val: %i\n", ret);
printf("%s\n", log);
}
出力に興味があるかもしれません (最後の 2 行はカーネルがビルドされていないことが原因です。ただし、プログラムはソースから作成できます - コードを見てください):
E: Could not build Kernel!
reta: 0
retb: 0
ret-val: -11
E: Could not create Kernel!
kernel error: -45
他の誰かが同様の問題を抱えていましたか?私はそれについて何をすべきですか?cl Kernel/Shader のヘッダーが含まれている可能性がありますが、これを含める必要がありますか? 私の clBuildProgram 呼び出しが間違っている可能性がありますか? (誰かがデバイスを渡さなかったと読んだので、コードに何か他のものが欠けている可能性があります)
詳細が必要な場合は、お知らせください。提供できるようにします (他に必要なものは今のところ思いつきません)。
お時間をいただきありがとうございます。
編集:
仕様によると、デバイスはCL_ DEVICE_ IMAGE_ SUPPORT拡張機能をサポートする必要があります。
これを使用して確認しました:
cl_bool image_support = CL_FALSE;
clGetDeviceInfo(device_id, CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool), &image_support, NULL);
printf("image_support: %i\n", image_support);
どの出力:
image_support: 1
別名。CL_TRUE
編集 2:
カーネルで OpenCL 拡張機能を有効にする必要があることが判明しました: https://www.khronos.org/registry/OpenCL/sdk/2.2/docs/man/html/EXTENSION.htmlの最初の行に
追加#pragma OPENCL EXTENSION all : enable
カーネル/シェーダーは同じ問題を引き起こします
編集 3:
カーネル イメージ パラメーターから __read_write フラグを削除するか、それを別のもの (__read_only など) に置き換えると、clBuildProgram が返されない (または非常に長い時間のように返される) ため、OpenCL コンパイラがクラッシュするか無限にループします。