rsProgram.cpp revision 6e9342199959dc9beb5299fefc9775fe8c32620e
1/* 2 * Copyright (C) 2009 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#ifndef ANDROID_RS_BUILD_FOR_HOST 18#include "rsContext.h" 19#include <GLES2/gl2.h> 20#include <GLES2/gl2ext.h> 21#else 22#include "rsContextHostStub.h" 23#include <OpenGL/gl.h> 24#include <OpenGL/glext.h> 25#endif //ANDROID_RS_BUILD_FOR_HOST 26 27#include "rsProgram.h" 28 29using namespace android; 30using namespace android::renderscript; 31 32 33Program::Program(Context *rsc) : ObjectBase(rsc) 34{ 35 mAllocFile = __FILE__; 36 mAllocLine = __LINE__; 37 mDirty = true; 38 mShaderID = 0; 39 mAttribCount = 0; 40 mUniformCount = 0; 41 42 mInputElements = NULL; 43 mOutputElements = NULL; 44 mConstantTypes = NULL; 45 mInputCount = 0; 46 mOutputCount = 0; 47 mConstantCount = 0; 48 mIsValid = false; 49} 50 51Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength, 52 const uint32_t * params, uint32_t paramLength) : 53 ObjectBase(rsc) 54{ 55 mAllocFile = __FILE__; 56 mAllocLine = __LINE__; 57 mDirty = true; 58 mShaderID = 0; 59 mAttribCount = 0; 60 mUniformCount = 0; 61 mTextureCount = 0; 62 63 mInputCount = 0; 64 mOutputCount = 0; 65 mConstantCount = 0; 66 67 for (uint32_t ct=0; ct < paramLength; ct+=2) { 68 if (params[ct] == RS_PROGRAM_PARAM_INPUT) { 69 mInputCount++; 70 } 71 if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) { 72 mOutputCount++; 73 } 74 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) { 75 mConstantCount++; 76 } 77 if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) { 78 mTextureCount = params[ct+1]; 79 } 80 } 81 82 mInputElements = new ObjectBaseRef<Element>[mInputCount]; 83 mOutputElements = new ObjectBaseRef<Element>[mOutputCount]; 84 mConstantTypes = new ObjectBaseRef<Type>[mConstantCount]; 85 86 uint32_t input = 0; 87 uint32_t output = 0; 88 uint32_t constant = 0; 89 for (uint32_t ct=0; ct < paramLength; ct+=2) { 90 if (params[ct] == RS_PROGRAM_PARAM_INPUT) { 91 mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1])); 92 } 93 if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) { 94 mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1])); 95 } 96 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) { 97 mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1])); 98 } 99 } 100 mUserShader.setTo(shaderText, shaderLength); 101} 102 103Program::~Program() 104{ 105 for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) { 106 bindAllocation(NULL, ct); 107 } 108 109 delete[] mInputElements; 110 delete[] mOutputElements; 111 delete[] mConstantTypes; 112 mInputCount = 0; 113 mOutputCount = 0; 114 mConstantCount = 0; 115} 116 117 118void Program::bindAllocation(Allocation *alloc, uint32_t slot) 119{ 120 if (mConstants[slot].get() == alloc) { 121 return; 122 } 123 if (mConstants[slot].get()) { 124 mConstants[slot].get()->removeProgramToDirty(this); 125 } 126 mConstants[slot].set(alloc); 127 if (alloc) { 128 alloc->addProgramToDirty(this); 129 } 130 mDirty = true; 131} 132 133void Program::bindTexture(uint32_t slot, Allocation *a) 134{ 135 if (slot >= MAX_TEXTURE) { 136 LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE"); 137 return; 138 } 139 140 //LOGE("bindtex %i %p", slot, a); 141 mTextures[slot].set(a); 142 mDirty = true; 143} 144 145void Program::bindSampler(uint32_t slot, Sampler *s) 146{ 147 if (slot >= MAX_TEXTURE) { 148 LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE"); 149 return; 150 } 151 152 mSamplers[slot].set(s); 153 mDirty = true; 154} 155 156String8 Program::getGLSLInputString() const 157{ 158 String8 s; 159 for (uint32_t ct=0; ct < mInputCount; ct++) { 160 const Element *e = mInputElements[ct].get(); 161 for (uint32_t field=0; field < e->getFieldCount(); field++) { 162 const Element *f = e->getField(field); 163 164 // Cannot be complex 165 rsAssert(!f->getFieldCount()); 166 switch(f->getComponent().getVectorSize()) { 167 case 1: s.append("attribute float ATTRIB_"); break; 168 case 2: s.append("attribute vec2 ATTRIB_"); break; 169 case 3: s.append("attribute vec3 ATTRIB_"); break; 170 case 4: s.append("attribute vec4 ATTRIB_"); break; 171 default: 172 rsAssert(0); 173 } 174 175 s.append(e->getFieldName(field)); 176 s.append(";\n"); 177 } 178 } 179 return s; 180} 181 182String8 Program::getGLSLOutputString() const 183{ 184 return String8(); 185} 186 187String8 Program::getGLSLConstantString() const 188{ 189 return String8(); 190} 191 192 193void Program::createShader() 194{ 195} 196 197bool Program::loadShader(Context *rsc, uint32_t type) 198{ 199 mShaderID = glCreateShader(type); 200 rsAssert(mShaderID); 201 202 if (rsc->props.mLogShaders) { 203 LOGV("Loading shader type %x, ID %i", type, mShaderID); 204 LOGV("%s", mShader.string()); 205 } 206 207 if (mShaderID) { 208 const char * ss = mShader.string(); 209 glShaderSource(mShaderID, 1, &ss, NULL); 210 glCompileShader(mShaderID); 211 212 GLint compiled = 0; 213 glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled); 214 if (!compiled) { 215 GLint infoLen = 0; 216 glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen); 217 if (infoLen) { 218 char* buf = (char*) malloc(infoLen); 219 if (buf) { 220 glGetShaderInfoLog(mShaderID, infoLen, NULL, buf); 221 LOGE("Could not compile shader \n%s\n", buf); 222 free(buf); 223 } 224 glDeleteShader(mShaderID); 225 mShaderID = 0; 226 rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,"); 227 return false; 228 } 229 } 230 } 231 232 if (rsc->props.mLogShaders) { 233 LOGV("--Shader load result %x ", glGetError()); 234 } 235 mIsValid = true; 236 return true; 237} 238 239void Program::setShader(const char *txt, uint32_t len) 240{ 241 mUserShader.setTo(txt, len); 242} 243 244void Program::appendUserConstants() { 245 for (uint32_t ct=0; ct < mConstantCount; ct++) { 246 const Element *e = mConstantTypes[ct]->getElement(); 247 for (uint32_t field=0; field < e->getFieldCount(); field++) { 248 const Element *f = e->getField(field); 249 const char *fn = e->getFieldName(field); 250 251 if (fn[0] == '#') { 252 continue; 253 } 254 255 // Cannot be complex 256 rsAssert(!f->getFieldCount()); 257 if(f->getType() == RS_TYPE_MATRIX_4X4) { 258 mShader.append("uniform mat4 UNI_"); 259 } 260 else if(f->getType() == RS_TYPE_MATRIX_3X3) { 261 mShader.append("uniform mat3 UNI_"); 262 } 263 else if(f->getType() == RS_TYPE_MATRIX_2X2) { 264 mShader.append("uniform mat2 UNI_"); 265 } 266 else { 267 switch(f->getComponent().getVectorSize()) { 268 case 1: mShader.append("uniform float UNI_"); break; 269 case 2: mShader.append("uniform vec2 UNI_"); break; 270 case 3: mShader.append("uniform vec3 UNI_"); break; 271 case 4: mShader.append("uniform vec4 UNI_"); break; 272 default: 273 rsAssert(0); 274 } 275 } 276 277 mShader.append(fn); 278 mShader.append(";\n"); 279 } 280 } 281} 282 283void Program::setupUserConstants(ShaderCache *sc, bool isFragment) { 284 uint32_t uidx = 1; 285 for (uint32_t ct=0; ct < mConstantCount; ct++) { 286 Allocation *alloc = mConstants[ct+1].get(); 287 if (!alloc) { 288 continue; 289 } 290 291 const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr()); 292 const Element *e = mConstantTypes[ct]->getElement(); 293 for (uint32_t field=0; field < e->getFieldCount(); field++) { 294 const Element *f = e->getField(field); 295 const char *fieldName = e->getFieldName(field); 296 // If this field is padding, skip it 297 if(fieldName[0] == '#') { 298 continue; 299 } 300 301 uint32_t offset = e->getFieldOffsetBytes(field); 302 const float *fd = reinterpret_cast<const float *>(&data[offset]); 303 304 int32_t slot = -1; 305 if(!isFragment) { 306 slot = sc->vtxUniformSlot(uidx); 307 } 308 else { 309 slot = sc->fragUniformSlot(uidx); 310 } 311 312 //LOGE("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName); 313 if (slot >= 0) { 314 if(f->getType() == RS_TYPE_MATRIX_4X4) { 315 glUniformMatrix4fv(slot, 1, GL_FALSE, fd); 316 } 317 else if(f->getType() == RS_TYPE_MATRIX_3X3) { 318 glUniformMatrix3fv(slot, 1, GL_FALSE, fd); 319 } 320 else if(f->getType() == RS_TYPE_MATRIX_2X2) { 321 glUniformMatrix2fv(slot, 1, GL_FALSE, fd); 322 } 323 else { 324 switch(f->getComponent().getVectorSize()) { 325 case 1: 326 //LOGE("Uniform 1 = %f", fd[0]); 327 glUniform1fv(slot, 1, fd); 328 break; 329 case 2: 330 //LOGE("Uniform 2 = %f %f", fd[0], fd[1]); 331 glUniform2fv(slot, 1, fd); 332 break; 333 case 3: 334 //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]); 335 glUniform3fv(slot, 1, fd); 336 break; 337 case 4: 338 //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]); 339 glUniform4fv(slot, 1, fd); 340 break; 341 default: 342 rsAssert(0); 343 } 344 } 345 } 346 uidx ++; 347 } 348 } 349} 350 351void Program::initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix) 352{ 353 rsAssert(e->getFieldCount()); 354 for (uint32_t ct=0; ct < e->getFieldCount(); ct++) { 355 const Element *ce = e->getField(ct); 356 if (ce->getFieldCount()) { 357 initAddUserElement(ce, names, count, prefix); 358 } 359 else if(e->getFieldName(ct)[0] != '#') { 360 String8 tmp(prefix); 361 tmp.append(e->getFieldName(ct)); 362 names[*count].setTo(tmp.string()); 363 (*count)++; 364 } 365 } 366} 367 368namespace android { 369namespace renderscript { 370 371 372void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants) 373{ 374 Program *p = static_cast<Program *>(vp); 375 p->bindAllocation(static_cast<Allocation *>(constants), slot); 376} 377 378void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a) 379{ 380 Program *p = static_cast<Program *>(vpf); 381 p->bindTexture(slot, static_cast<Allocation *>(a)); 382} 383 384void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s) 385{ 386 Program *p = static_cast<Program *>(vpf); 387 p->bindSampler(slot, static_cast<Sampler *>(s)); 388} 389 390} 391} 392 393