Edit

kc3-lang/angle/src/libANGLE/ResourceManager.cpp

Branch :

  • Show log

    Commit

  • Author : Martin Radev
    Date : 2016-08-04 12:25:34
    Hash : 4c4c8e72
    Message : Add compute program compilation and linking support Compute shaders can be now compiled and linked to create programs. Some tests are added to verify successful and unsuccessful compute shader linking. The patch also replaces std::array<int, 3> with a custom struct WorkGroupSize. BUG=angleproject:1442 TEST=angle_end2end_tests TEST=angle_unittests Change-Id: I4ab0ac05755d0167a6d2a798f8d7f1516cf54d84 Reviewed-on: https://chromium-review.googlesource.com/366740 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Olli Etuaho <oetuaho@nvidia.com> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>

  • src/libANGLE/ResourceManager.cpp
  • //
    // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and
    // retrieves objects which may be shared by multiple Contexts.
    
    #include "libANGLE/ResourceManager.h"
    
    #include "libANGLE/Buffer.h"
    #include "libANGLE/Fence.h"
    #include "libANGLE/Path.h"
    #include "libANGLE/Program.h"
    #include "libANGLE/Renderbuffer.h"
    #include "libANGLE/Sampler.h"
    #include "libANGLE/Shader.h"
    #include "libANGLE/Texture.h"
    #include "libANGLE/renderer/GLImplFactory.h"
    
    namespace gl
    {
    ResourceManager::ResourceManager() : mRefCount(1)
    {
    }
    
    ResourceManager::~ResourceManager()
    {
        while (!mBufferMap.empty())
        {
            deleteBuffer(mBufferMap.begin()->first);
        }
    
        while (!mProgramMap.empty())
        {
            deleteProgram(mProgramMap.begin()->first);
        }
    
        while (!mShaderMap.empty())
        {
            deleteShader(mShaderMap.begin()->first);
        }
    
        while (!mRenderbufferMap.empty())
        {
            deleteRenderbuffer(mRenderbufferMap.begin()->first);
        }
    
        while (!mTextureMap.empty())
        {
            deleteTexture(mTextureMap.begin()->first);
        }
    
        while (!mSamplerMap.empty())
        {
            deleteSampler(mSamplerMap.begin()->first);
        }
    
        while (!mFenceSyncMap.empty())
        {
            deleteFenceSync(mFenceSyncMap.begin()->first);
        }
    
        for (auto it = mPathMap.begin(); it != mPathMap.end(); ++it)
        {
            const auto *p = it->second;
            delete p;
        }
    }
    
    void ResourceManager::addRef()
    {
        mRefCount++;
    }
    
    void ResourceManager::release()
    {
        if (--mRefCount == 0)
        {
            delete this;
        }
    }
    
    // Returns an unused buffer name
    GLuint ResourceManager::createBuffer()
    {
        GLuint handle = mBufferHandleAllocator.allocate();
    
        mBufferMap[handle] = nullptr;
    
        return handle;
    }
    
    // Returns an unused shader/program name
    GLuint ResourceManager::createShader(rx::GLImplFactory *factory,
                                         const gl::Limitations &rendererLimitations,
                                         GLenum type)
    {
        ASSERT(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER || type == GL_COMPUTE_SHADER);
        GLuint handle = mProgramShaderHandleAllocator.allocate();
    
        mShaderMap[handle] = new Shader(this, factory, rendererLimitations, type, handle);
    
        return handle;
    }
    
    // Returns an unused program/shader name
    GLuint ResourceManager::createProgram(rx::GLImplFactory *factory)
    {
        GLuint handle = mProgramShaderHandleAllocator.allocate();
    
        mProgramMap[handle] = new Program(factory, this, handle);
    
        return handle;
    }
    
    // Returns an unused texture name
    GLuint ResourceManager::createTexture()
    {
        GLuint handle = mTextureHandleAllocator.allocate();
    
        mTextureMap[handle] = nullptr;
    
        return handle;
    }
    
    // Returns an unused renderbuffer name
    GLuint ResourceManager::createRenderbuffer()
    {
        GLuint handle = mRenderbufferHandleAllocator.allocate();
    
        mRenderbufferMap[handle] = nullptr;
    
        return handle;
    }
    
    // Returns an unused sampler name
    GLuint ResourceManager::createSampler()
    {
        GLuint handle = mSamplerHandleAllocator.allocate();
    
        mSamplerMap[handle] = nullptr;
    
        return handle;
    }
    
    // Returns the next unused fence name, and allocates the fence
    GLuint ResourceManager::createFenceSync(rx::GLImplFactory *factory)
    {
        GLuint handle = mFenceSyncHandleAllocator.allocate();
    
        FenceSync *fenceSync = new FenceSync(factory->createFenceSync(), handle);
        fenceSync->addRef();
        mFenceSyncMap[handle] = fenceSync;
    
        return handle;
    }
    
    ErrorOrResult<GLuint> ResourceManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
    {
        // Allocate client side handles.
        const GLuint client = mPathHandleAllocator.allocateRange(static_cast<GLuint>(range));
        if (client == HandleRangeAllocator::kInvalidHandle)
            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.");
    
        const auto &paths = factory->createPaths(range);
        if (paths.empty())
        {
            mPathHandleAllocator.releaseRange(client, range);
            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate path objects.");
        }
    
        auto hint = mPathMap.begin();
    
        for (GLsizei i = 0; i < range; ++i)
        {
            const auto impl = paths[static_cast<unsigned>(i)];
            const auto id   = client + i;
            hint            = mPathMap.insert(hint, std::make_pair(id, new Path(impl)));
        }
        return client;
    }
    
    void ResourceManager::deleteBuffer(GLuint buffer)
    {
        auto bufferObject = mBufferMap.find(buffer);
    
        if (bufferObject != mBufferMap.end())
        {
            mBufferHandleAllocator.release(bufferObject->first);
            if (bufferObject->second) bufferObject->second->release();
            mBufferMap.erase(bufferObject);
        }
    }
    
    void ResourceManager::deleteShader(GLuint shader)
    {
        auto shaderObject = mShaderMap.find(shader);
    
        if (shaderObject != mShaderMap.end())
        {
            if (shaderObject->second->getRefCount() == 0)
            {
                mProgramShaderHandleAllocator.release(shaderObject->first);
                delete shaderObject->second;
                mShaderMap.erase(shaderObject);
            }
            else
            {
                shaderObject->second->flagForDeletion();
            }
        }
    }
    
    void ResourceManager::deleteProgram(GLuint program)
    {
        auto programObject = mProgramMap.find(program);
    
        if (programObject != mProgramMap.end())
        {
            if (programObject->second->getRefCount() == 0)
            {
                mProgramShaderHandleAllocator.release(programObject->first);
                delete programObject->second;
                mProgramMap.erase(programObject);
            }
            else
            {
                programObject->second->flagForDeletion();
            }
        }
    }
    
    void ResourceManager::deleteTexture(GLuint texture)
    {
        auto textureObject = mTextureMap.find(texture);
    
        if (textureObject != mTextureMap.end())
        {
            mTextureHandleAllocator.release(textureObject->first);
            if (textureObject->second) textureObject->second->release();
            mTextureMap.erase(textureObject);
        }
    }
    
    void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
    {
        auto renderbufferObject = mRenderbufferMap.find(renderbuffer);
    
        if (renderbufferObject != mRenderbufferMap.end())
        {
            mRenderbufferHandleAllocator.release(renderbufferObject->first);
            if (renderbufferObject->second) renderbufferObject->second->release();
            mRenderbufferMap.erase(renderbufferObject);
        }
    }
    
    void ResourceManager::deleteSampler(GLuint sampler)
    {
        auto samplerObject = mSamplerMap.find(sampler);
    
        if (samplerObject != mSamplerMap.end())
        {
            mSamplerHandleAllocator.release(samplerObject->first);
            if (samplerObject->second) samplerObject->second->release();
            mSamplerMap.erase(samplerObject);
        }
    }
    
    void ResourceManager::deleteFenceSync(GLuint fenceSync)
    {
        auto fenceObjectIt = mFenceSyncMap.find(fenceSync);
    
        if (fenceObjectIt != mFenceSyncMap.end())
        {
            mFenceSyncHandleAllocator.release(fenceObjectIt->first);
            if (fenceObjectIt->second) fenceObjectIt->second->release();
            mFenceSyncMap.erase(fenceObjectIt);
        }
    }
    
    void ResourceManager::deletePaths(GLuint first, GLsizei range)
    {
        for (GLsizei i = 0; i < range; ++i)
        {
            const auto id = first + i;
            const auto it = mPathMap.find(id);
            if (it == mPathMap.end())
                continue;
            Path *p = it->second;
            delete p;
            mPathMap.erase(it);
        }
        mPathHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
    }
    
    Buffer *ResourceManager::getBuffer(unsigned int handle)
    {
        auto buffer = mBufferMap.find(handle);
    
        if (buffer == mBufferMap.end())
        {
            return nullptr;
        }
        else
        {
            return buffer->second;
        }
    }
    
    Shader *ResourceManager::getShader(unsigned int handle)
    {
        auto shader = mShaderMap.find(handle);
    
        if (shader == mShaderMap.end())
        {
            return nullptr;
        }
        else
        {
            return shader->second;
        }
    }
    
    Texture *ResourceManager::getTexture(unsigned int handle)
    {
        if (handle == 0)
            return nullptr;
    
        auto texture = mTextureMap.find(handle);
    
        if (texture == mTextureMap.end())
        {
            return nullptr;
        }
        else
        {
            return texture->second;
        }
    }
    
    Program *ResourceManager::getProgram(unsigned int handle) const
    {
        auto program = mProgramMap.find(handle);
    
        if (program == mProgramMap.end())
        {
            return nullptr;
        }
        else
        {
            return program->second;
        }
    }
    
    Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
    {
        auto renderbuffer = mRenderbufferMap.find(handle);
    
        if (renderbuffer == mRenderbufferMap.end())
        {
            return nullptr;
        }
        else
        {
            return renderbuffer->second;
        }
    }
    
    Sampler *ResourceManager::getSampler(unsigned int handle)
    {
        auto sampler = mSamplerMap.find(handle);
    
        if (sampler == mSamplerMap.end())
        {
            return nullptr;
        }
        else
        {
            return sampler->second;
        }
    }
    
    FenceSync *ResourceManager::getFenceSync(unsigned int handle)
    {
        auto fenceObjectIt = mFenceSyncMap.find(handle);
    
        if (fenceObjectIt == mFenceSyncMap.end())
        {
            return nullptr;
        }
        else
        {
            return fenceObjectIt->second;
        }
    }
    
    const Path *ResourceManager::getPath(GLuint handle) const
    {
        auto it = mPathMap.find(handle);
        if (it == std::end(mPathMap))
            return nullptr;
        return it->second;
    }
    
    Path *ResourceManager::getPath(GLuint handle)
    {
        auto it = mPathMap.find(handle);
        if (it == std::end(mPathMap))
            return nullptr;
    
        return it->second;
    }
    
    bool ResourceManager::hasPath(GLuint handle) const
    {
        return mPathHandleAllocator.isUsed(handle);
    }
    
    void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
    {
        mRenderbufferMap[handle] = buffer;
    }
    
    Buffer *ResourceManager::checkBufferAllocation(rx::GLImplFactory *factory, GLuint handle)
    {
        if (handle == 0)
        {
            return nullptr;
        }
    
        auto bufferMapIt     = mBufferMap.find(handle);
        bool handleAllocated = (bufferMapIt != mBufferMap.end());
    
        if (handleAllocated && bufferMapIt->second != nullptr)
        {
            return bufferMapIt->second;
        }
    
        Buffer *buffer = new Buffer(factory->createBuffer(), handle);
        buffer->addRef();
    
        if (handleAllocated)
        {
            bufferMapIt->second = buffer;
        }
        else
        {
            mBufferHandleAllocator.reserve(handle);
            mBufferMap[handle] = buffer;
        }
    
        return buffer;
    }
    
    Texture *ResourceManager::checkTextureAllocation(rx::GLImplFactory *factory,
                                                     GLuint handle,
                                                     GLenum type)
    {
        if (handle == 0)
        {
            return nullptr;
        }
    
        auto textureMapIt    = mTextureMap.find(handle);
        bool handleAllocated = (textureMapIt != mTextureMap.end());
    
        if (handleAllocated && textureMapIt->second != nullptr)
        {
            return textureMapIt->second;
        }
    
        Texture *texture = new Texture(factory, handle, type);
        texture->addRef();
    
        if (handleAllocated)
        {
            textureMapIt->second = texture;
        }
        else
        {
            mTextureHandleAllocator.reserve(handle);
            mTextureMap[handle] = texture;
        }
    
        return texture;
    }
    
    Renderbuffer *ResourceManager::checkRenderbufferAllocation(rx::GLImplFactory *factory,
                                                               GLuint handle)
    {
        if (handle == 0)
        {
            return nullptr;
        }
    
        auto renderbufferMapIt = mRenderbufferMap.find(handle);
        bool handleAllocated   = (renderbufferMapIt != mRenderbufferMap.end());
    
        if (handleAllocated && renderbufferMapIt->second != nullptr)
        {
            return renderbufferMapIt->second;
        }
    
        Renderbuffer *renderbuffer = new Renderbuffer(factory->createRenderbuffer(), handle);
        renderbuffer->addRef();
    
        if (handleAllocated)
        {
            renderbufferMapIt->second = renderbuffer;
        }
        else
        {
            mRenderbufferHandleAllocator.reserve(handle);
            mRenderbufferMap[handle] = renderbuffer;
        }
    
        return renderbuffer;
    }
    
    Sampler *ResourceManager::checkSamplerAllocation(rx::GLImplFactory *factory, GLuint samplerHandle)
    {
        // Samplers cannot be created via Bind
        if (samplerHandle == 0)
        {
            return nullptr;
        }
    
        Sampler *sampler = getSampler(samplerHandle);
    
        if (!sampler)
        {
            sampler                    = new Sampler(factory, samplerHandle);
            mSamplerMap[samplerHandle] = sampler;
            sampler->addRef();
        }
    
        return sampler;
    }
    
    bool ResourceManager::isSampler(GLuint sampler)
    {
        return mSamplerMap.find(sampler) != mSamplerMap.end();
    }
    
    }  // namespace gl