Home | History | Annotate | Download | only in driver
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <GLES2/gl2.h>
     18 #include <GLES2/gl2ext.h>
     19 
     20 #include <rs_hal.h>
     21 #include <rsContext.h>
     22 #include <rsProgram.h>
     23 
     24 #include "rsdCore.h"
     25 #include "rsdAllocation.h"
     26 #include "rsdShader.h"
     27 #include "rsdShaderCache.h"
     28 
     29 using namespace android;
     30 using namespace android::renderscript;
     31 
     32 RsdShader::RsdShader(const Program *p, uint32_t type,
     33                        const char * shaderText, uint32_t shaderLength) {
     34 
     35     mUserShader.setTo(shaderText, shaderLength);
     36     mRSProgram = p;
     37     mType = type;
     38     initMemberVars();
     39     initAttribAndUniformArray();
     40     init();
     41 }
     42 
     43 RsdShader::~RsdShader() {
     44     if (mShaderID) {
     45         glDeleteShader(mShaderID);
     46     }
     47 
     48     delete[] mAttribNames;
     49     delete[] mUniformNames;
     50     delete[] mUniformArraySizes;
     51     delete[] mTextureTargets;
     52 }
     53 
     54 void RsdShader::initMemberVars() {
     55     mDirty = true;
     56     mShaderID = 0;
     57     mAttribCount = 0;
     58     mUniformCount = 0;
     59 
     60     mAttribNames = NULL;
     61     mUniformNames = NULL;
     62     mUniformArraySizes = NULL;
     63     mTextureTargets = NULL;
     64 
     65     mIsValid = false;
     66 }
     67 
     68 void RsdShader::init() {
     69     uint32_t attribCount = 0;
     70     uint32_t uniformCount = 0;
     71     for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
     72         initAddUserElement(mRSProgram->mHal.state.inputElements[ct], mAttribNames, NULL, &attribCount, RS_SHADER_ATTR);
     73     }
     74     for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
     75         initAddUserElement(mRSProgram->mHal.state.constantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
     76     }
     77 
     78     mTextureUniformIndexStart = uniformCount;
     79     char buf[256];
     80     for (uint32_t ct=0; ct < mRSProgram->mHal.state.texturesCount; ct++) {
     81         snprintf(buf, sizeof(buf), "UNI_Tex%i", ct);
     82         mUniformNames[uniformCount].setTo(buf);
     83         mUniformArraySizes[uniformCount] = 1;
     84         uniformCount++;
     85     }
     86 
     87 }
     88 
     89 String8 RsdShader::getGLSLInputString() const {
     90     String8 s;
     91     for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
     92         const Element *e = mRSProgram->mHal.state.inputElements[ct];
     93         for (uint32_t field=0; field < e->getFieldCount(); field++) {
     94             const Element *f = e->getField(field);
     95 
     96             // Cannot be complex
     97             rsAssert(!f->getFieldCount());
     98             switch (f->getComponent().getVectorSize()) {
     99             case 1: s.append("attribute float ATTRIB_"); break;
    100             case 2: s.append("attribute vec2 ATTRIB_"); break;
    101             case 3: s.append("attribute vec3 ATTRIB_"); break;
    102             case 4: s.append("attribute vec4 ATTRIB_"); break;
    103             default:
    104                 rsAssert(0);
    105             }
    106 
    107             s.append(e->getFieldName(field));
    108             s.append(";\n");
    109         }
    110     }
    111     return s;
    112 }
    113 
    114 void RsdShader::appendAttributes() {
    115     for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
    116         const Element *e = mRSProgram->mHal.state.inputElements[ct];
    117         for (uint32_t field=0; field < e->getFieldCount(); field++) {
    118             const Element *f = e->getField(field);
    119             const char *fn = e->getFieldName(field);
    120 
    121             if (fn[0] == '#') {
    122                 continue;
    123             }
    124 
    125             // Cannot be complex
    126             rsAssert(!f->getFieldCount());
    127             switch (f->getComponent().getVectorSize()) {
    128             case 1: mShader.append("attribute float ATTRIB_"); break;
    129             case 2: mShader.append("attribute vec2 ATTRIB_"); break;
    130             case 3: mShader.append("attribute vec3 ATTRIB_"); break;
    131             case 4: mShader.append("attribute vec4 ATTRIB_"); break;
    132             default:
    133                 rsAssert(0);
    134             }
    135 
    136             mShader.append(fn);
    137             mShader.append(";\n");
    138         }
    139     }
    140 }
    141 
    142 void RsdShader::appendTextures() {
    143     char buf[256];
    144     for (uint32_t ct=0; ct < mRSProgram->mHal.state.texturesCount; ct++) {
    145         if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) {
    146             snprintf(buf, sizeof(buf), "uniform sampler2D UNI_Tex%i;\n", ct);
    147             mTextureTargets[ct] = GL_TEXTURE_2D;
    148         } else {
    149             snprintf(buf, sizeof(buf), "uniform samplerCube UNI_Tex%i;\n", ct);
    150             mTextureTargets[ct] = GL_TEXTURE_CUBE_MAP;
    151         }
    152         mShader.append(buf);
    153     }
    154 }
    155 
    156 bool RsdShader::createShader() {
    157 
    158     if (mType == GL_FRAGMENT_SHADER) {
    159         mShader.append("precision mediump float;\n");
    160     }
    161     appendUserConstants();
    162     appendAttributes();
    163     appendTextures();
    164 
    165     mShader.append(mUserShader);
    166 
    167     return true;
    168 }
    169 
    170 bool RsdShader::loadShader(const Context *rsc) {
    171     mShaderID = glCreateShader(mType);
    172     rsAssert(mShaderID);
    173 
    174     if (rsc->props.mLogShaders) {
    175         LOGV("Loading shader type %x, ID %i", mType, mShaderID);
    176         LOGV("%s", mShader.string());
    177     }
    178 
    179     if (mShaderID) {
    180         const char * ss = mShader.string();
    181         RSD_CALL_GL(glShaderSource, mShaderID, 1, &ss, NULL);
    182         RSD_CALL_GL(glCompileShader, mShaderID);
    183 
    184         GLint compiled = 0;
    185         RSD_CALL_GL(glGetShaderiv, mShaderID, GL_COMPILE_STATUS, &compiled);
    186         if (!compiled) {
    187             GLint infoLen = 0;
    188             RSD_CALL_GL(glGetShaderiv, mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
    189             if (infoLen) {
    190                 char* buf = (char*) malloc(infoLen);
    191                 if (buf) {
    192                     RSD_CALL_GL(glGetShaderInfoLog, mShaderID, infoLen, NULL, buf);
    193                     LOGE("Could not compile shader \n%s\n", buf);
    194                     free(buf);
    195                 }
    196                 RSD_CALL_GL(glDeleteShader, mShaderID);
    197                 mShaderID = 0;
    198                 rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
    199                 return false;
    200             }
    201         }
    202     }
    203 
    204     if (rsc->props.mLogShaders) {
    205         LOGV("--Shader load result %x ", glGetError());
    206     }
    207     mIsValid = true;
    208     return true;
    209 }
    210 
    211 void RsdShader::appendUserConstants() {
    212     for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
    213         const Element *e = mRSProgram->mHal.state.constantTypes[ct]->getElement();
    214         for (uint32_t field=0; field < e->getFieldCount(); field++) {
    215             const Element *f = e->getField(field);
    216             const char *fn = e->getFieldName(field);
    217 
    218             if (fn[0] == '#') {
    219                 continue;
    220             }
    221 
    222             // Cannot be complex
    223             rsAssert(!f->getFieldCount());
    224             if (f->getType() == RS_TYPE_MATRIX_4X4) {
    225                 mShader.append("uniform mat4 UNI_");
    226             } else if (f->getType() == RS_TYPE_MATRIX_3X3) {
    227                 mShader.append("uniform mat3 UNI_");
    228             } else if (f->getType() == RS_TYPE_MATRIX_2X2) {
    229                 mShader.append("uniform mat2 UNI_");
    230             } else {
    231                 switch (f->getComponent().getVectorSize()) {
    232                 case 1: mShader.append("uniform float UNI_"); break;
    233                 case 2: mShader.append("uniform vec2 UNI_"); break;
    234                 case 3: mShader.append("uniform vec3 UNI_"); break;
    235                 case 4: mShader.append("uniform vec4 UNI_"); break;
    236                 default:
    237                     rsAssert(0);
    238                 }
    239             }
    240 
    241             mShader.append(fn);
    242             if (e->getFieldArraySize(field) > 1) {
    243                 mShader.appendFormat("[%d]", e->getFieldArraySize(field));
    244             }
    245             mShader.append(";\n");
    246         }
    247     }
    248 }
    249 
    250 void RsdShader::logUniform(const Element *field, const float *fd, uint32_t arraySize ) {
    251     RsDataType dataType = field->getType();
    252     uint32_t elementSize = field->getSizeBytes() / sizeof(float);
    253     for (uint32_t i = 0; i < arraySize; i ++) {
    254         if (arraySize > 1) {
    255             LOGV("Array Element [%u]", i);
    256         }
    257         if (dataType == RS_TYPE_MATRIX_4X4) {
    258             LOGV("Matrix4x4");
    259             LOGV("{%f, %f, %f, %f",  fd[0], fd[4], fd[8], fd[12]);
    260             LOGV(" %f, %f, %f, %f",  fd[1], fd[5], fd[9], fd[13]);
    261             LOGV(" %f, %f, %f, %f",  fd[2], fd[6], fd[10], fd[14]);
    262             LOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]);
    263         } else if (dataType == RS_TYPE_MATRIX_3X3) {
    264             LOGV("Matrix3x3");
    265             LOGV("{%f, %f, %f",  fd[0], fd[3], fd[6]);
    266             LOGV(" %f, %f, %f",  fd[1], fd[4], fd[7]);
    267             LOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]);
    268         } else if (dataType == RS_TYPE_MATRIX_2X2) {
    269             LOGV("Matrix2x2");
    270             LOGV("{%f, %f",  fd[0], fd[2]);
    271             LOGV(" %f, %f}", fd[1], fd[3]);
    272         } else {
    273             switch (field->getComponent().getVectorSize()) {
    274             case 1:
    275                 LOGV("Uniform 1 = %f", fd[0]);
    276                 break;
    277             case 2:
    278                 LOGV("Uniform 2 = %f %f", fd[0], fd[1]);
    279                 break;
    280             case 3:
    281                 LOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
    282                 break;
    283             case 4:
    284                 LOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
    285                 break;
    286             default:
    287                 rsAssert(0);
    288             }
    289         }
    290         LOGE("Element size %u data=%p", elementSize, fd);
    291         fd += elementSize;
    292         LOGE("New data=%p", fd);
    293     }
    294 }
    295 
    296 void RsdShader::setUniform(const Context *rsc, const Element *field, const float *fd,
    297                          int32_t slot, uint32_t arraySize ) {
    298     RsDataType dataType = field->getType();
    299     if (dataType == RS_TYPE_MATRIX_4X4) {
    300         RSD_CALL_GL(glUniformMatrix4fv, slot, arraySize, GL_FALSE, fd);
    301     } else if (dataType == RS_TYPE_MATRIX_3X3) {
    302         RSD_CALL_GL(glUniformMatrix3fv, slot, arraySize, GL_FALSE, fd);
    303     } else if (dataType == RS_TYPE_MATRIX_2X2) {
    304         RSD_CALL_GL(glUniformMatrix2fv, slot, arraySize, GL_FALSE, fd);
    305     } else {
    306         switch (field->getComponent().getVectorSize()) {
    307         case 1:
    308             RSD_CALL_GL(glUniform1fv, slot, arraySize, fd);
    309             break;
    310         case 2:
    311             RSD_CALL_GL(glUniform2fv, slot, arraySize, fd);
    312             break;
    313         case 3:
    314             RSD_CALL_GL(glUniform3fv, slot, arraySize, fd);
    315             break;
    316         case 4:
    317             RSD_CALL_GL(glUniform4fv, slot, arraySize, fd);
    318             break;
    319         default:
    320             rsAssert(0);
    321         }
    322     }
    323 }
    324 
    325 void RsdShader::setupSampler(const Context *rsc, const Sampler *s, const Allocation *tex) {
    326     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    327 
    328     GLenum trans[] = {
    329         GL_NEAREST, //RS_SAMPLER_NEAREST,
    330         GL_LINEAR, //RS_SAMPLER_LINEAR,
    331         GL_LINEAR_MIPMAP_LINEAR, //RS_SAMPLER_LINEAR_MIP_LINEAR,
    332         GL_REPEAT, //RS_SAMPLER_WRAP,
    333         GL_CLAMP_TO_EDGE, //RS_SAMPLER_CLAMP
    334         GL_LINEAR_MIPMAP_NEAREST, //RS_SAMPLER_LINEAR_MIP_NEAREST
    335     };
    336 
    337     GLenum transNP[] = {
    338         GL_NEAREST, //RS_SAMPLER_NEAREST,
    339         GL_LINEAR, //RS_SAMPLER_LINEAR,
    340         GL_LINEAR, //RS_SAMPLER_LINEAR_MIP_LINEAR,
    341         GL_CLAMP_TO_EDGE, //RS_SAMPLER_WRAP,
    342         GL_CLAMP_TO_EDGE, //RS_SAMPLER_CLAMP
    343         GL_LINEAR, //RS_SAMPLER_LINEAR_MIP_NEAREST,
    344     };
    345 
    346     // This tells us the correct texture type
    347     DrvAllocation *drvTex = (DrvAllocation *)tex->mHal.drv;
    348     const GLenum target = drvTex->glTarget;
    349 
    350     if (!dc->gl.gl.OES_texture_npot && tex->getType()->getIsNp2()) {
    351         if (tex->getHasGraphicsMipmaps() &&
    352             (dc->gl.gl.GL_NV_texture_npot_2D_mipmap || dc->gl.gl.GL_IMG_texture_npot)) {
    353             if (dc->gl.gl.GL_NV_texture_npot_2D_mipmap) {
    354                 RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
    355                             trans[s->mHal.state.minFilter]);
    356             } else {
    357                 switch (trans[s->mHal.state.minFilter]) {
    358                 case GL_LINEAR_MIPMAP_LINEAR:
    359                     RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
    360                                 GL_LINEAR_MIPMAP_NEAREST);
    361                     break;
    362                 default:
    363                     RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
    364                                 trans[s->mHal.state.minFilter]);
    365                     break;
    366                 }
    367             }
    368         } else {
    369             RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
    370                         transNP[s->mHal.state.minFilter]);
    371         }
    372         RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MAG_FILTER,
    373                     transNP[s->mHal.state.magFilter]);
    374         RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_S, transNP[s->mHal.state.wrapS]);
    375         RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_T, transNP[s->mHal.state.wrapT]);
    376     } else {
    377         if (tex->getHasGraphicsMipmaps()) {
    378             RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
    379                         trans[s->mHal.state.minFilter]);
    380         } else {
    381             RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
    382                         transNP[s->mHal.state.minFilter]);
    383         }
    384         RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MAG_FILTER, trans[s->mHal.state.magFilter]);
    385         RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_S, trans[s->mHal.state.wrapS]);
    386         RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_T, trans[s->mHal.state.wrapT]);
    387     }
    388 
    389     float anisoValue = rsMin(dc->gl.gl.EXT_texture_max_aniso, s->mHal.state.aniso);
    390     if (dc->gl.gl.EXT_texture_max_aniso > 1.0f) {
    391         RSD_CALL_GL(glTexParameterf, target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoValue);
    392     }
    393 
    394     rsdGLCheckError(rsc, "Sampler::setup tex env");
    395 }
    396 
    397 void RsdShader::setupTextures(const Context *rsc, RsdShaderCache *sc) {
    398     if (mRSProgram->mHal.state.texturesCount == 0) {
    399         return;
    400     }
    401 
    402     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    403 
    404     uint32_t numTexturesToBind = mRSProgram->mHal.state.texturesCount;
    405     uint32_t numTexturesAvailable = dc->gl.gl.maxFragmentTextureImageUnits;
    406     if (numTexturesToBind >= numTexturesAvailable) {
    407         LOGE("Attempting to bind %u textures on shader id %u, but only %u are available",
    408              mRSProgram->mHal.state.texturesCount, (uint32_t)this, numTexturesAvailable);
    409         rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind more textuers than available");
    410         numTexturesToBind = numTexturesAvailable;
    411     }
    412 
    413     for (uint32_t ct=0; ct < numTexturesToBind; ct++) {
    414         RSD_CALL_GL(glActiveTexture, GL_TEXTURE0 + ct);
    415         RSD_CALL_GL(glUniform1i, sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct);
    416 
    417         if (!mRSProgram->mHal.state.textures[ct]) {
    418             // if nothing is bound, reset to default GL texture
    419             RSD_CALL_GL(glBindTexture, mTextureTargets[ct], 0);
    420             continue;
    421         }
    422 
    423         DrvAllocation *drvTex = (DrvAllocation *)mRSProgram->mHal.state.textures[ct]->mHal.drv;
    424         if (drvTex->glTarget != GL_TEXTURE_2D && drvTex->glTarget != GL_TEXTURE_CUBE_MAP) {
    425             LOGE("Attempting to bind unknown texture to shader id %u, texture unit %u", (uint)this, ct);
    426             rsc->setError(RS_ERROR_BAD_SHADER, "Non-texture allocation bound to a shader");
    427         }
    428         RSD_CALL_GL(glBindTexture, drvTex->glTarget, drvTex->textureID);
    429         rsdGLCheckError(rsc, "ProgramFragment::setup tex bind");
    430         if (mRSProgram->mHal.state.samplers[ct]) {
    431             setupSampler(rsc, mRSProgram->mHal.state.samplers[ct],
    432                          mRSProgram->mHal.state.textures[ct]);
    433         } else {
    434             RSD_CALL_GL(glTexParameteri, drvTex->glTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    435             RSD_CALL_GL(glTexParameteri, drvTex->glTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    436             RSD_CALL_GL(glTexParameteri, drvTex->glTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    437             RSD_CALL_GL(glTexParameteri, drvTex->glTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    438             rsdGLCheckError(rsc, "ProgramFragment::setup tex env");
    439         }
    440         rsdGLCheckError(rsc, "ProgramFragment::setup uniforms");
    441     }
    442 
    443     RSD_CALL_GL(glActiveTexture, GL_TEXTURE0);
    444     mDirty = false;
    445     rsdGLCheckError(rsc, "ProgramFragment::setup");
    446 }
    447 
    448 void RsdShader::setupUserConstants(const Context *rsc, RsdShaderCache *sc, bool isFragment) {
    449     uint32_t uidx = 0;
    450     for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
    451         Allocation *alloc = mRSProgram->mHal.state.constants[ct];
    452         if (!alloc) {
    453             LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set",
    454                  (uint32_t)this, ct);
    455             rsc->setError(RS_ERROR_BAD_SHADER, "No constant allocation bound");
    456             continue;
    457         }
    458 
    459         const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
    460         const Element *e = mRSProgram->mHal.state.constantTypes[ct]->getElement();
    461         for (uint32_t field=0; field < e->getFieldCount(); field++) {
    462             const Element *f = e->getField(field);
    463             const char *fieldName = e->getFieldName(field);
    464             // If this field is padding, skip it
    465             if (fieldName[0] == '#') {
    466                 continue;
    467             }
    468 
    469             uint32_t offset = e->getFieldOffsetBytes(field);
    470             const float *fd = reinterpret_cast<const float *>(&data[offset]);
    471 
    472             int32_t slot = -1;
    473             uint32_t arraySize = 1;
    474             if (!isFragment) {
    475                 slot = sc->vtxUniformSlot(uidx);
    476                 arraySize = sc->vtxUniformSize(uidx);
    477             } else {
    478                 slot = sc->fragUniformSlot(uidx);
    479                 arraySize = sc->fragUniformSize(uidx);
    480             }
    481             if (rsc->props.mLogShadersUniforms) {
    482                 LOGV("Uniform  slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s",
    483                      slot, offset, ct, field, uidx, fieldName);
    484             }
    485             uidx ++;
    486             if (slot < 0) {
    487                 continue;
    488             }
    489 
    490             if (rsc->props.mLogShadersUniforms) {
    491                 logUniform(f, fd, arraySize);
    492             }
    493             setUniform(rsc, f, fd, slot, arraySize);
    494         }
    495     }
    496 }
    497 
    498 void RsdShader::setup(const android::renderscript::Context *rsc, RsdShaderCache *sc) {
    499 
    500     setupUserConstants(rsc, sc, mType == GL_FRAGMENT_SHADER);
    501     setupTextures(rsc, sc);
    502 }
    503 
    504 void RsdShader::initAttribAndUniformArray() {
    505     mAttribCount = 0;
    506     for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
    507         const Element *elem = mRSProgram->mHal.state.inputElements[ct];
    508         for (uint32_t field=0; field < elem->getFieldCount(); field++) {
    509             if (elem->getFieldName(field)[0] != '#') {
    510                 mAttribCount ++;
    511             }
    512         }
    513     }
    514 
    515     mUniformCount = 0;
    516     for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
    517         const Element *elem = mRSProgram->mHal.state.constantTypes[ct]->getElement();
    518 
    519         for (uint32_t field=0; field < elem->getFieldCount(); field++) {
    520             if (elem->getFieldName(field)[0] != '#') {
    521                 mUniformCount ++;
    522             }
    523         }
    524     }
    525     mUniformCount += mRSProgram->mHal.state.texturesCount;
    526 
    527     if (mAttribCount) {
    528         mAttribNames = new String8[mAttribCount];
    529     }
    530     if (mUniformCount) {
    531         mUniformNames = new String8[mUniformCount];
    532         mUniformArraySizes = new uint32_t[mUniformCount];
    533     }
    534 
    535     mTextureCount = mRSProgram->mHal.state.texturesCount;
    536     if (mTextureCount) {
    537         mTextureTargets = new uint32_t[mTextureCount];
    538     }
    539 }
    540 
    541 void RsdShader::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths,
    542                                    uint32_t *count, const char *prefix) {
    543     rsAssert(e->getFieldCount());
    544     for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
    545         const Element *ce = e->getField(ct);
    546         if (ce->getFieldCount()) {
    547             initAddUserElement(ce, names, arrayLengths, count, prefix);
    548         } else if (e->getFieldName(ct)[0] != '#') {
    549             String8 tmp(prefix);
    550             tmp.append(e->getFieldName(ct));
    551             names[*count].setTo(tmp.string());
    552             if (arrayLengths) {
    553                 arrayLengths[*count] = e->getFieldArraySize(ct);
    554             }
    555             (*count)++;
    556         }
    557     }
    558 }
    559