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

use*_*715 0 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();
}
Run Code Online (Sandbox Code Playgroud)

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

我对此进行了测试,看起来并没有让应用程序崩溃,但我很担心.

  1. 为什么OpenGL要我在CreateVertexArrays/DeleteVertexArrays时传递地址?
  2. 这段代码对你来说安全吗?

下面是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
Run Code Online (Sandbox Code Playgroud)

Ret*_*adi 5

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

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

GLuint ids[3];
glGenBuffers(3, ids);
glDeleteBuffers(3, ids);
Run Code Online (Sandbox Code Playgroud)

否则,您将需要3个调用来生成和删除3个ID.

没有要求将相同的指针传递给GenDelete.以下是完全合法和安全的:

GLuint id = 0;
glGenBuffers(1, &id);
GLuint idCopy = id;
glDeleteBuffers(1, &idCopy);
Run Code Online (Sandbox Code Playgroud)