1

Can any one tell me why my code works on local machine but not on a remote machine I'm trying to push to?

local driver version:  NVIDIA-SMI 460.91.03   Driver Version: 460.91.03
remote driver version: NVIDIA-SMI 435.21      Driver Version: 435.21

When trying to run on remote machine, I keep getting:

QGLFramebufferObject: Framebuffer incomplete attachment.
QGLFramebufferObject: Framebuffer incomplete attachment.
Framebuffer is not valid, may be out of memoryor context is not valid
Could not bind framebuffer
Image passed to GenImage is null!

Framebuffer code:

/*--------------------------------------------------------------------------*/
    /*--------------------------------------------------------------------------*/
    void GlowFramebuffer::Create( int width , int height )
    {
       QGLFramebufferObjectFormat format;
       if( m_format == GLOW_R )
       {
          format.setInternalTextureFormat(GL_RED );
          m_framebuffer =
          QSharedPointer<QGLFramebufferObject>(
                new QGLFramebufferObject(width, height, format) );
       }   else if ( m_attachment == GLOW_DEPTH_STENCIL ) {
          format.setAttachment( QGLFramebufferObject::CombinedDepthStencil );
          m_framebuffer =
          QSharedPointer<QGLFramebufferObject>(
                new QGLFramebufferObject(width, height, format) );
       }
       else // GLOW_RGBA
       {
          m_framebuffer =
          QSharedPointer<QGLFramebufferObject>(
                new QGLFramebufferObject(width, height) );
       }
       SetClearColor( m_clear_color ); 
    }
    /*--------------------------------------------------------------------------*/
    
    /*--------------------------------------------------------------------------*/
    void GlowFramebuffer::Create( const QSize& size )
    {
       Create( size.width() , size.height() ); 
       if( !m_framebuffer->isValid() )
       {
          qCritical() << "Framebuffer is not valid, may be out of memory" 
             "or context is not valid";
       }
    }
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
int GlowFramebuffer::CopyMultiTexture(  GlowFilter filter , GlowFormat format )
{
   GLint width = m_framebuffer->width(); 
   GLint height = m_framebuffer->height();

   GLuint FramebufferName = 0;
   glGenFramebuffers(1, &FramebufferName);
   glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); 

   GLenum glfilter = (filter == GLOW_NEAREST) ? GL_NEAREST : GL_LINEAR;
   GLenum glformat = (format == GLOW_R ) ? GL_R : GL_RGBA;

   GLuint renderedTexture;
   glGenTextures(1, &renderedTexture);

   // "Bind" the newly created texture : all future texture functions will modify this texture
   glBindTexture(GL_TEXTURE_2D, renderedTexture);

   // Give an empty image to OpenGL ( the last "0" )
   glTexImage2D(GL_TEXTURE_2D, 0,glformat, width, height, 0,glformat, GL_UNSIGNED_BYTE, 0);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfilter);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfilter);
   glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderedTexture, 0);
   // Set the list of draw buffers.
   GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
   glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers

    GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
    if( status != GL_FRAMEBUFFER_COMPLETE )
    {
       qCritical() << "Error with framebuffer!";
    }

    GLuint handle = m_framebuffer->handle();
    GLClear();

    glBindFramebuffer( GL_DRAW_FRAMEBUFFER , FramebufferName );
    glBindFramebuffer( GL_READ_FRAMEBUFFER , handle );
    glDrawBuffer( GL_BACK );
    glBlitFramebuffer( 0 , 0 , width , height , 0 , 0 , width , height , GL_COLOR_BUFFER_BIT , GL_NEAREST );
   
    glBindTexture( GL_TEXTURE_2D , 0 );
    glBindFramebuffer( GL_FRAMEBUFFER , handle );
    glDeleteFramebuffers( 1 , &FramebufferName );

    return renderedTexture;
}

I know its likely because FBOs are specific to each machine and driver. In order to ensure its compatible, you need to check the system to make sure the Format which you created your frame buffer is valid.

I think its failing on the remote machine at this line:

 GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
    if( status != GL_FRAMEBUFFER_COMPLETE )
    {
       qCritical() << "Error with framebuffer!";
    }

I think glformat variable is the format to be adjusted in this function:

 glTexImage2D(GL_TEXTURE_2D, 0,glformat, width, height, 0,glformat, GL_UNSIGNED_BYTE, 0);

How do I have it pick the appropriate format to make the FBO on the remote machine?

Code for the image from the framebuffer we're trying to attach:

bool Product::SetImgInfo(GeoRadarProd &prod, const JsonConfig &config)
{
    DataInput input(FLAGS_input.c_str());
    QString file_name_data = FLAGS_file_name.c_str();

    int width = config.GetInt("width");
    int height = config.GetInt("height");

    if(!input.isValid())
    {
       LOG(INFO) << "Input is not valid";
       return false;
    }

    QByteArray data = input.getByteArray();

    VLOG(3) << "width from config: "<< width;
    VLOG(3) << "height from config: "<< height;

    VLOG(3) << "data : "<< data.size();
    QImage image_data;
    image_data.fromData(data, "PNG");

    VLOG(3) << "what is file_name_data ???: " << file_name_data.toStdString();
    VLOG(3) << "is image_data load???: " << image_data.load(file_name_data, "PNG");
    VLOG(3) << "is image_data null???: " << image_data.isNull();

    VLOG(3) << "image data width: "<< image_data.width();
    VLOG(3) << "image data height: "<< image_data.height();
    VLOG(3)<< "Original Format was tif";

    VLOG(3)<<"Data Img H: "<< image_data.height()<<" W: "<<image_data.width();
    QImage new_image(image_data.width(), image_data.height(), QImage::Format_RGBA8888);
        
// Format_ARGB32 , Format_RGBA8888_Premultiplied
        
VLOG(3)<<"New Img H: "<<new_image.height()<<" W: "<<new_image.width();
        VLOG(3)<<"Setting img data";

    for(int idx = 0; idx < image_data.width(); idx++)
    {
       for(int idy = 0; idy < image_data.height(); idy++)
       {
           int index_value = image_data.pixelIndex(idx, idy);
           uint color_value;
           if(index_value == 0 )
           {
               color_value = qRgba((int(0)), 0, 0, 0);
           }
           else
           {
               //! +1*20 to have a wider spread in the palette
               //! and since the values start from 0
//               index_value = index_value + 1;
               color_value = qRgb(((int)index_value ), 0, 0);
            }

          new_image.setPixel(idx, idy, color_value);
       }
    }

    const QImage& img = QGLWidget::convertToGLFormat(new_image);
    prod.setQImageData(img);

    return true;
}

1 Answer 1

1

The image format you use is never the cause of this completeness error:

Framebuffer incomplete attachment.

This error means that one of the attachments violates OpenGL's rules on attachment completeness. This is not a problem of the wrong format (per se); it is a code bug.

If you see this on one implementation, you should see it on all implementations running the same FBO setup code. Attachment completeness rules are not allowed to change based on the implementation (with an exception). So if you're seeing this error appear or not appear based on the implementation, one of the following is happening:

  1. There is a bug in one or more of the implementations. Your code may or may not be following the attachment completeness rules, but implementations are supposed to implement the same rules.

  2. You are not in fact using the same FBO setup logic on the different implementations. Since you're creating a QGLFramebufferObject rather than a proper FBO, a lot of the FBO setup code is out of your hands. So maybe stop using Qt for this.

  3. You are running on implementations that differ significantly in which version of OpenGL they implement. See, while the attachment rules don't allow implementation variance, this is only true for a specific version of OpenGL itself. New versions of the API can change the attachment rules, but backwards compatibility guarantees ensure that code that worked on older versions continues to work on newer ones.

    But that only works in one direction: code written against newer OpenGL versions may not be compatible with older implementation versions. Not unless you specifically check the standards and write code that ought to work on all versions you intend to run on.

    Again, most of your FBO logic is hidden behind Qt's implementation, so there's no simple way to know what's going on. It would be good to ditch Qt and do it yourself to make sure.


Now, the above assumes that when Qt tells you "QGLFramebufferObject: Framebuffer incomplete attachment", it really means the GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT completeness status. It's possible Qt is lying to you and your problem really is the format.

When making textures meant to be used by FBOs, you should stick to the image formats that are required to work for FBO-attached images. GL_RED is not one of them.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.