为什么OpenGL在创建/释放资源时会获取指向资源ID的指针?

时间:2014-08-15 15:22:13

标签: c++ opengl

我想知道为什么OpenGL会将指针指向资源ID,因为我正在做这样的事情:

#include "OglResource.h"
#include <iostream>

void WINAPI DeleteVertexArray( GLuint item )
{
    glDeleteVertexArrays(1, &item);
}
OglResource MakeOglResource( GLenum type )
{
    switch( type )
    {
    case GL_VERTEX_SHADER:
        return OglResource(glCreateShader(GL_VERTEX_SHADER), (OglResource::ReleaseFunc)glDeleteShader, GL_VERTEX_SHADER);
        break;
    case GL_FRAGMENT_SHADER:
        return OglResource(glCreateShader(GL_FRAGMENT_SHADER), (OglResource::ReleaseFunc)glDeleteShader, GL_FRAGMENT_SHADER);
        break;
    case GL_VERTEX_ARRAY:
        {
            GLuint out = OglResource::INVALID_OGL_RESOURCE_ID;
            glGenVertexArrays(1, &out);
            return OglResource(out, DeleteVertexArray, GL_VERTEX_ARRAY);
        }
        break;
    }

    return OglResource();
}

如果我传递给OpenGL的资源ID的地址确实很重要,这很危险,因为只要MakeOglResource函数返回,我传递给OpenGL(&amp; out)的位置就无效。

我对此进行了测试,但似乎没有崩溃应用程序,但我很担心。

  1. 为什么OpenGL要我在CreateVertexArrays / DeleteVertexArrays时传递地址?
  2. 这段代码对您来说是否安全?
  3. 以下是OglResource的实现:

    #ifndef _HANDLE_H
    #define _HANDLE_H
    
    #include <memory>
    #include <functional>
    
    #define CALL_CONVENTION WINAPI
    template <typename HANDLE_TYPE>
    class Handle
    {
    public:
        typedef void (CALL_CONVENTION *ReleaseFunc)(HANDLE_TYPE);
    
    private:
        // Handler
        std::shared_ptr<void> m_spItem;
    
    public:
        operator HANDLE_TYPE()
        {
            return (HANDLE_TYPE)(m_spItem.get());
        }
        Handle( void )
            : m_spItem()
        {
        }
        Handle( HANDLE_TYPE id, ReleaseFunc fpRelease )
            : m_spItem(nullptr)
        {
            Reset(id,fpRelease);
        }
        void Reset( void )
        {
            m_spItem.reset();
        }
        void Reset( HANDLE_TYPE handle, ReleaseFunc fpRelease)
        {
            m_spItem.reset((void*)handle,[=](void* vpItem)
                                         {
                                            fpRelease((HANDLE_TYPE)vpItem);
                                         });
        }
    };
    
    #endif // _HANDLE_H
    
    #ifndef _OGLRESOURCE_H
    #define _OGLRESOURCE_H
    
    #include <Windows.h>
    #include <gl/glew.h>
    #include <Gl/GL.h>
    #include "Handle.h"
    
    class OglResource : public Handle<GLuint>
    {
        friend OglResource MakeOglResource( GLenum type );
    
    public:
        GLenum m_type;
        OglResource( void )
            : Handle()
            , m_type(0)
        {
        }
        OglResource( GLuint resource, Handle::ReleaseFunc fpRelease, GLenum type )
            : Handle(resource, fpRelease)
            , m_type(type)
    
        {
        }
        enum { INVALID_OGL_RESOURCE_ID = 0 };
    }; // class OglShader
    
    OglResource MakeOglResource( GLenum type );
    
    #endif // _OGLRESOURCE_H
    

1 个答案:

答案 0 :(得分:5)

此接口允许调用者通过单个调用生成或删除多个资源ID(也称为名称)。我认为这纯粹是一种效率考虑。如果您通过值传递,则每个ID都需要一次调用。

例如,这会生成并删除3个ID:

GLuint ids[3];
glGenBuffers(3, ids);
glDeleteBuffers(3, ids);

否则你将需要3个电话来生成和删除3个ID。

无需将同一指针传递给GenDelete。以下是完全合法和安全的:

GLuint id = 0;
glGenBuffers(1, &id);
GLuint idCopy = id;
glDeleteBuffers(1, &idCopy);