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