glBlitFramebuffer Недопустимая операция

Я возился с фреймбуферами и рендерингом в текстуру, и я столкнулся с необходимостью их блита. Опять же, на некоторых машинах я получаю GL_INVALID_OPERATION сразу после вызова glBlitFramebuffer. Каждая текстура, привязанная к фреймбуферу, настраивается точно так же, с одинаковым размером и параметрами. Кроме того, когда я пытаюсь перенести одну всю текстуру (ранее успешно отрендеренную) в другой буфер кадра, только целевой «прямоугольник» для записи меньше, чем прямоугольник для чтения (например, когда я хочу преобразовать его в четверть кадра). экран), он также выдает GL_INVALID_OPERATION.

РЕДАКТИРОВАТЬ: На самом деле он всегда выдает ошибку всякий раз, когда прямоугольники для чтения и рисования имеют другой размер, поэтому я не могу использовать текстуру другого размера или того же размера. но область рендеринга другого размера...?

Каждый раз, когда я перехожу к созданному вручную фреймбуферу, статус проверяется через glCheckFramebufferStatus и всегда возвращает GL_FRAMEBUFFER_COMPLETE.

-САМЫЙ БОЛЬШОЙ SNIP-, см. ниже более короткий «исходный код», очевидно, пара ошибок C++ и не полный, но это только для вызовов GL

Ошибка OpenGL возникает, когда я вызываю последний метод окна просмотра (Viewport::blit) с кадровым буфером экрана в качестве цели (путем передачи NULL). Сначала он устанавливает буфер чтения своего собственного фреймбуфера (буферы отрисовки уже были установлены), а затем вызывает RenderTarget::blit, который вызывает glBlitFramebuffer. В методе blit он связывает оба буфера, и вы можете видеть, что он вызывает там glCheckFramebufferStatus, который не возвращает ошибку.

Я читаю это снова и снова, но не могу найти ошибку что вызывает это. Когда я блицирую цветовой буфер, я использую GL_LINEAR, иначе я использую GL_NEAREST Все цветовые буферы используют GL_RGB32F в качестве внутреннего формата, а буфер глубины (который я никогда не блицировал) использует GL_DEPTH_COMPONENT32F

EDIT, более короткий пример, просто взял все вызовы GL и заполнил параметры, которые я использовал

glBindFramebuffer(GL_READ_FRAMEBUFFER, _GL_Framebuffer);
glReadBuffer(GL_COLOR_ATTACHMENT0 + index);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

// OpenGL error check, does not return an error

glBindFramebuffer(GL_READ_FRAMEBUFFER, _GL_Framebuffer);
GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
{
    // Some error checking, fortunately status always turns out to be complete
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

glBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, target, (target == GL_COLOR_BUFFER_BIT) ? GL_LINEAR : GL_NEAREST);

// If the source/destination read/draw rectangles are different in size, GL_INVALID_OPERATION is cought here

И создание фреймбуфера/текстуры:

glGenFramebuffer(1, &_GL_Framebuffer);

glGenTextures(1, &_GL_ZBuffer);
glBindTexture(GL_TEXTURE_2D, _GL_ZBuffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, screenWidth, screenHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);

glBindFramebuffer(GL_FRAMEBUFFER, _GL_Framebuffer);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT + 0, _GL_ZBuffer, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

int writeIndices[BUFFER_COUNT];
for(unsigned int i = 0; i < BUFFER_COUNT; ++i)
{
    writeIndices[i] = i;

    glGenTextures(1, &_GL_Texture);
    glBindTexture(GL_TEXTURE_2D, _GL_Texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, screenWidth, screenHeight, 0, GL_RGB, GL_FLOAT, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);

    glBindFramebuffer(GL_FRAMEBUFFER, _GL_Framebuffer);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, _GL_Texture, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // In the actual code each texture is obviously saved in an object
}

GLenum *enums = new GLenum[BUFFER_COUNT];
for(unsigned int i = 0; i < BUFFER_COUNT; ++i)
{
    // Get index and validate
    int index = *(indices + i); // indices = writeIndices
    if(index < 0 || index >= maxAttachments)
    {
        delete[] enums;
        return false;
    }

    // Set index
    enums[i] = GL_COLOR_ATTACHMENT0 + index;
}

// Set indices
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _GL_Framebuffer);
glDrawBuffers(BUFFER_COUNT, enums);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

delete[] enums;

// OpenGL error check, no errors

person Invalid    schedule 11.08.2012    source источник
comment
Является ли какой-либо из ваших FBO мультисэмплированным?   -  person KillianDS    schedule 11.08.2012
comment
О, об этом, я никогда не устанавливал никаких параметров, касающихся мультисэмплинга, я не знаю, как FBO справляются с этим сами, но я предполагаю, что в настоящее время они следуют поведению по умолчанию. Я был бы признателен за подсказку в правильном направлении о том, как установить поведение мультисэмплинга FBO. xD Также обратите внимание, что он успешно переносится, если прямоугольники рисования / чтения равны, он выдает ошибку только тогда, когда они не равны, или на некоторых ноутбуках ( ноутбуки ДОЛЖНЫ поддерживать как минимум OpenGL 3.2).   -  person Invalid    schedule 11.08.2012
comment
Вы можете взглянуть на это и это. Он содержит и другие возможные причины, потому что здесь трудно угадать. Ваш пример слишком длинный, не могли бы вы попытаться воспроизвести его в строке или в 20?   -  person KillianDS    schedule 11.08.2012
comment
Хорошо, я просмотрел каждый вызов и исключил все вызовы OpenGL, см. В нижней части вопроса фактический код блитинга и создание буфера кадра/текстуры.   -  person Invalid    schedule 11.08.2012


Ответы (1)


После некоторого внимательного чтения я обнаружил, что проблема заключалась в разнице в мультисэмплинге. «Основной» FBO был настроен SFML, поэтому, просто установив уровень сглаживания при запуске на 0, проблема была частично решена.

Теперь он срабатывает, если прямоугольники рисования/чтения неравны по размеру, но он продолжает падать на некоторых машинах, где он ДОЛЖЕН работать.

person Invalid    schedule 11.08.2012
comment
Сколько лет драйверам на этих машинах? Есть несколько старых драйверов, на которых FBO плохо себя ведет (хотя они очень старые). edit: хитрость в том, что если ваш кадровый буфер src мультисэмплирован, вы должны иметь возможность рисовать на fbo без выборки, но только один из них одинакового размера гарантированно будет работать iirc. Так что, возможно, на этих платформах буфер кадра по умолчанию все еще мультисэмплинг. Блайтинг с разными размерами, но с одинаковой частотой дискретизации должен работать без ограничений. - person KillianDS; 12.08.2012