Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ff1959f authored by Alex Sakhartchouk's avatar Alex Sakhartchouk
Browse files

State based shader recompile to support camera input.

Change-Id: Ia6c362571e1b44254461522a8c49a8551b46f28d
parent 69f819b3
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -71,10 +71,10 @@ void rsdProgramVertexDestroy(const Context *rsc, const ProgramVertex *pv) {
    if(pv->mHal.drv) {
        drv = (RsdShader*)pv->mHal.drv;
        if (rsc->props.mLogShaders) {
            ALOGV("Destroying vertex shader with ID %u", drv->getShaderID());
            ALOGV("Destroying vertex shader with ID %u", (uint32_t)pv);
        }
        if (drv->getShaderID()) {
            dc->gl.shaderCache->cleanupVertex(drv->getShaderID());
        if (drv->getStateBasedIDCount()) {
            dc->gl.shaderCache->cleanupVertex(drv);
        }
        delete drv;
    }
@@ -105,10 +105,10 @@ void rsdProgramFragmentDestroy(const Context *rsc, const ProgramFragment *pf) {
    if(pf->mHal.drv) {
        drv = (RsdShader*)pf->mHal.drv;
        if (rsc->props.mLogShaders) {
            ALOGV("Destroying fragment shader with ID %u", drv->getShaderID());
            ALOGV("Destroying fragment shader with ID %u", (uint32_t)pf);
        }
        if (drv->getShaderID()) {
            dc->gl.shaderCache->cleanupFragment(drv->getShaderID());
        if (drv->getStateBasedIDCount()) {
            dc->gl.shaderCache->cleanupFragment(drv);
        }
        delete drv;
    }
+65 −23
Original line number Diff line number Diff line
@@ -46,30 +46,74 @@ RsdShader::RsdShader(const Program *p, uint32_t type,
}

RsdShader::~RsdShader() {
    if (mShaderID) {
        glDeleteShader(mShaderID);
    for (uint32_t i = 0; i < mStateBasedShaders.size(); i ++) {
        StateBasedKey *state = mStateBasedShaders.itemAt(i);
        if (state->mShaderID) {
            glDeleteShader(state->mShaderID);
        }
        delete state;
    }

    delete[] mAttribNames;
    delete[] mUniformNames;
    delete[] mUniformArraySizes;
    delete[] mTextureTargets;
}

void RsdShader::initMemberVars() {
    mDirty = true;
    mShaderID = 0;
    mAttribCount = 0;
    mUniformCount = 0;

    mAttribNames = NULL;
    mUniformNames = NULL;
    mUniformArraySizes = NULL;
    mTextureTargets = NULL;
    mCurrentState = NULL;

    mIsValid = false;
}

RsdShader::StateBasedKey *RsdShader::getExistingState() {
    RsdShader::StateBasedKey *returnKey = NULL;

    for (uint32_t i = 0; i < mStateBasedShaders.size(); i ++) {
        returnKey = mStateBasedShaders.itemAt(i);

        for (uint32_t ct = 0; ct < mRSProgram->mHal.state.texturesCount; ct ++) {
            uint32_t texType = 0;
            if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) {
                Allocation *a = mRSProgram->mHal.state.textures[ct];
                if (a && a->mHal.state.surfaceTextureID) {
                    texType = GL_TEXTURE_EXTERNAL_OES;
                } else {
                    texType = GL_TEXTURE_2D;
                }
            } else {
                texType = GL_TEXTURE_CUBE_MAP;
            }
            if (texType != returnKey->mTextureTargets[ct]) {
                returnKey = NULL;
                break;
            }
        }
    }
    return returnKey;
}

uint32_t RsdShader::getStateBasedShaderID(const Context *rsc) {
    StateBasedKey *state = getExistingState();
    if (state != NULL) {
        mCurrentState = state;
        return mCurrentState->mShaderID;
    }
    // We have not created a shader for this particular state yet
    state = new StateBasedKey(mTextureCount);
    mCurrentState = state;
    mStateBasedShaders.add(state);
    createShader();
    loadShader(rsc);
    return mCurrentState->mShaderID;
}

void RsdShader::init(const char** textureNames, size_t textureNamesCount,
                     const size_t *textureNamesLength) {
    uint32_t attribCount = 0;
@@ -155,14 +199,14 @@ void RsdShader::appendTextures() {
                    appendUsing = false;
                }
                mShader.append("uniform samplerExternalOES UNI_");
                mTextureTargets[ct] = GL_TEXTURE_EXTERNAL_OES;
                mCurrentState->mTextureTargets[ct] = GL_TEXTURE_EXTERNAL_OES;
            } else {
                mShader.append("uniform sampler2D UNI_");
                mTextureTargets[ct] = GL_TEXTURE_2D;
                mCurrentState->mTextureTargets[ct] = GL_TEXTURE_2D;
            }
        } else {
            mShader.append("uniform samplerCube UNI_");
            mTextureTargets[ct] = GL_TEXTURE_CUBE_MAP;
            mCurrentState->mTextureTargets[ct] = GL_TEXTURE_CUBE_MAP;
        }

        mShader.append(mTextureNames[ct]);
@@ -171,6 +215,7 @@ void RsdShader::appendTextures() {
}

bool RsdShader::createShader() {
    mShader.clear();
    if (mType == GL_FRAGMENT_SHADER) {
        mShader.append("precision mediump float;\n");
    }
@@ -183,37 +228,37 @@ bool RsdShader::createShader() {
}

bool RsdShader::loadShader(const Context *rsc) {
    mShaderID = glCreateShader(mType);
    rsAssert(mShaderID);
    mCurrentState->mShaderID = glCreateShader(mType);
    rsAssert(mCurrentState->mShaderID);

    if(!mShader.length()) {
        createShader();
    }

    if (rsc->props.mLogShaders) {
        ALOGV("Loading shader type %x, ID %i", mType, mShaderID);
        ALOGV("Loading shader type %x, ID %i", mType, mCurrentState->mShaderID);
        ALOGV("%s", mShader.string());
    }

    if (mShaderID) {
    if (mCurrentState->mShaderID) {
        const char * ss = mShader.string();
        RSD_CALL_GL(glShaderSource, mShaderID, 1, &ss, NULL);
        RSD_CALL_GL(glCompileShader, mShaderID);
        RSD_CALL_GL(glShaderSource, mCurrentState->mShaderID, 1, &ss, NULL);
        RSD_CALL_GL(glCompileShader, mCurrentState->mShaderID);

        GLint compiled = 0;
        RSD_CALL_GL(glGetShaderiv, mShaderID, GL_COMPILE_STATUS, &compiled);
        RSD_CALL_GL(glGetShaderiv, mCurrentState->mShaderID, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLint infoLen = 0;
            RSD_CALL_GL(glGetShaderiv, mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
            RSD_CALL_GL(glGetShaderiv, mCurrentState->mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen) {
                char* buf = (char*) malloc(infoLen);
                if (buf) {
                    RSD_CALL_GL(glGetShaderInfoLog, mShaderID, infoLen, NULL, buf);
                    RSD_CALL_GL(glGetShaderInfoLog, mCurrentState->mShaderID, infoLen, NULL, buf);
                    rsc->setError(RS_ERROR_FATAL_PROGRAM_LINK, buf);
                    free(buf);
                }
                RSD_CALL_GL(glDeleteShader, mShaderID);
                mShaderID = 0;
                RSD_CALL_GL(glDeleteShader, mCurrentState->mShaderID);
                mCurrentState->mShaderID = 0;
                return false;
            }
        }
@@ -430,7 +475,7 @@ void RsdShader::setupTextures(const Context *rsc, RsdShaderCache *sc) {

        if (!mRSProgram->mHal.state.textures[ct]) {
            // if nothing is bound, reset to default GL texture
            RSD_CALL_GL(glBindTexture, mTextureTargets[ct], 0);
            RSD_CALL_GL(glBindTexture, mCurrentState->mTextureTargets[ct], 0);
            continue;
        }

@@ -537,9 +582,6 @@ void RsdShader::initAttribAndUniformArray() {
    }

    mTextureCount = mRSProgram->mHal.state.texturesCount;
    if (mTextureCount) {
        mTextureTargets = new uint32_t[mTextureCount];
    }
}

void RsdShader::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths,
+24 −4
Original line number Diff line number Diff line
@@ -44,9 +44,13 @@ public:
              const size_t *textureNamesLength);
    virtual ~RsdShader();

    bool createShader();
    uint32_t getStateBasedShaderID(const android::renderscript::Context *);

    uint32_t getShaderID() const {return mShaderID;}
    // Add ability to get all ID's to clean up the cached program objects
    uint32_t getStateBasedIDCount() const { return mStateBasedShaders.size(); }
    uint32_t getStateBasedID(uint32_t index) const {
        return mStateBasedShaders.itemAt(index)->mShaderID;
    }

    uint32_t getAttribCount() const {return mAttribCount;}
    uint32_t getUniformCount() const {return mUniformCount;}
@@ -64,6 +68,21 @@ public:

protected:

    class StateBasedKey {
    public:
        StateBasedKey(uint32_t texCount) : mShaderID(0) {
            mTextureTargets = new uint32_t[texCount];
        }
        ~StateBasedKey() {
            delete[] mTextureTargets;
        }
        uint32_t mShaderID;
        uint32_t *mTextureTargets;
    };

    bool createShader();
    StateBasedKey *getExistingState();

    const android::renderscript::Program *mRSProgram;
    bool mIsValid;

@@ -87,11 +106,10 @@ protected:
    mutable bool mDirty;
    android::String8 mShader;
    android::String8 mUserShader;
    uint32_t mShaderID;
    uint32_t mType;

    uint32_t mTextureCount;
    uint32_t *mTextureTargets;
    StateBasedKey *mCurrentState;
    uint32_t mAttribCount;
    uint32_t mUniformCount;
    android::String8 *mAttribNames;
@@ -100,6 +118,8 @@ protected:

    android::Vector<android::String8> mTextureNames;

    android::Vector<StateBasedKey*> mStateBasedShaders;

    int32_t mTextureUniformIndexStart;

    void logUniform(const android::renderscript::Element *field,
+35 −31
Original line number Diff line number Diff line
@@ -108,21 +108,17 @@ bool RsdShaderCache::link(const Context *rsc) {

    RsdShader *vtx = mVertex;
    RsdShader *frag = mFragment;
    if (!vtx->getShaderID()) {
        vtx->loadShader(rsc);
    }
    if (!frag->getShaderID()) {
        frag->loadShader(rsc);
    }

    uint32_t vID = vtx->getStateBasedShaderID(rsc);
    uint32_t fID = frag->getStateBasedShaderID(rsc);

    // Don't try to cache if shaders failed to load
    if (!vtx->getShaderID() || !frag->getShaderID()) {
    if (!vID || !fID) {
        return false;
    }
    uint32_t entryCount = mEntries.size();
    for (uint32_t ct = 0; ct < entryCount; ct ++) {
        if ((mEntries[ct]->vtx == vtx->getShaderID()) &&
            (mEntries[ct]->frag == frag->getShaderID())) {
        if ((mEntries[ct]->vtx == vID) && (mEntries[ct]->frag == fID)) {

            //ALOGV("SC using program %i", mEntries[ct]->program);
            glUseProgram(mEntries[ct]->program);
@@ -138,14 +134,14 @@ bool RsdShaderCache::link(const Context *rsc) {
                                       frag->getUniformCount());
    mEntries.push(e);
    mCurrent = e;
    e->vtx = vtx->getShaderID();
    e->frag = frag->getShaderID();
    e->vtx = vID;
    e->frag = fID;
    e->program = glCreateProgram();
    if (e->program) {
        GLuint pgm = e->program;
        glAttachShader(pgm, vtx->getShaderID());
        glAttachShader(pgm, vID);
        //ALOGE("e1 %x", glGetError());
        glAttachShader(pgm, frag->getShaderID());
        glAttachShader(pgm, fID);

        glBindAttribLocation(pgm, 0, "ATTRIB_position");
        glBindAttribLocation(pgm, 1, "ATTRIB_color");
@@ -241,8 +237,11 @@ int32_t RsdShaderCache::vtxAttribSlot(const String8 &attrName) const {
    return -1;
}

void RsdShaderCache::cleanupVertex(uint32_t id) {
void RsdShaderCache::cleanupVertex(RsdShader *s) {
    int32_t numEntries = (int32_t)mEntries.size();
    uint32_t numShaderIDs = s->getStateBasedIDCount();
    for (uint32_t sId = 0; sId < numShaderIDs; sId ++) {
        uint32_t id = s->getStateBasedID(sId);
        for (int32_t ct = 0; ct < numEntries; ct ++) {
            if (mEntries[ct]->vtx == id) {
                glDeleteProgram(mEntries[ct]->program);
@@ -254,9 +253,13 @@ void RsdShaderCache::cleanupVertex(uint32_t id) {
            }
        }
    }
}

void RsdShaderCache::cleanupFragment(uint32_t id) {
void RsdShaderCache::cleanupFragment(RsdShader *s) {
    int32_t numEntries = (int32_t)mEntries.size();
    uint32_t numShaderIDs = s->getStateBasedIDCount();
    for (uint32_t sId = 0; sId < numShaderIDs; sId ++) {
        uint32_t id = s->getStateBasedID(sId);
        for (int32_t ct = 0; ct < numEntries; ct ++) {
            if (mEntries[ct]->frag == id) {
                glDeleteProgram(mEntries[ct]->program);
@@ -268,6 +271,7 @@ void RsdShaderCache::cleanupFragment(uint32_t id) {
            }
        }
    }
}

void RsdShaderCache::cleanupAll() {
    for (uint32_t ct=0; ct < mEntries.size(); ct++) {
+2 −2
Original line number Diff line number Diff line
@@ -49,8 +49,8 @@ public:

    bool setup(const android::renderscript::Context *rsc);

    void cleanupVertex(uint32_t id);
    void cleanupFragment(uint32_t id);
    void cleanupVertex(RsdShader *s);
    void cleanupFragment(RsdShader *s);

    void cleanupAll();