예제 #1
0
bool vogl_sync_state::remap_handles(vogl_handle_remapper &remapper)
{
    VOGL_FUNC_TRACER

    m_snapshot_handle = remapper.remap_handle(VOGL_NAMESPACE_SYNCS, m_snapshot_handle);

    return true;
}
예제 #2
0
bool vogl_vao_state::remap_handles(vogl_handle_remapper &remapper)
{
    VOGL_FUNC_TRACER

    m_snapshot_handle = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_VERTEX_ARRAYS, m_snapshot_handle));

    if (m_element_array_binding)
        m_element_array_binding = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, m_element_array_binding));

    for (uint32_t i = 0; i < m_vertex_attribs.size(); i++)
    {
        if (m_vertex_attribs[i].m_array_binding)
            m_vertex_attribs[i].m_array_binding = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, m_vertex_attribs[i].m_array_binding));

        else if (m_vertex_attribs[i].m_pointer)
            m_vertex_attribs[i].m_pointer = remapper.remap_vertex_attrib_ptr(i, m_vertex_attribs[i].m_pointer);
    }

    return true;
}
예제 #3
0
bool vogl_sync_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 &handle) const
{
    VOGL_FUNC_TRACER

    VOGL_NOTE_UNUSED(context_info);

    if (!m_is_valid)
        return false;

    VOGL_CHECK_GL_ERROR;

    if (!handle)
    {
        GLsync sync = GL_ENTRYPOINT(glFenceSync)(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
        if ((vogl_check_gl_error()) || (!sync))
            return false;
        handle = vogl_sync_to_handle(sync);

        remapper.declare_handle(VOGL_NAMESPACE_SYNCS, m_snapshot_handle, handle, GL_NONE);
        VOGL_ASSERT(remapper.remap_handle(VOGL_NAMESPACE_SYNCS, m_snapshot_handle) == handle);
    }

    return true;
}
예제 #4
0
bool vogl_vao_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 &handle) const
{
    VOGL_FUNC_TRACER

    VOGL_CHECK_GL_ERROR;

    if (!m_is_valid)
        return false;

    vogl_scoped_binding_state orig_binding(GL_VERTEX_ARRAY, GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER);

    if ((!m_snapshot_handle) && (!handle))
    {
        GL_ENTRYPOINT(glBindVertexArray)(0);
        VOGL_CHECK_GL_ERROR;
    }
    else
    {
        if (!handle)
        {
            GLuint handle32 = 0;
            GL_ENTRYPOINT(glGenVertexArrays)(1, &handle32);
            if ((vogl_check_gl_error()) || (!handle32))
                return false;
            handle = handle32;

            if (m_snapshot_handle)
            {
                remapper.declare_handle(VOGL_NAMESPACE_VERTEX_ARRAYS, m_snapshot_handle, handle, GL_NONE);
                VOGL_ASSERT(remapper.remap_handle(VOGL_NAMESPACE_VERTEX_ARRAYS, m_snapshot_handle) == handle);
            }
        }

        if (m_has_been_bound)
        {
            GL_ENTRYPOINT(glBindVertexArray)(static_cast<GLuint>(handle));
            VOGL_CHECK_GL_ERROR;
        }
    }

    if (m_has_been_bound)
    {
        GL_ENTRYPOINT(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, m_element_array_binding)));
        VOGL_CHECK_GL_ERROR;

        if (m_vertex_attribs.size() > context_info.get_max_vertex_attribs())
        {
            vogl_warning_printf("Saved VAO state has %u attribs, but context only allows %u attribs\n", m_vertex_attribs.size(), context_info.get_max_vertex_attribs());
        }

        for (uint32_t i = 0; i < math::minimum<uint32_t>(context_info.get_max_vertex_attribs(), m_vertex_attribs.size()); i++)
        {
            const vogl_vertex_attrib_desc &desc = m_vertex_attribs[i];

            GL_ENTRYPOINT(glBindBuffer)(GL_ARRAY_BUFFER, static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, desc.m_array_binding)));
            VOGL_CHECK_GL_ERROR;

            vogl_trace_ptr_value trace_ptr_val = desc.m_pointer;

            vogl_trace_ptr_value restore_ptr_val = trace_ptr_val;
            if ((!desc.m_array_binding) && (trace_ptr_val) && (context_info.is_compatibility_profile()))
                restore_ptr_val = remapper.remap_vertex_attrib_ptr(i, trace_ptr_val);

            void *pRestore_ptr = reinterpret_cast<void *>(restore_ptr_val);

            if ((handle) && (desc.m_array_binding == 0))
            {
                // If it's a non-default VAO, and there's no array binding, we can't call glVertexAttribPointer() because it's not allowed by AMD drivers (it thinks we're trying to set client side array data)
                // "OpenGL: glVertexAttribPointer failed because it is not allowed to specify a client-side vertex or element array when a non-default vertex array object is bound (GL_INVALID_OPERATION) [source=API type=ERROR severity=HIGH id=2100]"

                // Sanity checks.
                if ((pRestore_ptr != NULL) || (desc.m_stride) || (desc.m_enabled))
                {
                    vogl_warning_printf("Can't bind client side vertex array data on a non-default VAO, trace handle %u GL handle %u, restore ptr %p, size %i stride %i enabled %u\n",
                                        m_snapshot_handle, static_cast<uint32_t>(handle), pRestore_ptr, desc.m_size, desc.m_stride, desc.m_enabled);
                }
            }
            else
            {
                if (desc.m_integer)
                {
                    GL_ENTRYPOINT(glVertexAttribIPointer)(i, desc.m_size, desc.m_type, desc.m_stride, pRestore_ptr);
                    VOGL_CHECK_GL_ERROR;
                }
                else
                {
                    GL_ENTRYPOINT(glVertexAttribPointer)(i, desc.m_size, desc.m_type, desc.m_normalized, desc.m_stride, pRestore_ptr);
                    VOGL_CHECK_GL_ERROR;
                }
            }

            GL_ENTRYPOINT(glVertexAttribDivisor)(i, desc.m_divisor);
            VOGL_CHECK_GL_ERROR;

            if (desc.m_enabled)
            {
                GL_ENTRYPOINT(glEnableVertexAttribArray)(i);
                VOGL_CHECK_GL_ERROR;
            }
            else
            {
                GL_ENTRYPOINT(glDisableVertexAttribArray)(i);
                VOGL_CHECK_GL_ERROR;
            }
        }
    }

    return true;
}
예제 #5
0
bool vogl_query_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 &handle) const
{
    VOGL_FUNC_TRACER

    VOGL_NOTE_UNUSED(context_info);

    if (!m_is_valid)
        return false;

    bool created_handle = false;

    if (!handle)
    {
        GLuint handle32 = 0;
        GL_ENTRYPOINT(glGenQueries)(1, &handle32);
        if ((vogl_check_gl_error()) || (!handle32))
            return false;
        handle = handle32;

        remapper.declare_handle(VOGL_NAMESPACE_QUERIES, m_snapshot_handle, handle, m_target);
        VOGL_ASSERT(remapper.remap_handle(VOGL_NAMESPACE_QUERIES, m_snapshot_handle) == handle);

        created_handle = true;
    }

    // m_target will be GL_NONE if the query has been genned but not begun up to this point.
    if ((m_target != GL_NONE) && (m_has_been_begun))
    {
        GLuint prev_query = 0;
        GL_ENTRYPOINT(glGetQueryiv)(m_target, GL_CURRENT_QUERY, reinterpret_cast<GLint *>(&prev_query));
        VOGL_CHECK_GL_ERROR;

        VOGL_ASSERT(handle <= cUINT32_MAX);

        // Begin end the restore query, so it becomes a valid name.
        GL_ENTRYPOINT(glBeginQuery)(m_target, static_cast<GLuint>(handle));
        if (vogl_check_gl_error())
            goto handle_error;

        GL_ENTRYPOINT(glEndQuery)(m_target);
        if (vogl_check_gl_error())
            goto handle_error;

        if (prev_query)
        {
            // Now begin/end the original query so it's active again. The query API sucks.
            GL_ENTRYPOINT(glBeginQuery)(m_target, prev_query);
            VOGL_CHECK_GL_ERROR;

            GL_ENTRYPOINT(glEndQuery)(m_target);
            VOGL_CHECK_GL_ERROR;
        }
    }

    return true;

handle_error:
    if ((handle) && (created_handle))
    {
        remapper.delete_handle_and_object(VOGL_NAMESPACE_QUERIES, m_snapshot_handle, handle);

        //GLuint handle32 = static_cast<GLuint>(handle);
        //GL_ENTRYPOINT(glDeleteQueries)(1, &handle32);
        //VOGL_CHECK_GL_ERROR;

        handle = 0;
    }

    return false;
}
예제 #6
0
bool vogl_renderbuffer_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 &handle) const
{
    VOGL_FUNC_TRACER

    VOGL_ASSERT(context_info.get_version() >= VOGL_GL_VERSION_3_0);

    if (!m_is_valid)
        return false;

    vogl_scoped_binding_state orig_renderbuffer(GL_RENDERBUFFER);

    bool created_handle = false;

    if (!handle)
    {
        GLuint handle32 = 0;
        GL_ENTRYPOINT(glGenRenderbuffers)(1, &handle32);
        if ((vogl_check_gl_error()) || (!handle32))
            return false;
        handle = handle32;

        remapper.declare_handle(VOGL_NAMESPACE_RENDER_BUFFERS, m_snapshot_handle, handle, GL_NONE);
        VOGL_ASSERT(remapper.remap_handle(VOGL_NAMESPACE_RENDER_BUFFERS, m_snapshot_handle) == handle);

        created_handle = true;
    }

    GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, static_cast<GLuint>(handle));
    if (vogl_check_gl_error())
        goto handle_error;

    if ((m_desc.m_width) && (m_desc.m_height) && (m_desc.m_internal_format))
    {
        if (!m_desc.restore(context_info))
            goto handle_error;

        if (m_texture.is_valid())
        {
            GLenum attachment = GL_COLOR_ATTACHMENT0;
            GLenum draw_and_read_buf = GL_COLOR_ATTACHMENT0;
            GLenum blit_type = GL_COLOR_BUFFER_BIT;

            if ((m_desc.m_depth_size) && (m_desc.m_stencil_size))
            {
                attachment = GL_DEPTH_STENCIL_ATTACHMENT;
                draw_and_read_buf = GL_NONE;
                blit_type = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
            }
            else if (m_desc.m_depth_size)
            {
                attachment = GL_DEPTH_ATTACHMENT;
                draw_and_read_buf = GL_NONE;
                blit_type = GL_DEPTH_BUFFER_BIT;
            }
            else if (m_desc.m_stencil_size)
            {
                attachment = GL_STENCIL_ATTACHMENT;
                draw_and_read_buf = GL_NONE;
                blit_type = GL_STENCIL_BUFFER_BIT;
            }

            bool restore_status = false;

            GLuint64 tex_handle64 = 0;
            vogl_handle_remapper def_handle_remapper;
            if (m_texture.restore(context_info, def_handle_remapper, tex_handle64))
            {
                GLuint tex_handle = static_cast<GLuint>(tex_handle64);

                const GLenum tex_target = (m_desc.m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;

                GLuint src_fbo_handle = 0, dst_fbo_handle = 0;

                // Source FBO
                GL_ENTRYPOINT(glGenFramebuffers)(1, &src_fbo_handle);
                VOGL_CHECK_GL_ERROR;

                GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, src_fbo_handle);
                VOGL_CHECK_GL_ERROR;

                GL_ENTRYPOINT(glFramebufferTexture2D)(GL_READ_FRAMEBUFFER, attachment, tex_target, tex_handle, 0);
                VOGL_CHECK_GL_ERROR;

                GL_ENTRYPOINT(glReadBuffer)(draw_and_read_buf);
                VOGL_CHECK_GL_ERROR;

                // Dest FBO
                GL_ENTRYPOINT(glGenFramebuffers)(1, &dst_fbo_handle);
                VOGL_CHECK_GL_ERROR;

                GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, dst_fbo_handle);
                VOGL_CHECK_GL_ERROR;

                GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, static_cast<GLuint>(handle));
                VOGL_CHECK_GL_ERROR;

                GL_ENTRYPOINT(glDrawBuffers)(1, &draw_and_read_buf);
                VOGL_CHECK_GL_ERROR;

                GLenum read_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_READ_FRAMEBUFFER);
                VOGL_CHECK_GL_ERROR;

                GLenum draw_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
                VOGL_CHECK_GL_ERROR;

                if ((read_status = GL_FRAMEBUFFER_COMPLETE) && (draw_status == GL_FRAMEBUFFER_COMPLETE))
                {
    #if 0
                    // HACK HACK HACK
                    if (m_texture.get_num_samples() > 1)
                    {
                        uint base_level = m_texture.get_params().get_value<GLenum>(GL_TEXTURE_BASE_LEVEL);

                        if (base_level < m_texture.get_num_levels())
                        {
                            const vogl_state_vector &state_vec = m_texture.get_level_params(0, base_level);

                            uint clear_mask = 0;
                            if (state_vec.get_value<GLenum>(GL_TEXTURE_DEPTH_SIZE))
                            {
                                clear_mask |= GL_DEPTH_BUFFER_BIT;
                            }
                            if (state_vec.get_value<GLenum>(GL_TEXTURE_STENCIL_SIZE))
                            {
                                clear_mask |= GL_STENCIL_BUFFER_BIT;
                            }
                            if (state_vec.get_value<GLenum>(GL_TEXTURE_RED_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_GREEN_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_BLUE_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_ALPHA_SIZE) +
                                state_vec.get_value<GLenum>(GL_TEXTURE_INTENSITY_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_LUMINANCE_SIZE))
                            {
                                clear_mask |= GL_COLOR_BUFFER_BIT;
                            }

                            GL_ENTRYPOINT(glClearColor)(1.0f, 0.0f, 1.0f, 1.0f);
                            GL_ENTRYPOINT(glClearDepth)(.5f);
                            GL_ENTRYPOINT(glClearStencil)(128);
                            GL_ENTRYPOINT(glClear)(clear_mask);

                            VOGL_CHECK_GL_ERROR;
                        }
                    }
                    else
    #endif
                    {
                        GL_ENTRYPOINT(glBlitFramebuffer)(
                            0, 0, m_desc.m_width, m_desc.m_height,
                            0, 0, m_desc.m_width, m_desc.m_height,
                            blit_type,
                            GL_NEAREST);

                        if (!vogl_check_gl_error_internal())
                        {
                            restore_status = true;
                        }
                    }
                }

                // Delete FBO
                GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
                VOGL_CHECK_GL_ERROR;

                GL_ENTRYPOINT(glDeleteFramebuffers)(1, &dst_fbo_handle);
                VOGL_CHECK_GL_ERROR;

                GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, 0);
                VOGL_CHECK_GL_ERROR;

                GL_ENTRYPOINT(glDeleteFramebuffers)(1, &src_fbo_handle);
                VOGL_CHECK_GL_ERROR;

                GL_ENTRYPOINT(glDeleteTextures)(1, &tex_handle);
                VOGL_CHECK_GL_ERROR;
            }

            if (!restore_status)
            {
                vogl_error_printf("%s: Failed restoring contents of renderbuffer %u\n", VOGL_METHOD_NAME, static_cast<GLuint>(handle));
            }
        }
    }

    return true;

handle_error:
    if (created_handle)
    {
        GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0);
        VOGL_CHECK_GL_ERROR;

        remapper.delete_handle_and_object(VOGL_NAMESPACE_RENDER_BUFFERS, m_snapshot_handle, handle);

        //GLuint handle32 = static_cast<GLuint>(handle);
        //GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &handle32);
        //VOGL_CHECK_GL_ERROR;

        handle = 0;
    }

    return false;
}