State based shader recompile to support camera input.
Change-Id: Ia6c362571e1b44254461522a8c49a8551b46f28d
diff --git a/driver/rsdProgram.cpp b/driver/rsdProgram.cpp
index 30a4c5f..a96a5f9 100644
--- a/driver/rsdProgram.cpp
+++ b/driver/rsdProgram.cpp
@@ -71,10 +71,10 @@
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 @@
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;
}
diff --git a/driver/rsdShader.cpp b/driver/rsdShader.cpp
index a386735..6d9fa90 100644
--- a/driver/rsdShader.cpp
+++ b/driver/rsdShader.cpp
@@ -46,30 +46,74 @@
}
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 @@
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 @@
}
bool RsdShader::createShader() {
+ mShader.clear();
if (mType == GL_FRAGMENT_SHADER) {
mShader.append("precision mediump float;\n");
}
@@ -183,37 +228,37 @@
}
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 @@
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 @@
}
mTextureCount = mRSProgram->mHal.state.texturesCount;
- if (mTextureCount) {
- mTextureTargets = new uint32_t[mTextureCount];
- }
}
void RsdShader::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths,
diff --git a/driver/rsdShader.h b/driver/rsdShader.h
index 6c0b616..2680b3e 100644
--- a/driver/rsdShader.h
+++ b/driver/rsdShader.h
@@ -44,9 +44,13 @@
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 @@
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 @@
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 @@
android::Vector<android::String8> mTextureNames;
+ android::Vector<StateBasedKey*> mStateBasedShaders;
+
int32_t mTextureUniformIndexStart;
void logUniform(const android::renderscript::Element *field,
diff --git a/driver/rsdShaderCache.cpp b/driver/rsdShaderCache.cpp
index 50cb9f9..69b43fc 100644
--- a/driver/rsdShaderCache.cpp
+++ b/driver/rsdShaderCache.cpp
@@ -108,21 +108,17 @@
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 @@
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 @@
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 --;
+ }
}
}
}
diff --git a/driver/rsdShaderCache.h b/driver/rsdShaderCache.h
index 1192916..88aa32d 100644
--- a/driver/rsdShaderCache.h
+++ b/driver/rsdShaderCache.h
@@ -49,8 +49,8 @@
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();