Merge "State based shader recompile to support camera input."

This commit is contained in:
Alex Sakhartchouk
2012-03-27 08:49:52 -07:00
committed by Android (Google) Code Review
5 changed files with 130 additions and 64 deletions

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,30 +237,38 @@ 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();
for (int32_t ct = 0; ct < numEntries; ct ++) {
if (mEntries[ct]->vtx == id) {
glDeleteProgram(mEntries[ct]->program);
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);
delete mEntries[ct];
mEntries.removeAt(ct);
numEntries = (int32_t)mEntries.size();
ct --;
delete mEntries[ct];
mEntries.removeAt(ct);
numEntries = (int32_t)mEntries.size();
ct --;
}
}
}
}
void RsdShaderCache::cleanupFragment(uint32_t id) {
void RsdShaderCache::cleanupFragment(RsdShader *s) {
int32_t numEntries = (int32_t)mEntries.size();
for (int32_t ct = 0; ct < numEntries; ct ++) {
if (mEntries[ct]->frag == id) {
glDeleteProgram(mEntries[ct]->program);
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);
delete mEntries[ct];
mEntries.removeAt(ct);
numEntries = (int32_t)mEntries.size();
ct --;
delete mEntries[ct];
mEntries.removeAt(ct);
numEntries = (int32_t)mEntries.size();
ct --;
}
}
}
}

View File

@@ -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();