簡體   English   中英

Windows上的OpenCL / OpenGL紋理互操作:調整OpenGL紋理的大小

[英]OpenCL/OpenGL Texture interop on windows: resizing OpenGL textures

此問題的后續處理OpenCL / OpenGL Texture互操作/ windows問題

我們有:

  • 渲染到FBO,紋理附加為COLOR_ATTACHMENT0,這是inTex
  • 可分離downscaler在OpenCL中,使用inTex ,產生outTex在通過三步過程tempTex

現在出現了一個新問題,因為這是一個編輯器實現。 如果inTex的大小更改或outTex的大小更改,則首先使用glTexImage2d調整OpenGL紋理的大小。 然后釋放三個內核對象,最后使用clReleaseMemObj( XTex )釋放所有三個紋理的cl_mem對象。 最后一步只是使用與初始化時相同的代碼重新創建所有必要的對象,然后循環繼續進行。

在使用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;
    }
}

簡單的答案:顯然,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 );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM