2016-08-19 68 views
0

後續這個問題Problems with OpenCL/OpenGL Texture interop/windows的OpenCL/OpenGL的紋理互操作:調整OpenGL紋理

我們:

  • 渲染到FBO,附帶作爲COLOR_ATTACHMENT0紋理,這是inTex
  • OpenCL中可分離downscaler,使用inTex,通過tempTex
01在一個三步過程中產生

現在出現了一個新問題,因爲這是一個編輯器實現。如果inTex的大小發生變化或者outTex的大小發生變化,則首先使用glTexImage2d調整OpenGL紋理的大小。然後釋放三個內核對象,最後使用clReleaseMemObj(XTex)發佈所有三種紋理的對象。最後一步簡單地使用與初始化時相同的代碼重新創建所有必需的對象,並繼續循環。

在使用clCreateFromGLTexture2D重新創建那些紋理的cl_mem對象時,我收到CL_OUT_OF_RESOURCES。相應地,縮減不再被執行,因爲設置紋理內核參數產生CL_INVALID_MEM_OBJECT

也許有些僞代碼有助於理解這個問題:

// OBJECTS // 
//////////// 
cl_kernel k_x, k_y, k_clear; 
cl_mem  textureObjects[3]; 
int   src_width, src_height, dst_width, dst_height; 
size_t  rngClr[3], offsClr[3], range_x[3], range_y[3]; 
float  clrCol[4] 

// MAIN ENTRY POINT // 
///////////////////// 
if ((fbo) && calculate()) 
{ 
    glFinish(); 

    if (CL_recreate) recreateCLstuff(); 

    CLmgr->acquireGLObjects(3, textureObjects); 
    CLmgr->callKernel(k_clear, rngClr, offsClr, "clear"); 
    CLmgr->setSimpleKernelArg(k_x, 3, 8, &convertXY, "horizontal::convert"); 
    CLmgr->setSimpleKernelArg(k_x, 4, 16, &offsets_X, "horizontal::offset"); 
    CLmgr->callKernel(k_x, range_x, "horizontal downsample"); 
    CLmgr->setSimpleKernelArg(k_y, 3, 8, &convertXY.m128_f32[ 2 ], "vertical::convert"); 
    CLmgr->setSimpleKernelArg(k_y, 4, 16, &offsets_Y, "vertical::offset"); 
    CLmgr->callKernel(k_y, range_y, "vertical downsample"); 
    CLmgr->releaseGLObjects(3, textureObjects); 
    clFinish(); 
} 

bool calculate() 
{ 
    // check if a resize of the "inTex" happened or a resize of 
    // "outTex" or "tempTex" is necessary 
    int srcw, srch, dstw, dsth; 
    // acquire above values 
    if ((srcw != src_width) || (srch != src_height) || (dstw != dst_width) || (dsth != dst_height)) 
    { 
     CL_recreate = true; 

     // rebuild temporary texture 
     if ((dst_width != dstw) || (src_height != srch)) 
      resizeTemporaryOpenGLTexture(); 
     // rebuild target texture 
     if ((dst_width != dstw) || (dst_height != dsth)) 
      resizeOutputOpenGLTexture(); 

     // finally copy new values to the non-temporary objects 
    } 
    // produce all necessary parameters: 
    // - ranges (rngClr, offsClr, range_x, range_y) 
    // - convertXY 
    // - offsets_X 
    // - offsets_Y 
} 

void recreateCLstuff() 
{ 
    releaseCLstuff(); 
    cerr << name() << ": recreating CL-stuff...\n"; 
    k_x    = CLmgr->newKernelInstance(className(), "separable"); 
    k_y    = CLmgr->newKernelInstance(className(), "separable"); 
    k_clearEmpty = CLmgr->newKernelInstance(className(), "clearEmpty"); 
    k_clear   = CLmgr->newKernelInstance(className(), "clear"); 
    // [...] 
    textureObjects[ 0 ] = CLmgr->createTexture(sourceTexID, WI_CL_TEXTURE_USE::sourceTexture, "source FBO texture"); 
    CLmgr->setMemKernelArg(k_x, 0, textureObjects[ 0 ], "horizontal::src"); 
    textureObjects[ 1 ] = CLmgr->createTexture(tempTexID, WI_CL_TEXTURE_USE::tempTexture, "separable downscaler buffer"); 
    CLmgr->setMemKernelArg(k_x, 1, textureObjects[ 1 ], "horizontal::dst"); 
    CLmgr->setMemKernelArg(k_y, 0, textureObjects[ 1 ], "vertical::src"); 
    textureObjects[ 2 ] = CLmgr->createTexture(textureID, WI_CL_TEXTURE_USE::targetTexture, "WI_CLtexture target"); 
    CLmgr->setMemKernelArg(k_y, 1, textureObjects[ 2 ], "vertical::dst"); 
    CLmgr->setMemKernelArg(k_clear, 1, textureObjects[ 2 ], "clear::dst"); 

    CLmgr->setSimpleKernelArg(k_clear, 0, 16, clrCol, "clear::clearColor"); 

    CL_recreate = false; 
} 

void releaseCLstuff() 
{ 
    cerr << name() << ": releasing CL stuff...\n"; 
    cl_int err; 
    #define releaseKernel(obj) if (obj) if (err = clReleaseKernel(obj)) cerr << "release kernel object \""##obj##"\" failed! (" << clErrorString(err) << ")\n" 

    releaseKernel(k_x); 
    releaseKernel(k_y); 
    releaseKernel(k_clear); 

    for (int i = 0; i < 3; ++i) 
    { 
     if (textureObjects[ i ]) 
      if (err = clReleaseMemObject(textureObjects[ i ])) 
       cerr << "release texture object #" << i << " failed! (" << clErrorString(err) << ")\n"; 
      else 
       textureObjects[ i ] = nullptr; 
    } 
} 

回答

0

答案很簡單:明顯的OpenCL不喜歡重複使用一個OpenGL紋理。如果共享紋理的大小發生變化,則需要處理以下步驟:

glDeleteTextures(1, &id); 
glGenTextures(1, &id); 
glBindTexture(GL_TEXTURE_2D, id); 
// set texture parameters, so it becomes complete in the eyes of OpenCL and OpenGL 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
// allocate texture storage in the GPU 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 
glBindTexture(GL_TEXTURE_2D, 0); 
glFinish(); 

object = clCreateFromGLTexture2D(context, flags[ usage ], GL_TEXTURE_2D, 0, &id, nullptr); 
clSetKernelArg(kernel, argPos, sizeof(cl_mem), &object);