0 Replies Latest reply on Dec 29, 2010 10:33 AM by dstokac

    Bug related to the CALcontext?

    dstokac

      I found a problem when using multiple contests in the same program. The source code of the program which demonstrates and describes the problem is found as an attachment. In short, when I use more then one context, tests in the program fail. Since the program is simple, and I don't see in the source code any obvious reason for the failure, I posted it in this forum to check if I overlooked something, or there is a bug in the amd provided libraries.

      #include <iostream> #include <iomanip> #include <vector> #include <stdlib.h> #include <assert.h> #include <math.h> #include <sstream> #include "cal.h" #include "calcl.h" using namespace std; void calAssert(CALresult cr, std::string s) { if (cr!=CAL_RESULT_OK) { std::cerr<<"Error in "<<s<<" : "<<calGetErrorString()<<std::endl; exit(1); } } void calAssertcl(CALresult cr, std::string s) { if (cr!=CAL_RESULT_OK) { std::cerr<<"Error in "<<s<<" : "<<calclGetErrorString()<<std::endl; exit(1); } } ////////////////////////////////////////////////////////////////////////// //! multicontext_bug_v1.0.cpp // // Compilation: // g++ multicontext_bug_v1.0.cpp -I $ATISTREAMSDKROOT/include -L $ATISTREAMSDKROOT/lib/x86/ -laticalrt -laticalcl // Description: (use TAB 2) // This program is an attempt to explore possible bug/undocumented CAL feature. // It consists of three kernels: kernelIL_flush initializes the global buffer with values A*indx+B, // while kernelIL_read copies global buffer into a texture buffer. In the end the content of the // texture buffer is compared to A*indx+B value. If the two values are not the same, the test fails. // The same thing is also done in the reverse order. In the first step texture buffer is initialized, in the // second copied into the global buffer (kernelIL_write) and in the third step it is checked that the content of the // global buffer corresponds to the initialization function. // The test in this program normally fails when the program is started as // a.out -r (or -l) > output.txt. In order to pass the test it is necessary to start the program with -d argument, // which turns on destruction of the old context before creating a new one. As a consequence, only one // context should exist at a time if the test is to be passed. // Tests were performed on OpenSUSE11.3 with HD4770, ati-driver-8.801, ati-stream-2.3. ////////////////////////////////////////////////////////////////////////// //copy global buffer into a texture buffer std::string kernelIL_read = "il_ps_2_0\n" "dcl_input_position_interp(linear_noperspective) vWinCoord0.xy__\n" "dcl_cb cb0[1]\n" "dcl_output_generic o0\n" "flr r0, vWinCoord0\n" "ftou r10,r0\n" "ftou r11, cb0[0]\n" "umul r0.x, r10.y, r11.y\n" "iadd r0.y, r0.x, r10.x\n" "iadd r12.x, r11.x, r0.y\n" "mov o0, g[r12.x]\n" // "mov r0,g[0]\n" // "utof r0,r12\n" // "mov o0, r0.x\n" "end\n"; //copy texture buffer into the global buffer std::string kernelIL_write = "il_ps_2_0\n" "dcl_input_position_interp(linear_noperspective) vWinCoord0.xy__\n" "dcl_resource_id(0)_type(2d,unnorm)_fmtx(float)_fmty(float)_fmtz(float)_fmtw(float)\n" "dcl_cb cb0[1]\n" "flr r0, vWinCoord0\n" "ftou r10,r0\n" "ftou r11, cb0[0]\n" "umul r0.x, r10.y, r11.y\n" "iadd r0.y, r0.x, r10.x\n" "iadd r12.x, r11.x, r0.y\n" "sample_resource(0)_sampler(0) g[r12.x], vWinCoord0.xy\n" "end\n"; //initialize global buffer with A*indx+B std::string kernelIL_flush = "il_cs_2_0\n" "dcl_num_thread_per_group 1\n" "dcl_cb cb0[1]\n" //{A, B} "ftou r10, cb0[0]\n" "iadd r10.y, r10.x, vAbsTid0.x\n" "utof r0.x, vAbsTid0.x\n" "dcl_literal l0, 4.0f,0,0,0\n" "dcl_literal l1, 0.0f,1.0f,2.0f,3.0f\n" "mul r0.y, r0.x, l0.x\n" "add r1, r0.y, l1\n" "mul r2, r1, cb0[0].x\n" "add r2, r2, cb0[0].y\n" "mov g[vAbsTid0.x], r2\n" // "mov g[vAbsTid0.x], r1\n" // "mov g[vAbsTid0.x], l1.w\n" "end\n"; //////////////////////////////////////////////////////////////////// //! Main function /////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { int width=3; int height=7; float f_A=1; float f_B=11; int repeat_No=400; int repeat_all_No=5; bool test_passed=1; int rem_loc=0; bool cacheable=0; bool nullify=0; bool destroy_ctx=0; srand48(time(NULL)); if (argc<2) { cerr<<"Usage: a.out [options] "<<endl; cerr<<" -l - local buffer"<<endl; cerr<<" -r - remote buffer"<<endl; cerr<<" -c - cacheable buffer"<<endl; cerr<<" -n - nullify texture buffer before writing into it"<<endl; cerr<<" -d - destroy current context before creating a new one"<<endl; exit(1); } else { for(int i_arg=1; i_arg<=argc; i_arg++) { stringstream ss; ss<<argv[i_arg]; if (ss.str()=="-l") rem_loc=1; else if (ss.str()=="-r") rem_loc=0; else if (ss.str()=="-c") cacheable=1; else if (ss.str()=="-n") nullify=1; else if (ss.str()=="-d") destroy_ctx=1; } } calInit(); vector<CALcontext> ctx(repeat_all_No, 0); //-------------------------------------------------------------- // Querying and opening device //-------------------------------------------------------------- // Finding number of devices CALuint numDevices = 0; calDeviceGetCount(&numDevices); assert(numDevices>0); // Querying device info CALdeviceinfo info; calDeviceGetInfo(&info, 0); // Opening device CALdevice device = 0; calDeviceOpen(&device, 0); //----------------------------------------------------------------- // Compiling Device Kernels //----------------------------------------------------------------- CALlanguage lang = CAL_LANGUAGE_IL; std::string kernelType = "IL"; CALobject obj_read = NULL; CALimage image_read = NULL; std::string kernel_read = kernelIL_read; calAssertcl(calclCompile(&obj_read, lang, kernel_read.c_str(), info.target),"calclCompile(&obj_read, lang, kernel_read.c_str(), info.target);"); calAssertcl(calclLink(&image_read, &obj_read, 1),"calclLink(&image_read, &obj_read, 1)"); CALobject obj_write = NULL; CALimage image_write = NULL; std::string kernel_write = kernelIL_write; calAssertcl(calclCompile(&obj_write, lang, kernel_write.c_str(), info.target),"calclCompile(&obj_write, lang, kernel_write.c_str(), info.target);"); calAssertcl(calclLink(&image_write, &obj_write, 1),"calclLink(&image_write, &obj_write, 1)"); CALobject obj_flush = NULL; CALimage image_flush = NULL; std::string kernel_flush = kernelIL_flush; calAssertcl(calclCompile(&obj_flush, lang, kernel_flush.c_str(), info.target),"calclCompile(&obj_flush, lang, kernel_flush.c_str(), info.target);"); calAssertcl(calclLink(&image_flush, &obj_flush, 1),"calclLink(&image_flush, &obj_flush, 1)"); //------------------------------------------------------------------------- // Allocating and initializing resources //------------------------------------------------------------------------- CALresource globRes = 0; CALresource textureRes = 0; CALresource paramRes_1 =0; CALresource paramRes_2 =0; CALuint flag=(cacheable ? CAL_RESALLOC_CACHEABLE : 0); if (rem_loc==0) calAssert(calResAllocRemote2D(&textureRes, &device, 1, width, height, CAL_FORMAT_FLOAT32_4, flag),"2"); if (rem_loc==1) calAssert(calResAllocLocal2D(&textureRes, device, width, height, CAL_FORMAT_FLOAT32_4, flag),"2"); calAssert(calResAllocLocal1D(&globRes, device, height*width, CAL_FORMAT_FLOAT32_4, CAL_RESALLOC_GLOBAL_BUFFER),"1"); calAssert(calResAllocLocal1D(&paramRes_1, device, 1, CAL_FORMAT_FLOAT32_4, 0),"3"); calAssert(calResAllocLocal1D(&paramRes_2, device, 1, CAL_FORMAT_FLOAT32_4, 0),"3"); for(int rep_all=0; rep_all<repeat_all_No; rep_all++) { ctx[rep_all] = 0; calCtxCreate(&ctx[rep_all], device); float* fdata_glob=NULL; float* fdata_param=NULL; float* fdata_texture=NULL; CALuint pitch_glob=0; CALuint pitch_param=0; CALuint pitch_texture=0; CALmem globMem=0; CALmem paramMem_1=0; CALmem paramMem_2=0; CALmem textureMem=0; //Get memory handles for various resources calAssert(calCtxGetMem(&globMem, ctx[rep_all], globRes),"4"); calAssert(calCtxGetMem(&paramMem_1, ctx[rep_all], paramRes_1),"5"); calAssert(calCtxGetMem(&paramMem_2, ctx[rep_all], paramRes_2),"5"); calAssert(calCtxGetMem(&textureMem, ctx[rep_all], textureRes),"6"); //----------------------------------------------------------------- // Loading module and setting domain //----------------------------------------------------------------- CALmodule module_read=0; calAssert(calModuleLoad(&module_read, ctx[rep_all], image_read),"moduleload"); CALfunc func_read=0; CALname globName_read=0, paramName_read=0; CALname textureName_read=0; calAssert(calModuleGetEntry(&func_read, ctx[rep_all], module_read, "main"),"func_read"); calAssert(calModuleGetName(&globName_read, ctx[rep_all], module_read, "g[]"), "g1"); calAssert(calModuleGetName(&paramName_read, ctx[rep_all], module_read, "cb0"),"p1"); calAssert(calModuleGetName(&textureName_read, ctx[rep_all], module_read, "o0"),"t1"); calAssert(calCtxSetMem(ctx[rep_all], globName_read, globMem),"calCtxSetMem(ctx[rep_all], globName_read, globMem)"); calAssert(calCtxSetMem(ctx[rep_all], textureName_read, textureMem),"calCtxSetMem(ctx[rep_all], textureName_read, textureMem)"); CALmodule module_write=0; calAssert(calModuleLoad(&module_write, ctx[rep_all], image_write),"moduleload"); CALfunc func_write=0; CALname globName_write=0, paramName_write=0; CALname textureName_write=0; calAssert(calModuleGetEntry(&func_write, ctx[rep_all], module_write, "main"),"func_write"); calAssert(calModuleGetName(&globName_write, ctx[rep_all], module_write, "g[]"), "g1"); calAssert(calModuleGetName(&paramName_write, ctx[rep_all], module_write, "cb0"),"p1"); calAssert(calModuleGetName(&textureName_write, ctx[rep_all], module_write, "i0"),"wt1"); calAssert(calCtxSetMem(ctx[rep_all], globName_write, globMem),"calCtxSetMem(ctx[rep_all], globName_write, globMem)"); calAssert(calCtxSetMem(ctx[rep_all], textureName_write, textureMem),"calCtxSetMem(ctx[rep_all], textureName_write, textureMem)"); CALmodule module_flush=0; calAssert(calModuleLoad(&module_flush, ctx[rep_all], image_flush),"moduleload"); CALfunc func_flush=0; CALname globName_flush=0, paramName_flush=0; calAssert(calModuleGetEntry(&func_flush, ctx[rep_all], module_flush, "main"),"func_flush"); calAssert(calModuleGetName(&globName_flush, ctx[rep_all], module_flush, "g[]"), "g2"); calAssert(calModuleGetName(&paramName_flush, ctx[rep_all], module_flush, "cb0"),"p2"); calAssert(calCtxSetMem(ctx[rep_all], globName_flush, globMem),"calCtxSetMem(ctx[rep_all], globName_flush, globMem)"); for(int i_rep=0; i_rep<repeat_No; i_rep++) { float xA, xB,diff; xA=int(drand48()*5); xB=int(drand48()*100); CALmem &paramMem_flush=paramMem_1; CALmem &paramRes_flush=paramRes_1; CALmem &paramMem_read=paramMem_1; CALmem &paramRes_read=paramRes_1; CALmem &paramMem_write=paramMem_1; CALmem &paramRes_write=paramRes_1; if (nullify) { //nullify texture field calAssert(calResMap((CALvoid**)&fdata_texture, &pitch_texture, textureRes, 0),"calResMap((CALvoid**)&fdata_texture,"); for(int i=0; i<height; i++) for(int j=0; j<4*width; j++) fdata_texture[i*4*pitch_texture+j]=100; calAssert(calResUnmap(textureRes),"calResUnmap(textureRes)"); } //flush-kernel calAssert(calCtxSetMem(ctx[rep_all], paramName_flush, paramMem_flush),"calCtxSetMem(ctx[rep_all], paramName_flush, paramMem_flush)"); calAssert(calResMap((CALvoid**)&fdata_param, &pitch_param, paramRes_flush, 0),"calResMap((CALvoid**)&fdata_param_flush"); fdata_param[0]=xA; //A*indx+B fdata_param[1]=xB; // fdata_param[2]=0.0f; fdata_param[3]=0.0f; calAssert(calResUnmap(paramRes_flush),"calResUnmap(paramRes)_flush"); CALevent e_flush=0; CALdomain3D gridBlock_flush = {1, 1, 1}; CALdomain3D gridSize_flush = {width*height, 1, 1}; CALprogramGrid programGrid_flush = { func_flush, gridBlock_flush, gridSize_flush, 0}; calAssert(calCtxRunProgramGrid(&e_flush, ctx[rep_all], &programGrid_flush),"calCtxRunProgramGrid(&event_flush..."); while (calCtxIsEventDone(ctx[rep_all], e_flush) == CAL_RESULT_PENDING); //read-kernel calAssert(calCtxSetMem(ctx[rep_all], paramName_read, paramMem_read),"calCtxSetMem(ctx[rep_all], paramName_read, paramMem_read)"); calAssert(calResMap((CALvoid**)&fdata_param, &pitch_param, paramRes_read, 0),"calResMap((CALvoid**)&fdata_param_read"); fdata_param[0]=0.0; //offset fdata_param[1]=width; //width of the texture field(domain) fdata_param[2]=0.0f; fdata_param[3]=0.0f; calAssert(calResUnmap(paramRes_read),"calResUnmap(paramRes)_read"); CALevent e_read=0; CALdomain domain = {0, 0, width, height}; calAssert(calCtxRunProgram(&e_read, ctx[rep_all], func_read, &domain),"calCtxRunProgram(&e_read,"); while (calCtxIsEventDone(ctx[rep_all], e_read) == CAL_RESULT_PENDING); //check content of the texture field diff=0; calAssert(calResMap((CALvoid**)&fdata_texture, &pitch_texture, textureRes, 0),"calResMap((CALvoid**)&fdata_texture, "); for(int i=0; i<height; i++) for(int j=0; j<4*width; j++) { diff+=fabs(fdata_texture[i*4*pitch_texture+j]-(xB+xA*(i*4*width+j))); // diff+=fabs(fdata_texture[i*4*pitch_texture+j]-((i*4*width+j)/4)); // diff+=fabs(fdata_texture[i*4*pitch_texture+j]-((i*4*width+j))); } if (diff) { test_passed=0; cout<<"-------------------------------------"<<endl; cout<<"i_rep:"<<i_rep<<endl; cout.precision(3); cout<<"diff: "<<diff<<endl; cout<<"A: "<<setw(20)<<xA<<" B:"<<setw(20)<<xB<<endl; cout<<"texture:"<<endl; for(int i=0; i<height; i++) { for(int j=0; j<4*width; j++) cout<<setw(11)<<fdata_texture[i*4*pitch_texture+j]; cout<<endl; } cout<<"should be:"<<endl; for(int i=0; i<height; i++) { for(int j=0; j<4*width; j++) cout<<setw(11)<<xB+xA*(i*4*width+j); // cout<<setw(11)<<(i*4*width+j); cout<<endl; } cout<<"glob_buffer:"<<endl; calAssert(calResMap((CALvoid**)&fdata_glob, &pitch_glob, globRes, 0),"calResMap((CALvoid**)&fdata_glob"); for(int i=0; i<4*height*width; i++) cout<<setw(11)<<fdata_glob[i]; cout<<endl; calAssert(calResUnmap(globRes),"calResUnmap(globRes)"); cerr<<"TEST failed"<<endl; sleep(1); exit(1); } calAssert(calResUnmap(textureRes),"calResUnmap(textureRes)"); xA=int(drand48()*5); xB=int(drand48()*100); //init texture field calAssert(calResMap((CALvoid**)&fdata_texture, &pitch_texture, textureRes, 0),"calResMap((CALvoid**)&fdata_texture"); for(int i=0; i<height; i++) for(int j=0; j<4*width; j++) fdata_texture[i*4*pitch_texture+j]=xB+xA*(i*4*width+j); calAssert(calResUnmap(textureRes),"calResUnmap(textureRes)"); //write-kernel calAssert(calCtxSetMem(ctx[rep_all], paramName_write, paramMem_write),"calCtxSetMem(ctx[rep_all], paramName_write, paramMem_write)"); calAssert(calResMap((CALvoid**)&fdata_param, &pitch_param, paramRes_write, 0),"calResMap((CALvoid**)&fdata_param_write"); fdata_param[0]=0.0; //offset fdata_param[1]=width; //width of the texture field(domain) fdata_param[2]=0.0f; fdata_param[3]=0.0f; calAssert(calResUnmap(paramRes_write),"calResUnmap(paramRes)_write"); CALevent e_write=0; CALdomain domain_write = {0, 0, width, height}; calAssert(calCtxRunProgram(&e_write, ctx[rep_all], func_write, &domain_write),"calCtxRunProgram(&e_write"); while (calCtxIsEventDone(ctx[rep_all], e_write) == CAL_RESULT_PENDING); //check content of the texture field diff=0; calAssert(calResMap((CALvoid**)&fdata_glob, &pitch_glob, globRes, 0),"calResMap((CALvoid**)&fdata_glob"); for(int i=0; i<height*4*width; i++) diff+=fabs(fdata_glob[i]-(xB+xA*i)); calAssert(calResUnmap(globRes),"calResUnmap(globRes)"); if (diff) { test_passed=0; cout.precision(3); cout<<"glob_buffer:"<<endl; calAssert(calResMap((CALvoid**)&fdata_glob, &pitch_glob, globRes, 0),"calResMap((CALvoid**)&fdata_glob, "); for(int i=0; i<4*height*width; i++) cout<<setw(11)<<fdata_glob[i]; cout<<endl; calAssert(calResUnmap(globRes),"calResUnmap(globRes)"); cout<<"should be:"<<endl; for(int i=0; i<4*height*width; i++) cout<<setw(11)<<xB+xA*i; cout<<endl; cout<<"texture:"<<endl; calAssert(calResMap((CALvoid**)&fdata_texture, &pitch_texture, textureRes, 0),"calResMap((CALvoid**)&fdata_texture"); for(int i=0; i<height; i++) { for(int j=0; j<4*width; j++) cout<<setw(11)<<fdata_texture[i*4*pitch_texture+j]; cout<<endl; } calAssert(calResUnmap(textureRes),"calResUnmap(textureRes)"); } } //-----------------------------------------------------------------// //Cleaning up ctx related objects //----------------------------------------------------------------- // Unloading the module calAssert(calModuleUnload(ctx[rep_all], module_read),"calModuleUnload(ctx[rep_all], module_read)"); calAssert(calModuleUnload(ctx[rep_all], module_write),"calModuleUnload(ctx[rep_all], module_write)"); calAssert(calModuleUnload(ctx[rep_all], module_flush),"calModuleUnload(ctx[rep_all], module_flush)"); // Realeasing resource from context calAssert(calCtxReleaseMem(ctx[rep_all], globMem),"calCtxReleaseMem(ctx[rep_all], globMem)"); calAssert(calCtxReleaseMem(ctx[rep_all], paramMem_1),"calCtxReleaseMem(ctx[rep_all], paramMem_1)"); calAssert(calCtxReleaseMem(ctx[rep_all], paramMem_2),"calCtxReleaseMem(ctx[rep_all], paramMem_2)"); calAssert(calCtxReleaseMem(ctx[rep_all], textureMem),"calCtxReleaseMem(ctx[rep_all], textureMem)"); if (ctx[rep_all] && destroy_ctx) { calAssert(calCtxDestroy(ctx[rep_all]),"calCtxDestroy(ctx[rep_all])"); ctx[rep_all]=0; } } // Freeing commpiled kernel binary calAssert(calclFreeImage(image_read),"calclFreeImage(image_read)"); calAssert(calclFreeObject(obj_read),"calclFreeObject(obj_read)"); calAssert(calclFreeImage(image_write),"calclFreeImage(image_write)"); calAssert(calclFreeObject(obj_write),"calclFreeObject(obj_write)"); calAssert(calclFreeImage(image_flush),"calclFreeImage(image_flush)"); calAssert(calclFreeObject(obj_flush),"calclFreeObject(obj_flush)"); // Deallocating resources calAssert(calResFree(globRes),"calResFree(globRes)"); calAssert(calResFree(paramRes_1),"calResFree(paramRes_1)"); calAssert(calResFree(paramRes_2),"calResFree(paramRes_2)"); calAssert(calResFree(textureRes),"calResFree(textureRes)"); // Destroying context for(int i=0; i<ctx.size(); i++) if (ctx[i]) calAssert(calCtxDestroy(ctx[i]),"calCtxDestroy(ctx[i])"); // Closing device calAssert(calDeviceClose(device),"calDeviceClose(device)"); if (test_passed) { cerr<<"TEST passed"<<endl; } else { cerr<<"TEST failed"<<endl; } calAssert(calShutdown(),"calShutdown()"); return 0; }