コード例 #1
0
// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLBindless::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                   const std::vector<TexturedQuadsProblem::Index>& _indices,
                                   const std::vector<TextureDetails*>& _textures,
                                   size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Prerequisites
    if (glGetTextureHandleARB == nullptr) {
        console::warn("Unable to initialize solution '%s', requires support for bindless textures (not present).", GetName().c_str());
        return false;
    }

    // Program
    const char* kUniformNames[] = { "ViewProjection", "DrawID", "gTex", nullptr };

    mProgram = CreateProgramT("textures_gl_bindless_vs.glsl",
                              "textures_gl_bindless_fs.glsl", 
                              kUniformNames, &mUniformLocation);

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    // Textures
    for (auto it = _textures.begin(); it != _textures.end(); ++it) {
        GLuint tex = NewTex2DFromDetails(*(*it));
        if (!tex) {
            console::warn("Unable to initialize solution '%s', texture creation failed.", GetName().c_str());
            return false;
        }

        // Needs to be freed later.
        mTextures.push_back(tex);

        GLuint64 texHandle = glGetTextureHandleARB(tex);
        if (texHandle == 0) {
            console::warn("Unable to initialize solution '%s', couldn't get texture handle.", GetName().c_str());
        }
        mTexHandles.push_back(texHandle);
    }

    // Buffers
    glGenVertexArrays(1, &mVertexArray);
    glBindVertexArray(mVertexArray);

    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    glGenBuffers(1, &mTransformBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer);

    glGenVertexArrays(1, &mVAO);
    glBindVertexArray(mVAO);

    return glGetError() == GL_NO_ERROR;
}
コード例 #2
0
// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLSparseBindlessTextureArray::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                                     const std::vector<TexturedQuadsProblem::Index>& _indices,
                                                     const std::vector<TextureDetails*>& _textures,
                                                     size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Prerequisites
    if (!mTexManager.Init()) {
        return false;
    }

    if (glGetTextureHandleARB == nullptr) {
        console::warn("Unable to initialize solution '%s', requires support for bindless textures (not present).", GetName().c_str());
        return false;
    }

    // Program
    const char* kUniformNames[] = { "ViewProjection", "DrawID", nullptr };

    mProgram = CreateProgramT("textures_gl_sparse_bindless_texture_array_vs.glsl",
                              "textures_gl_sparse_bindless_texture_array_fs.glsl",
                              kUniformNames, &mUniformLocation);

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    // Textures
    for (auto it = _textures.begin(); it != _textures.end(); ++it) {
        mTextures.push_back(mTexManager.newTexture2DFromDetails(*it));
    }

    // Buffers
    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    glGenBuffers(1, &mTransformBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer);

    auto srcIt = mTextures.cbegin();
    std::vector<TexAddress> texAddressContents(_objectCount);
    for (auto dstIt = texAddressContents.begin(); dstIt != texAddressContents.end(); ++dstIt) {
        if (srcIt == mTextures.cend()) {
            srcIt = mTextures.cbegin();
        }

        (*dstIt) = (*srcIt)->GetAddress();
        ++srcIt;
    }

    mTexAddressBuffer = NewBufferFromVector(GL_SHADER_STORAGE_BUFFER, texAddressContents, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mTexAddressBuffer);

    return glGetError() == GL_NO_ERROR;
}
コード例 #3
0
ファイル: naive.cpp プロジェクト: ChickenEggSolutions/apitest
// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLNaive::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                const std::vector<TexturedQuadsProblem::Index>& _indices,
                                const std::vector<TextureDetails*>& _textures,
                                size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Program
    const char* kUniformNames[] = { "ViewProjection", "World", "gTex", nullptr };

    mProgram = CreateProgramT("textures_gl_naive_vs.glsl",
                              "textures_gl_naive_fs.glsl",
                              kUniformNames, &mUniformLocation);

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    // Textures
    for (auto it = _textures.begin(); it != _textures.end(); ++it) {
        GLuint tex = NewTex2DFromDetails(*(*it));
        if (!tex) {
            console::warn("Unable to initialize solution '%s', texture creation failed.", GetName().c_str());
            return false;
        }

        // Needs to be freed later.
        mTextures.push_back(tex);
    }

    // Buffers
    glGenVertexArrays(1, &mVertexArray);
    glBindVertexArray(mVertexArray);

    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, pos));
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, tex));
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    return GLRenderer::GetApiError() == GL_NO_ERROR;
}
コード例 #4
0
ファイル: naiveuniform.cpp プロジェクト: bisclavret/apitest
// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLNaiveUniform::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                       const std::vector<TexturedQuadsProblem::Index>& _indices,
                                       const std::vector<TextureDetails*>& _textures,
                                       size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Program
    const char* kUniformNames[] = { "ViewProjection", "DrawID", "gTex", nullptr };

    mProgram = CreateProgramT("textures_gl_naive_uniform_vs.glsl",
                              "textures_gl_naive_uniform_fs.glsl",
                              kUniformNames, &mUniformLocation);

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    glGenVertexArrays(1, &mVertexArrayObject);
    glBindVertexArray(mVertexArrayObject);

    // Textures
    for (auto it = _textures.begin(); it != _textures.end(); ++it) {
        GLuint tex = NewTex2DFromDetails(*(*it));
        if (!tex) {
            console::warn("Unable to initialize solution '%s', texture creation failed.", GetName().c_str());
            return false;
        }

        // Needs to be freed later.
        mTextures.push_back(tex);
    }

    // Buffers
    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    glGenBuffers(1, &mTransformBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer);

    return GLRenderer::GetApiError() == GL_NO_ERROR;
}
コード例 #5
0
// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLNoTexUniform::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                       const std::vector<TexturedQuadsProblem::Index>& _indices,
                                       const std::vector<TextureDetails*>& _textures,
                                       size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Program
    const char* kUniformNames[] = { "ViewProjection", "DrawID", nullptr };

    mProgram = CreateProgramT("textures_gl_notex_uniform_vs.glsl",
                              "textures_gl_notex_uniform_fs.glsl",
                              kUniformNames, &mUniformLocation);

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    glGenVertexArrays(1, &mVertexArrayObject);
    glBindVertexArray(mVertexArrayObject);

    // Buffers
    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    glGenBuffers(1, &mTransformBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer);

    glGenVertexArrays(1, &mVAO);
    glBindVertexArray(mVAO);

    return glGetError() == GL_NO_ERROR;
}
コード例 #6
0
// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLSparseBindlessTextureArrayMultiDraw::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                                              const std::vector<TexturedQuadsProblem::Index>& _indices,
                                                              const std::vector<TextureDetails*>& _textures,
                                                              size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Prerequisites
    if (!mTexManager.Init()) {
        return false;
    }

    if (glGetTextureHandleARB == nullptr) {
        console::warn("Unable to initialize solution '%s', requires support for bindless textures (not present).", GetName().c_str());
        return false;
    }

    if (mUseShaderDrawParameters && !HasExtension(ARB_shader_draw_parameters)) {
        console::warn("Unable to initialize solution, ARB_shader_draw_parameters is required but not available.");
        return false;
    }

    // Program
    mProgram = CreateProgram("textures_gl_sparse_bindless_texture_array_multidraw_vs.glsl",
                             "textures_gl_sparse_bindless_texture_array_multidraw_fs.glsl",
                             mUseShaderDrawParameters ? std::string("#define USE_SHADER_DRAW_PARAMETERS 1\n") : std::string("")
                             );

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    // Textures
    for (auto it = _textures.begin(); it != _textures.end(); ++it) {
        mTextures.push_back(mTexManager.newTexture2DFromDetails(*it));
    }

    // Buffers
    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, pos));
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, tex));
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    // If we aren't using shader draw parameters, use the workaround instead.
    if (!mUseShaderDrawParameters) {
        std::vector<uint32_t> drawids(_objectCount);
        for (uint32_t i = 0; i < _objectCount; ++i) {
            drawids[i] = i;
        }

        mDrawIDBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, drawids, GL_STATIC_DRAW);
        glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, sizeof(uint32_t), 0);
        glVertexAttribDivisor(2, 1);
        glEnableVertexAttribArray(2);
    }

    glGenBuffers(1, &mTransformBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer);

    auto srcIt = mTextures.cbegin();
    std::vector<TexAddress> texAddressContents(_objectCount);
    for (auto dstIt = texAddressContents.begin(); dstIt != texAddressContents.end(); ++dstIt) {
        if (srcIt == mTextures.cend()) {
            srcIt = mTextures.cbegin();
        }

        (*dstIt) = (*srcIt)->GetAddress();
        ++srcIt;
    }

    mTexAddressBuffer = NewBufferFromVector(GL_SHADER_STORAGE_BUFFER, texAddressContents, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mTexAddressBuffer);

    mCommands.resize(_objectCount);

    return glGetError() == GL_NO_ERROR;
}
コード例 #7
0
// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLTextureArrayUniform::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                              const std::vector<TexturedQuadsProblem::Index>& _indices,
                                              const std::vector<TextureDetails*>& _textures,
                                              size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Prerequisites
    auto numTextures = _textures.size();
    if (!mTexManager.Init(false, numTextures)) {
        return false;
    }

    // Program
    const char* kUniformNames[] = { "ViewProjection", "DrawID", "TexContainer", nullptr };

    mProgram = CreateProgramT("textures_gl_texture_array_uniform_vs.glsl",
                              "textures_gl_texture_array_uniform_fs.glsl",
                              kUniformNames, &mUniformLocation);

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    // Textures
    for (auto it = _textures.begin(); it != _textures.end(); ++it) {
        mTextures.push_back(mTexManager.newTexture2DFromDetails(*it));
    }

    GLint lastTexId = -1;
    GLint lastTexUnit = -1;
    std::vector<DenseTexAddress> texAddress(numTextures);
    for (size_t i = 0; i < numTextures; ++i) {
        auto texture = mTextures[i];
        auto texId = texture->GetTexId();
        if (lastTexId != texId) {
            lastTexId = texId;
            lastTexUnit = (GLint) mTexUnits.size();

            glActiveTexture(GL_TEXTURE0 + lastTexUnit);
            glBindTexture(GL_TEXTURE_2D_ARRAY, texId);
            mTexUnits.push_back(lastTexUnit);
        }

        texAddress[i].m_container_index = lastTexUnit;
        texAddress[i].m_layer = ((float) texture->getSliceNum() + 0.5f) / numTextures;
    }

    std::vector<DenseTexAddress> texAddressContents(_objectCount);
    for (uint32_t i = 0; i < _objectCount; ++i) {
        texAddressContents[i] = texAddress[i % numTextures];
    }

    mTexAddressBuffer = NewBufferFromVector(GL_SHADER_STORAGE_BUFFER, texAddressContents, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mTexAddressBuffer);

    // Buffers
    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    glGenBuffers(1, &mTransformBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer);

    return glGetError() == GL_NO_ERROR;
}
コード例 #8
0
// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLBindlessMultiDraw::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                            const std::vector<TexturedQuadsProblem::Index>& _indices,
                                            const std::vector<TextureDetails*>& _textures,
                                            size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Prerequisites
    if (glGetTextureHandleARB == nullptr) {
        console::warn("Unable to initialize solution '%s', requires support for bindless textures (not present).", GetName().c_str());
        return false;
    }

    // Programs
    mProgram = CreateProgram("textures_gl_bindless_multidraw_vs.glsl",
                             "textures_gl_bindless_multidraw_fs.glsl");

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    // Textures
    for (auto it = _textures.begin(); it != _textures.end(); ++it) {
        GLuint tex = NewTex2DFromDetails(*(*it));
        if (!tex) {
            console::warn("Unable to initialize solution '%s', texture creation failed.", GetName().c_str());
            return false;
        }

        // Needs to be freed later.
        mTextures.push_back(tex);

        GLuint64 texHandle = glGetTextureHandleARB(tex);
        if (texHandle == 0) {
            console::warn("Unable to initialize solution '%s', couldn't get texture handle.", GetName().c_str());
        }
        mTexHandles.push_back(texHandle);
    }

    // Buffers
    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    glGenBuffers(1, &mTransformBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer);

    auto srcIt = mTexHandles.cbegin();
    std::vector<GLuint64> texAddressContents(_objectCount);
    for (auto dstIt = texAddressContents.begin(); dstIt != texAddressContents.end(); ++dstIt) {
        if (srcIt == mTexHandles.cend()) {
            srcIt = mTexHandles.cbegin();
        }

        (*dstIt) = *srcIt;
        ++srcIt;
    }

    mTexAddressBuffer = NewBufferFromVector(GL_SHADER_STORAGE_BUFFER, texAddressContents, GL_STATIC_DRAW);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mTexAddressBuffer);

    mCommands.resize(_objectCount);

    return GLRenderer::GetApiError() == GL_NO_ERROR;
}
コード例 #9
0
// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLTextureArrayMultiDraw::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                       const std::vector<TexturedQuadsProblem::Index>& _indices,
                                       const std::vector<TextureDetails*>& _textures,
                                       size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Prerequisites
    auto numTextures = _textures.size();
    if (!mTexManager.Init(false, numTextures)) {
        return false;
    }

    if (mUseShaderDrawParameters && !HasExtension("GL_ARB_shader_draw_parameters")) {
        console::warn("Unable to initialize solution, ARB_shader_draw_parameters is required but not available.");
        return false;
    }

    // Program
    const char* kUniformNames[] = { "ViewProjection", "TexContainer", nullptr };

    mProgram = CreateProgramT("textures_gl_texture_array_multidraw_vs.glsl",
                              "textures_gl_texture_array_multidraw_fs.glsl",
                              mUseShaderDrawParameters ? std::string("#define USE_SHADER_DRAW_PARAMETERS 1\n") : std::string(""),
                              kUniformNames, &mUniformLocation);

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    // Textures
    for (auto it = _textures.begin(); it != _textures.end(); ++it) {
        mTextures.push_back(mTexManager.newTexture2DFromDetails(*it));
    }

    GLint lastTexId = -1;
    GLint lastTexUnit = -1;
    std::vector<DenseTexAddress> texAddress(numTextures);
    for (size_t i = 0; i < numTextures; ++i) {
        auto texture = mTextures[i];
        auto texId = texture->GetTexId();
        if (lastTexId != texId) {
            lastTexId = texId;
            lastTexUnit = (GLint) mTexUnits.size();

            glActiveTexture(GL_TEXTURE0 + lastTexUnit);
            glBindTexture(GL_TEXTURE_2D_ARRAY, texId);
            mTexUnits.push_back(lastTexUnit);
        }

        texAddress[i].m_container_index = lastTexUnit;
        texAddress[i].m_layer = ((float) texture->getSliceNum() + 0.5f) / numTextures;
    }

    std::vector<DenseTexAddress> texAddressContents(_objectCount);
    for (uint32_t i = 0; i < _objectCount; ++i) {
        texAddressContents[i] = texAddress[i % numTextures];
    }

    mTexAddressBuffer = NewBufferFromVector(GL_SHADER_STORAGE_BUFFER, texAddressContents, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mTexAddressBuffer);

    // Buffers
    glGenVertexArrays(1, &mVertexArray);
    glBindVertexArray(mVertexArray);

    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, pos));
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, tex));
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    // If we aren't using shader draw parameters, use the workaround instead.
    if (!mUseShaderDrawParameters) {
        std::vector<uint32_t> drawids(_objectCount);
        for (uint32_t i = 0; i < _objectCount; ++i) {
            drawids[i] = i;
        }

        mDrawIDBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, drawids, GL_STATIC_DRAW);
        glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, sizeof(uint32_t), 0);
        glVertexAttribDivisor(2, 1);
        glEnableVertexAttribArray(2);
    }

    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    glGenBuffers(1, &mTransformBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer);

    // Set the command buffer size.
    m_commands.resize(_objectCount);

    return glGetError() == GL_NO_ERROR;
}