Merge "State based shader recompile to support camera input."
This commit is contained in:
committed by
Android (Google) Code Review
commit
c72cb1c2e0
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 --;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user