diff options
Diffstat (limited to 'libs/rs/rsProgram.cpp')
-rw-r--r-- | libs/rs/rsProgram.cpp | 229 |
1 files changed, 215 insertions, 14 deletions
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp index 70e2868..10e00e6 100644 --- a/libs/rs/rsProgram.cpp +++ b/libs/rs/rsProgram.cpp @@ -14,16 +14,21 @@ * limitations under the License. */ +#ifndef ANDROID_RS_BUILD_FOR_HOST #include "rsContext.h" -#include "rsProgram.h" - #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +#else +#include "rsContextHostStub.h" +#include <OpenGL/gl.h> +#include <OpenGL/glext.h> +#endif //ANDROID_RS_BUILD_FOR_HOST + +#include "rsProgram.h" using namespace android; using namespace android::renderscript; - Program::Program(Context *rsc) : ObjectBase(rsc) { mAllocFile = __FILE__; @@ -32,7 +37,10 @@ Program::Program(Context *rsc) : ObjectBase(rsc) mShaderID = 0; mAttribCount = 0; mUniformCount = 0; + mTextureCount = 0; + mTextures = NULL; + mSamplers = NULL; mInputElements = NULL; mOutputElements = NULL; mConstantTypes = NULL; @@ -40,6 +48,7 @@ Program::Program(Context *rsc) : ObjectBase(rsc) mOutputCount = 0; mConstantCount = 0; mIsValid = false; + mIsInternal = false; } Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength, @@ -73,6 +82,8 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength, } } + mTextures = new ObjectBaseRef<Allocation>[mTextureCount]; + mSamplers = new ObjectBaseRef<Sampler>[mTextureCount]; mInputElements = new ObjectBaseRef<Element>[mInputCount]; mOutputElements = new ObjectBaseRef<Element>[mOutputCount]; mConstantTypes = new ObjectBaseRef<Type>[mConstantCount]; @@ -91,15 +102,37 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength, mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1])); } } + mIsInternal = false; + uint32_t internalTokenLen = strlen(RS_SHADER_INTERNAL); + if(shaderLength > internalTokenLen && + strncmp(RS_SHADER_INTERNAL, shaderText, internalTokenLen) == 0) { + mIsInternal = true; + shaderText += internalTokenLen; + shaderLength -= internalTokenLen; + } mUserShader.setTo(shaderText, shaderLength); } Program::~Program() { + if(mRSC->props.mLogShaders) { + LOGV("Program::~Program with shader id %u", mShaderID); + } + + if(mShaderID) { + glDeleteShader(mShaderID); + } + for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) { - bindAllocation(NULL, ct); + bindAllocation(NULL, NULL, ct); } + for (uint32_t ct=0; ct < mTextureCount; ct++) { + bindTexture(NULL, ct, NULL); + bindSampler(NULL, ct, NULL); + } + delete[] mTextures; + delete[] mSamplers; delete[] mInputElements; delete[] mOutputElements; delete[] mConstantTypes; @@ -109,8 +142,22 @@ Program::~Program() } -void Program::bindAllocation(Allocation *alloc, uint32_t slot) +void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot) { + if (alloc != NULL) { + if (slot >= mConstantCount) { + LOGE("Attempt to bind alloc at slot %u, on shader id %u, but const count is %u", + slot, (uint32_t)this, mConstantCount); + rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation"); + return; + } + if (!alloc->getType()->isEqual(mConstantTypes[slot].get())) { + LOGE("Attempt to bind alloc at slot %u, on shader id %u, but types mismatch", + slot, (uint32_t)this); + rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation"); + return; + } + } if (mConstants[slot].get() == alloc) { return; } @@ -124,10 +171,11 @@ void Program::bindAllocation(Allocation *alloc, uint32_t slot) mDirty = true; } -void Program::bindTexture(uint32_t slot, Allocation *a) +void Program::bindTexture(Context *rsc, uint32_t slot, Allocation *a) { - if (slot >= MAX_TEXTURE) { - LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE"); + if (slot >= mTextureCount) { + LOGE("Attempt to bind texture to slot %u but tex count is %u", slot, mTextureCount); + rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind texture"); return; } @@ -136,10 +184,11 @@ void Program::bindTexture(uint32_t slot, Allocation *a) mDirty = true; } -void Program::bindSampler(uint32_t slot, Sampler *s) +void Program::bindSampler(Context *rsc, uint32_t slot, Sampler *s) { - if (slot >= MAX_TEXTURE) { - LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE"); + if (slot >= mTextureCount) { + LOGE("Attempt to bind sampler to slot %u but tex count is %u", slot, mTextureCount); + rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind sampler"); return; } @@ -235,7 +284,159 @@ void Program::setShader(const char *txt, uint32_t len) mUserShader.setTo(txt, len); } +void Program::appendUserConstants() { + for (uint32_t ct=0; ct < mConstantCount; ct++) { + const Element *e = mConstantTypes[ct]->getElement(); + for (uint32_t field=0; field < e->getFieldCount(); field++) { + const Element *f = e->getField(field); + const char *fn = e->getFieldName(field); + + if (fn[0] == '#') { + continue; + } + + // Cannot be complex + rsAssert(!f->getFieldCount()); + if(f->getType() == RS_TYPE_MATRIX_4X4) { + mShader.append("uniform mat4 UNI_"); + } + else if(f->getType() == RS_TYPE_MATRIX_3X3) { + mShader.append("uniform mat3 UNI_"); + } + else if(f->getType() == RS_TYPE_MATRIX_2X2) { + mShader.append("uniform mat2 UNI_"); + } + else { + switch(f->getComponent().getVectorSize()) { + case 1: mShader.append("uniform float UNI_"); break; + case 2: mShader.append("uniform vec2 UNI_"); break; + case 3: mShader.append("uniform vec3 UNI_"); break; + case 4: mShader.append("uniform vec4 UNI_"); break; + default: + rsAssert(0); + } + } + + mShader.append(fn); + mShader.append(";\n"); + } + } +} + +void Program::setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment) { + uint32_t uidx = 0; + for (uint32_t ct=0; ct < mConstantCount; ct++) { + Allocation *alloc = mConstants[ct].get(); + if (!alloc) { + LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set", (uint32_t)this, ct); + rsc->setError(RS_ERROR_BAD_SHADER, "No constant allocation bound"); + continue; + } + + const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr()); + const Element *e = mConstantTypes[ct]->getElement(); + for (uint32_t field=0; field < e->getFieldCount(); field++) { + const Element *f = e->getField(field); + const char *fieldName = e->getFieldName(field); + // If this field is padding, skip it + if(fieldName[0] == '#') { + continue; + } + + uint32_t offset = e->getFieldOffsetBytes(field); + const float *fd = reinterpret_cast<const float *>(&data[offset]); + + int32_t slot = -1; + if(!isFragment) { + slot = sc->vtxUniformSlot(uidx); + } + else { + slot = sc->fragUniformSlot(uidx); + } + + if(rsc->props.mLogShadersUniforms) { + LOGV("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName); + } + if (slot >= 0) { + if(f->getType() == RS_TYPE_MATRIX_4X4) { + if(rsc->props.mLogShadersUniforms) { + LOGV("Matrix4x4"); + LOGV("{%f, %f, %f, %f", fd[0], fd[4], fd[8], fd[12]); + LOGV(" %f, %f, %f, %f", fd[1], fd[5], fd[9], fd[13]); + LOGV(" %f, %f, %f, %f", fd[2], fd[6], fd[10], fd[14]); + LOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]); + } + glUniformMatrix4fv(slot, 1, GL_FALSE, fd); + } + else if(f->getType() == RS_TYPE_MATRIX_3X3) { + if(rsc->props.mLogShadersUniforms) { + LOGV("Matrix3x3"); + LOGV("{%f, %f, %f", fd[0], fd[3], fd[6]); + LOGV(" %f, %f, %f", fd[1], fd[4], fd[7]); + LOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]); + } + glUniformMatrix3fv(slot, 1, GL_FALSE, fd); + } + else if(f->getType() == RS_TYPE_MATRIX_2X2) { + if(rsc->props.mLogShadersUniforms){ + LOGV("Matrix2x2"); + LOGV("{%f, %f", fd[0], fd[2]); + LOGV(" %f, %f}", fd[1], fd[3]); + } + glUniformMatrix2fv(slot, 1, GL_FALSE, fd); + } + else { + switch(f->getComponent().getVectorSize()) { + case 1: + if(rsc->props.mLogShadersUniforms) { + LOGV("Uniform 1 = %f", fd[0]); + } + glUniform1fv(slot, 1, fd); + break; + case 2: + if(rsc->props.mLogShadersUniforms) { + LOGV("Uniform 2 = %f %f", fd[0], fd[1]); + } + glUniform2fv(slot, 1, fd); + break; + case 3: + if(rsc->props.mLogShadersUniforms) { + LOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]); + } + glUniform3fv(slot, 1, fd); + break; + case 4: + if(rsc->props.mLogShadersUniforms) { + LOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]); + } + glUniform4fv(slot, 1, fd); + break; + default: + rsAssert(0); + } + } + } + uidx ++; + } + } +} +void Program::initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix) +{ + rsAssert(e->getFieldCount()); + for (uint32_t ct=0; ct < e->getFieldCount(); ct++) { + const Element *ce = e->getField(ct); + if (ce->getFieldCount()) { + initAddUserElement(ce, names, count, prefix); + } + else if(e->getFieldName(ct)[0] != '#') { + String8 tmp(prefix); + tmp.append(e->getFieldName(ct)); + names[*count].setTo(tmp.string()); + (*count)++; + } + } +} namespace android { namespace renderscript { @@ -244,19 +445,19 @@ namespace renderscript { void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants) { Program *p = static_cast<Program *>(vp); - p->bindAllocation(static_cast<Allocation *>(constants), slot); + p->bindAllocation(rsc, static_cast<Allocation *>(constants), slot); } void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a) { Program *p = static_cast<Program *>(vpf); - p->bindTexture(slot, static_cast<Allocation *>(a)); + p->bindTexture(rsc, slot, static_cast<Allocation *>(a)); } void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s) { Program *p = static_cast<Program *>(vpf); - p->bindSampler(slot, static_cast<Sampler *>(s)); + p->bindSampler(rsc, slot, static_cast<Sampler *>(s)); } } |