rsdShaderCache.cpp revision 886f11ade9dde05485cb11c0d67d87f76a428f6c
1c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams/* 2c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * Copyright (C) 2009 The Android Open Source Project 3c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * 4c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * Licensed under the Apache License, Version 2.0 (the "License"); 5c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * you may not use this file except in compliance with the License. 6c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * You may obtain a copy of the License at 7c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * 8c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * http://www.apache.org/licenses/LICENSE-2.0 9c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * 10c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * Unless required by applicable law or agreed to in writing, software 11c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * distributed under the License is distributed on an "AS IS" BASIS, 12c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * See the License for the specific language governing permissions and 14c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams * limitations under the License. 15c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams */ 16c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 17fb6b614bcea88a587a7ea4530be45ff0ffa0210eAlex Sakhartchouk#ifndef ANDROID_RS_BUILD_FOR_HOST 18c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams#include "rsContext.h" 19c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams#include <GLES/gl.h> 20c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams#include <GLES2/gl2.h> 21fb6b614bcea88a587a7ea4530be45ff0ffa0210eAlex Sakhartchouk#else 22fb6b614bcea88a587a7ea4530be45ff0ffa0210eAlex Sakhartchouk#include "rsContextHostStub.h" 23fb6b614bcea88a587a7ea4530be45ff0ffa0210eAlex Sakhartchouk#include <OpenGL/gl.h> 24fb6b614bcea88a587a7ea4530be45ff0ffa0210eAlex Sakhartchouk#endif //ANDROID_RS_BUILD_FOR_HOST 25c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 26c460e55d78cbe8bee95c5c947dfe541218142a5bJason Samsusing namespace android; 27c460e55d78cbe8bee95c5c947dfe541218142a5bJason Samsusing namespace android::renderscript; 28c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 29c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 30c460e55d78cbe8bee95c5c947dfe541218142a5bJason SamsShaderCache::ShaderCache() 31c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams{ 32c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams mEntryCount = 0; 33c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams mEntryAllocationCount = 16; 34c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams mEntries = (entry_t *)calloc(mEntryAllocationCount, sizeof(entry_t)); 35c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams} 36c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 37c460e55d78cbe8bee95c5c947dfe541218142a5bJason SamsShaderCache::~ShaderCache() 38c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams{ 39c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams for (uint32_t ct=0; ct < mEntryCount; ct++) { 40c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams glDeleteProgram(mEntries[ct].program); 41c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 42c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 43c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams mEntryCount = 0; 44c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams mEntryAllocationCount = 0; 45c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams free(mEntries); 46c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams} 47c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 48cd50653f99c960e1a47c2c30e53b369b8805344aJason Samsbool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag) 49c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams{ 50c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams if (!vtx->getShaderID()) { 51cd50653f99c960e1a47c2c30e53b369b8805344aJason Sams vtx->loadShader(rsc); 52c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 53c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams if (!frag->getShaderID()) { 54cd50653f99c960e1a47c2c30e53b369b8805344aJason Sams frag->loadShader(rsc); 55c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 56886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk 57886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk // Don't try to cache if shaders failed to load 58886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk if(!vtx->getShaderID() || !frag->getShaderID()) { 59886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk return false; 60886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk } 61f2a5d7326b38e5a28b6618f9b1e5a021aef7179fJason Sams //LOGV("ShaderCache lookup vtx %i, frag %i", vtx->getShaderID(), frag->getShaderID()); 62c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 63c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams for (uint32_t ct=0; ct < mEntryCount; ct++) { 64c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams if ((mEntries[ct].vtx == vtx->getShaderID()) && 65c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams (mEntries[ct].frag == frag->getShaderID())) { 66c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 67c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams //LOGV("SC using program %i", mEntries[ct].program); 68c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams glUseProgram(mEntries[ct].program); 69c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams mCurrent = &mEntries[ct]; 70f2a5d7326b38e5a28b6618f9b1e5a021aef7179fJason Sams //LOGV("ShaderCache hit, using %i", ct); 71433eca30b2efe0cf84bbda33f2dfdfd6dcafaf59Jason Sams rsc->checkError("ShaderCache::lookup (hit)"); 72c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams return true; 73c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 74c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 75c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams // Not in cache, add it. 76c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 77c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams if (mEntryAllocationCount == mEntryCount) { 78c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams // Out of space, make some. 79c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams mEntryAllocationCount *= 2; 80c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams entry_t *e = (entry_t *)calloc(mEntryAllocationCount, sizeof(entry_t)); 81c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams if (!e) { 82c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams LOGE("Out of memory for ShaderCache::lookup"); 83c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams return false; 84c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 85c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams memcpy(e, mEntries, sizeof(entry_t) * mEntryCount); 86c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams free(mEntries); 87c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams mEntries = e; 88c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 89c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 90f2a5d7326b38e5a28b6618f9b1e5a021aef7179fJason Sams //LOGV("ShaderCache miss, using %i", mEntryCount); 91f2a5d7326b38e5a28b6618f9b1e5a021aef7179fJason Sams //LOGE("e0 %x", glGetError()); 92c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 93c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams entry_t *e = &mEntries[mEntryCount]; 94c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams mCurrent = e; 95c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams e->vtx = vtx->getShaderID(); 96c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams e->frag = frag->getShaderID(); 97c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams e->program = glCreateProgram(); 98886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk e->vtxAttrCount = vtx->getAttribCount(); 99c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams if (mEntries[mEntryCount].program) { 100c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams GLuint pgm = e->program; 101c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams glAttachShader(pgm, vtx->getShaderID()); 102c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams //LOGE("e1 %x", glGetError()); 103c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams glAttachShader(pgm, frag->getShaderID()); 104c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 105433eca30b2efe0cf84bbda33f2dfdfd6dcafaf59Jason Sams if (!vtx->isUserProgram()) { 10679f52df541f87ac07709e770cd79f14dd1a05e93Jason Sams glBindAttribLocation(pgm, 0, "ATTRIB_position"); 10779f52df541f87ac07709e770cd79f14dd1a05e93Jason Sams glBindAttribLocation(pgm, 1, "ATTRIB_color"); 10879f52df541f87ac07709e770cd79f14dd1a05e93Jason Sams glBindAttribLocation(pgm, 2, "ATTRIB_normal"); 109479e2924807e1fff79de2e0bee2a67939d8659eeJason Sams glBindAttribLocation(pgm, 3, "ATTRIB_texture0"); 110433eca30b2efe0cf84bbda33f2dfdfd6dcafaf59Jason Sams } 111c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 112c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams //LOGE("e2 %x", glGetError()); 113c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams glLinkProgram(pgm); 114c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams //LOGE("e3 %x", glGetError()); 115c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams GLint linkStatus = GL_FALSE; 116c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams glGetProgramiv(pgm, GL_LINK_STATUS, &linkStatus); 117c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams if (linkStatus != GL_TRUE) { 118c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams GLint bufLength = 0; 119c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams glGetProgramiv(pgm, GL_INFO_LOG_LENGTH, &bufLength); 120c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams if (bufLength) { 121c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams char* buf = (char*) malloc(bufLength); 122c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams if (buf) { 123c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams glGetProgramInfoLog(pgm, bufLength, NULL, buf); 124c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams LOGE("Could not link program:\n%s\n", buf); 125c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams free(buf); 126c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 127c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 128c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams glDeleteProgram(pgm); 129a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams rsc->setError(RS_ERROR_BAD_SHADER, "Error linking GL Programs"); 130a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams return false; 131c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 132886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk 133886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk for (uint32_t ct=0; ct < e->vtxAttrCount; ct++) { 134886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk e->mVtxAttribSlots[ct] = glGetAttribLocation(pgm, vtx->getAttribName(ct)); 135886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk e->mVtxAttribNames[ct] = vtx->getAttribName(ct).string(); 136886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk if (rsc->props.mLogShaders) { 137886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk LOGV("vtx A %i, %s = %d\n", ct, vtx->getAttribName(ct).string(), e->mVtxAttribSlots[ct]); 138cd50653f99c960e1a47c2c30e53b369b8805344aJason Sams } 139c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 140886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk 141c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams for (uint32_t ct=0; ct < vtx->getUniformCount(); ct++) { 142c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams e->mVtxUniformSlots[ct] = glGetUniformLocation(pgm, vtx->getUniformName(ct)); 143cd50653f99c960e1a47c2c30e53b369b8805344aJason Sams if (rsc->props.mLogShaders) { 144cd50653f99c960e1a47c2c30e53b369b8805344aJason Sams LOGV("vtx U, %s = %d\n", vtx->getUniformName(ct).string(), e->mVtxUniformSlots[ct]); 145cd50653f99c960e1a47c2c30e53b369b8805344aJason Sams } 146c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 1479ebb0c44ece47531f3d0a98ba52ae448de42032bJason Sams for (uint32_t ct=0; ct < frag->getUniformCount(); ct++) { 148c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams e->mFragUniformSlots[ct] = glGetUniformLocation(pgm, frag->getUniformName(ct)); 149cd50653f99c960e1a47c2c30e53b369b8805344aJason Sams if (rsc->props.mLogShaders) { 150cd50653f99c960e1a47c2c30e53b369b8805344aJason Sams LOGV("frag U, %s = %d\n", frag->getUniformName(ct).string(), e->mFragUniformSlots[ct]); 151cd50653f99c960e1a47c2c30e53b369b8805344aJason Sams } 152c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 153c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams } 154c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 155a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams e->mIsValid = true; 156f2a5d7326b38e5a28b6618f9b1e5a021aef7179fJason Sams //LOGV("SC made program %i", e->program); 157c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams glUseProgram(e->program); 158c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams mEntryCount++; 159433eca30b2efe0cf84bbda33f2dfdfd6dcafaf59Jason Sams rsc->checkError("ShaderCache::lookup (miss)"); 160c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams return true; 161c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams} 162c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 163886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchoukint32_t ShaderCache::vtxAttribSlot(const String8 &attrName) const { 164886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk for (uint32_t ct=0; ct < mCurrent->vtxAttrCount; ct++) { 165886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk if(attrName == mCurrent->mVtxAttribNames[ct]) { 166886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk return mCurrent->mVtxAttribSlots[ct]; 167886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk } 168886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk } 169886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk return -1; 170886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk} 171886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk 172c460e55d78cbe8bee95c5c947dfe541218142a5bJason Samsvoid ShaderCache::cleanupVertex(uint32_t id) 173c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams{ 174c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams} 175c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 176c460e55d78cbe8bee95c5c947dfe541218142a5bJason Samsvoid ShaderCache::cleanupFragment(uint32_t id) 177c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams{ 178c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams} 179c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 180c460e55d78cbe8bee95c5c947dfe541218142a5bJason Samsvoid ShaderCache::cleanupAll() 181c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams{ 182c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams} 183c460e55d78cbe8bee95c5c947dfe541218142a5bJason Sams 184