1*e1eccf28SAndroid Build Coastguard Worker /*
2*e1eccf28SAndroid Build Coastguard Worker * Copyright (C) 2011-2012 The Android Open Source Project
3*e1eccf28SAndroid Build Coastguard Worker *
4*e1eccf28SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e1eccf28SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e1eccf28SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e1eccf28SAndroid Build Coastguard Worker *
8*e1eccf28SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e1eccf28SAndroid Build Coastguard Worker *
10*e1eccf28SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e1eccf28SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e1eccf28SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e1eccf28SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e1eccf28SAndroid Build Coastguard Worker * limitations under the License.
15*e1eccf28SAndroid Build Coastguard Worker */
16*e1eccf28SAndroid Build Coastguard Worker
17*e1eccf28SAndroid Build Coastguard Worker #include <rs_hal.h>
18*e1eccf28SAndroid Build Coastguard Worker #include <rsContext.h>
19*e1eccf28SAndroid Build Coastguard Worker
20*e1eccf28SAndroid Build Coastguard Worker #include "rsdShader.h"
21*e1eccf28SAndroid Build Coastguard Worker #include "rsdShaderCache.h"
22*e1eccf28SAndroid Build Coastguard Worker #include "rsdGL.h"
23*e1eccf28SAndroid Build Coastguard Worker
24*e1eccf28SAndroid Build Coastguard Worker #include <GLES/gl.h>
25*e1eccf28SAndroid Build Coastguard Worker #include <GLES2/gl2.h>
26*e1eccf28SAndroid Build Coastguard Worker
27*e1eccf28SAndroid Build Coastguard Worker using android::renderscript::Context;
28*e1eccf28SAndroid Build Coastguard Worker
RsdShaderCache()29*e1eccf28SAndroid Build Coastguard Worker RsdShaderCache::RsdShaderCache() {
30*e1eccf28SAndroid Build Coastguard Worker mVertexDirty = true;
31*e1eccf28SAndroid Build Coastguard Worker mFragmentDirty = true;
32*e1eccf28SAndroid Build Coastguard Worker }
33*e1eccf28SAndroid Build Coastguard Worker
~RsdShaderCache()34*e1eccf28SAndroid Build Coastguard Worker RsdShaderCache::~RsdShaderCache() {
35*e1eccf28SAndroid Build Coastguard Worker cleanupAll();
36*e1eccf28SAndroid Build Coastguard Worker }
37*e1eccf28SAndroid Build Coastguard Worker
updateUniformArrayData(const Context * rsc,RsdShader * prog,uint32_t linkedID,UniformData * data,const char * logTag,UniformQueryData ** uniformList,uint32_t uniListSize)38*e1eccf28SAndroid Build Coastguard Worker void RsdShaderCache::updateUniformArrayData(const Context *rsc,
39*e1eccf28SAndroid Build Coastguard Worker RsdShader *prog,
40*e1eccf28SAndroid Build Coastguard Worker uint32_t linkedID,
41*e1eccf28SAndroid Build Coastguard Worker UniformData *data,
42*e1eccf28SAndroid Build Coastguard Worker const char* logTag,
43*e1eccf28SAndroid Build Coastguard Worker UniformQueryData **uniformList,
44*e1eccf28SAndroid Build Coastguard Worker uint32_t uniListSize) {
45*e1eccf28SAndroid Build Coastguard Worker
46*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ct=0; ct < prog->getUniformCount(); ct++) {
47*e1eccf28SAndroid Build Coastguard Worker if (data[ct].slot >= 0 && data[ct].arraySize > 1) {
48*e1eccf28SAndroid Build Coastguard Worker //Iterate over the list of active GL uniforms and find highest array index
49*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ui = 0; ui < uniListSize; ui ++) {
50*e1eccf28SAndroid Build Coastguard Worker if (prog->getUniformName(ct) == uniformList[ui]->name) {
51*e1eccf28SAndroid Build Coastguard Worker data[ct].arraySize = (uint32_t)uniformList[ui]->arraySize;
52*e1eccf28SAndroid Build Coastguard Worker break;
53*e1eccf28SAndroid Build Coastguard Worker }
54*e1eccf28SAndroid Build Coastguard Worker }
55*e1eccf28SAndroid Build Coastguard Worker }
56*e1eccf28SAndroid Build Coastguard Worker
57*e1eccf28SAndroid Build Coastguard Worker if (rsc->props.mLogShaders) {
58*e1eccf28SAndroid Build Coastguard Worker ALOGV("%s U, %s = %d, arraySize = %d\n", logTag,
59*e1eccf28SAndroid Build Coastguard Worker prog->getUniformName(ct).c_str(), data[ct].slot,
60*e1eccf28SAndroid Build Coastguard Worker data[ct].arraySize);
61*e1eccf28SAndroid Build Coastguard Worker }
62*e1eccf28SAndroid Build Coastguard Worker }
63*e1eccf28SAndroid Build Coastguard Worker }
64*e1eccf28SAndroid Build Coastguard Worker
populateUniformData(RsdShader * prog,uint32_t linkedID,UniformData * data)65*e1eccf28SAndroid Build Coastguard Worker void RsdShaderCache::populateUniformData(RsdShader *prog, uint32_t linkedID,
66*e1eccf28SAndroid Build Coastguard Worker UniformData *data) {
67*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ct=0; ct < prog->getUniformCount(); ct++) {
68*e1eccf28SAndroid Build Coastguard Worker data[ct].slot = glGetUniformLocation(linkedID,
69*e1eccf28SAndroid Build Coastguard Worker prog->getUniformName(ct).c_str());
70*e1eccf28SAndroid Build Coastguard Worker data[ct].arraySize = prog->getUniformArraySize(ct);
71*e1eccf28SAndroid Build Coastguard Worker }
72*e1eccf28SAndroid Build Coastguard Worker }
73*e1eccf28SAndroid Build Coastguard Worker
hasArrayUniforms(RsdShader * vtx,RsdShader * frag)74*e1eccf28SAndroid Build Coastguard Worker bool RsdShaderCache::hasArrayUniforms(RsdShader *vtx, RsdShader *frag) {
75*e1eccf28SAndroid Build Coastguard Worker UniformData *data = mCurrent->vtxUniforms;
76*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ct=0; ct < vtx->getUniformCount(); ct++) {
77*e1eccf28SAndroid Build Coastguard Worker if (data[ct].slot >= 0 && data[ct].arraySize > 1) {
78*e1eccf28SAndroid Build Coastguard Worker return true;
79*e1eccf28SAndroid Build Coastguard Worker }
80*e1eccf28SAndroid Build Coastguard Worker }
81*e1eccf28SAndroid Build Coastguard Worker data = mCurrent->fragUniforms;
82*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ct=0; ct < frag->getUniformCount(); ct++) {
83*e1eccf28SAndroid Build Coastguard Worker if (data[ct].slot >= 0 && data[ct].arraySize > 1) {
84*e1eccf28SAndroid Build Coastguard Worker return true;
85*e1eccf28SAndroid Build Coastguard Worker }
86*e1eccf28SAndroid Build Coastguard Worker }
87*e1eccf28SAndroid Build Coastguard Worker return false;
88*e1eccf28SAndroid Build Coastguard Worker }
89*e1eccf28SAndroid Build Coastguard Worker
setup(const Context * rsc)90*e1eccf28SAndroid Build Coastguard Worker bool RsdShaderCache::setup(const Context *rsc) {
91*e1eccf28SAndroid Build Coastguard Worker if (!mVertexDirty && !mFragmentDirty) {
92*e1eccf28SAndroid Build Coastguard Worker return true;
93*e1eccf28SAndroid Build Coastguard Worker }
94*e1eccf28SAndroid Build Coastguard Worker
95*e1eccf28SAndroid Build Coastguard Worker if (!link(rsc)) {
96*e1eccf28SAndroid Build Coastguard Worker return false;
97*e1eccf28SAndroid Build Coastguard Worker }
98*e1eccf28SAndroid Build Coastguard Worker
99*e1eccf28SAndroid Build Coastguard Worker if (mFragmentDirty) {
100*e1eccf28SAndroid Build Coastguard Worker mFragment->setup(rsc, this);
101*e1eccf28SAndroid Build Coastguard Worker mFragmentDirty = false;
102*e1eccf28SAndroid Build Coastguard Worker }
103*e1eccf28SAndroid Build Coastguard Worker if (mVertexDirty) {
104*e1eccf28SAndroid Build Coastguard Worker mVertex->setup(rsc, this);
105*e1eccf28SAndroid Build Coastguard Worker mVertexDirty = false;
106*e1eccf28SAndroid Build Coastguard Worker }
107*e1eccf28SAndroid Build Coastguard Worker
108*e1eccf28SAndroid Build Coastguard Worker return true;
109*e1eccf28SAndroid Build Coastguard Worker }
110*e1eccf28SAndroid Build Coastguard Worker
link(const Context * rsc)111*e1eccf28SAndroid Build Coastguard Worker bool RsdShaderCache::link(const Context *rsc) {
112*e1eccf28SAndroid Build Coastguard Worker
113*e1eccf28SAndroid Build Coastguard Worker RsdShader *vtx = mVertex;
114*e1eccf28SAndroid Build Coastguard Worker RsdShader *frag = mFragment;
115*e1eccf28SAndroid Build Coastguard Worker
116*e1eccf28SAndroid Build Coastguard Worker uint32_t vID = vtx->getStateBasedShaderID(rsc);
117*e1eccf28SAndroid Build Coastguard Worker uint32_t fID = frag->getStateBasedShaderID(rsc);
118*e1eccf28SAndroid Build Coastguard Worker
119*e1eccf28SAndroid Build Coastguard Worker // Don't try to cache if shaders failed to load
120*e1eccf28SAndroid Build Coastguard Worker if (!vID || !fID) {
121*e1eccf28SAndroid Build Coastguard Worker return false;
122*e1eccf28SAndroid Build Coastguard Worker }
123*e1eccf28SAndroid Build Coastguard Worker uint32_t entryCount = mEntries.size();
124*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ct = 0; ct < entryCount; ct ++) {
125*e1eccf28SAndroid Build Coastguard Worker if ((mEntries[ct]->vtx == vID) && (mEntries[ct]->frag == fID)) {
126*e1eccf28SAndroid Build Coastguard Worker //ALOGV("SC using program %i", mEntries[ct]->program);
127*e1eccf28SAndroid Build Coastguard Worker glUseProgram(mEntries[ct]->program);
128*e1eccf28SAndroid Build Coastguard Worker mCurrent = mEntries[ct];
129*e1eccf28SAndroid Build Coastguard Worker //ALOGV("RsdShaderCache hit, using %i", ct);
130*e1eccf28SAndroid Build Coastguard Worker rsdGLCheckError(rsc, "RsdShaderCache::link (hit)");
131*e1eccf28SAndroid Build Coastguard Worker return true;
132*e1eccf28SAndroid Build Coastguard Worker }
133*e1eccf28SAndroid Build Coastguard Worker }
134*e1eccf28SAndroid Build Coastguard Worker
135*e1eccf28SAndroid Build Coastguard Worker ProgramEntry *e = new ProgramEntry(vtx->getAttribCount(),
136*e1eccf28SAndroid Build Coastguard Worker vtx->getUniformCount(),
137*e1eccf28SAndroid Build Coastguard Worker frag->getUniformCount());
138*e1eccf28SAndroid Build Coastguard Worker mEntries.push_back(e);
139*e1eccf28SAndroid Build Coastguard Worker mCurrent = e;
140*e1eccf28SAndroid Build Coastguard Worker e->vtx = vID;
141*e1eccf28SAndroid Build Coastguard Worker e->frag = fID;
142*e1eccf28SAndroid Build Coastguard Worker e->program = glCreateProgram();
143*e1eccf28SAndroid Build Coastguard Worker if (e->program) {
144*e1eccf28SAndroid Build Coastguard Worker GLuint pgm = e->program;
145*e1eccf28SAndroid Build Coastguard Worker glAttachShader(pgm, vID);
146*e1eccf28SAndroid Build Coastguard Worker //ALOGE("e1 %x", glGetError());
147*e1eccf28SAndroid Build Coastguard Worker glAttachShader(pgm, fID);
148*e1eccf28SAndroid Build Coastguard Worker
149*e1eccf28SAndroid Build Coastguard Worker glBindAttribLocation(pgm, 0, "ATTRIB_position");
150*e1eccf28SAndroid Build Coastguard Worker glBindAttribLocation(pgm, 1, "ATTRIB_color");
151*e1eccf28SAndroid Build Coastguard Worker glBindAttribLocation(pgm, 2, "ATTRIB_normal");
152*e1eccf28SAndroid Build Coastguard Worker glBindAttribLocation(pgm, 3, "ATTRIB_texture0");
153*e1eccf28SAndroid Build Coastguard Worker
154*e1eccf28SAndroid Build Coastguard Worker //ALOGE("e2 %x", glGetError());
155*e1eccf28SAndroid Build Coastguard Worker glLinkProgram(pgm);
156*e1eccf28SAndroid Build Coastguard Worker //ALOGE("e3 %x", glGetError());
157*e1eccf28SAndroid Build Coastguard Worker GLint linkStatus = GL_FALSE;
158*e1eccf28SAndroid Build Coastguard Worker glGetProgramiv(pgm, GL_LINK_STATUS, &linkStatus);
159*e1eccf28SAndroid Build Coastguard Worker if (linkStatus != GL_TRUE) {
160*e1eccf28SAndroid Build Coastguard Worker GLint bufLength = 0;
161*e1eccf28SAndroid Build Coastguard Worker glGetProgramiv(pgm, GL_INFO_LOG_LENGTH, &bufLength);
162*e1eccf28SAndroid Build Coastguard Worker if (bufLength) {
163*e1eccf28SAndroid Build Coastguard Worker char* buf = (char*) malloc(bufLength);
164*e1eccf28SAndroid Build Coastguard Worker if (buf) {
165*e1eccf28SAndroid Build Coastguard Worker glGetProgramInfoLog(pgm, bufLength, nullptr, buf);
166*e1eccf28SAndroid Build Coastguard Worker rsc->setError(RS_ERROR_FATAL_PROGRAM_LINK, buf);
167*e1eccf28SAndroid Build Coastguard Worker free(buf);
168*e1eccf28SAndroid Build Coastguard Worker }
169*e1eccf28SAndroid Build Coastguard Worker }
170*e1eccf28SAndroid Build Coastguard Worker glDeleteProgram(pgm);
171*e1eccf28SAndroid Build Coastguard Worker return false;
172*e1eccf28SAndroid Build Coastguard Worker }
173*e1eccf28SAndroid Build Coastguard Worker
174*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ct=0; ct < e->vtxAttrCount; ct++) {
175*e1eccf28SAndroid Build Coastguard Worker e->vtxAttrs[ct].slot =
176*e1eccf28SAndroid Build Coastguard Worker glGetAttribLocation(pgm, vtx->getAttribName(ct).c_str());
177*e1eccf28SAndroid Build Coastguard Worker e->vtxAttrs[ct].name = vtx->getAttribName(ct).c_str();
178*e1eccf28SAndroid Build Coastguard Worker if (rsc->props.mLogShaders) {
179*e1eccf28SAndroid Build Coastguard Worker ALOGV("vtx A %i, %s = %d\n", ct,
180*e1eccf28SAndroid Build Coastguard Worker vtx->getAttribName(ct).c_str(), e->vtxAttrs[ct].slot);
181*e1eccf28SAndroid Build Coastguard Worker }
182*e1eccf28SAndroid Build Coastguard Worker }
183*e1eccf28SAndroid Build Coastguard Worker
184*e1eccf28SAndroid Build Coastguard Worker populateUniformData(vtx, pgm, e->vtxUniforms);
185*e1eccf28SAndroid Build Coastguard Worker populateUniformData(frag, pgm, e->fragUniforms);
186*e1eccf28SAndroid Build Coastguard Worker
187*e1eccf28SAndroid Build Coastguard Worker // Only populate this list if we have arrays in our uniforms
188*e1eccf28SAndroid Build Coastguard Worker UniformQueryData **uniformList = nullptr;
189*e1eccf28SAndroid Build Coastguard Worker GLint numUniforms = 0;
190*e1eccf28SAndroid Build Coastguard Worker bool hasArrays = hasArrayUniforms(vtx, frag);
191*e1eccf28SAndroid Build Coastguard Worker if (hasArrays) {
192*e1eccf28SAndroid Build Coastguard Worker // Get the number of active uniforms and the length of the longest name
193*e1eccf28SAndroid Build Coastguard Worker glGetProgramiv(pgm, GL_ACTIVE_UNIFORMS, &numUniforms);
194*e1eccf28SAndroid Build Coastguard Worker GLint maxNameLength = 0;
195*e1eccf28SAndroid Build Coastguard Worker glGetProgramiv(pgm, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
196*e1eccf28SAndroid Build Coastguard Worker if (numUniforms > 0 && maxNameLength > 0) {
197*e1eccf28SAndroid Build Coastguard Worker uniformList = new UniformQueryData*[numUniforms];
198*e1eccf28SAndroid Build Coastguard Worker // Iterate over all the uniforms and build the list we
199*e1eccf28SAndroid Build Coastguard Worker // can later use to match our uniforms to
200*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ct = 0; ct < (uint32_t)numUniforms; ct++) {
201*e1eccf28SAndroid Build Coastguard Worker uniformList[ct] = new UniformQueryData(maxNameLength);
202*e1eccf28SAndroid Build Coastguard Worker glGetActiveUniform(pgm, ct, maxNameLength, &uniformList[ct]->writtenLength,
203*e1eccf28SAndroid Build Coastguard Worker &uniformList[ct]->arraySize, &uniformList[ct]->type,
204*e1eccf28SAndroid Build Coastguard Worker uniformList[ct]->name);
205*e1eccf28SAndroid Build Coastguard Worker //ALOGE("GL UNI idx=%u, arraySize=%u, name=%s", ct,
206*e1eccf28SAndroid Build Coastguard Worker // uniformList[ct]->arraySize, uniformList[ct]->name);
207*e1eccf28SAndroid Build Coastguard Worker }
208*e1eccf28SAndroid Build Coastguard Worker }
209*e1eccf28SAndroid Build Coastguard Worker }
210*e1eccf28SAndroid Build Coastguard Worker
211*e1eccf28SAndroid Build Coastguard Worker // We now know the highest index of all of the array uniforms
212*e1eccf28SAndroid Build Coastguard Worker // and we need to update our cache to reflect that
213*e1eccf28SAndroid Build Coastguard Worker // we may have declared [n], but only m < n elements are used
214*e1eccf28SAndroid Build Coastguard Worker updateUniformArrayData(rsc, vtx, pgm, e->vtxUniforms, "vtx",
215*e1eccf28SAndroid Build Coastguard Worker uniformList, (uint32_t)numUniforms);
216*e1eccf28SAndroid Build Coastguard Worker updateUniformArrayData(rsc, frag, pgm, e->fragUniforms, "frag",
217*e1eccf28SAndroid Build Coastguard Worker uniformList, (uint32_t)numUniforms);
218*e1eccf28SAndroid Build Coastguard Worker
219*e1eccf28SAndroid Build Coastguard Worker // Clean up the uniform data from GL
220*e1eccf28SAndroid Build Coastguard Worker if (uniformList != nullptr) {
221*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ct = 0; ct < (uint32_t)numUniforms; ct++) {
222*e1eccf28SAndroid Build Coastguard Worker delete uniformList[ct];
223*e1eccf28SAndroid Build Coastguard Worker }
224*e1eccf28SAndroid Build Coastguard Worker delete[] uniformList;
225*e1eccf28SAndroid Build Coastguard Worker uniformList = nullptr;
226*e1eccf28SAndroid Build Coastguard Worker }
227*e1eccf28SAndroid Build Coastguard Worker }
228*e1eccf28SAndroid Build Coastguard Worker
229*e1eccf28SAndroid Build Coastguard Worker //ALOGV("SC made program %i", e->program);
230*e1eccf28SAndroid Build Coastguard Worker glUseProgram(e->program);
231*e1eccf28SAndroid Build Coastguard Worker rsdGLCheckError(rsc, "RsdShaderCache::link (miss)");
232*e1eccf28SAndroid Build Coastguard Worker
233*e1eccf28SAndroid Build Coastguard Worker return true;
234*e1eccf28SAndroid Build Coastguard Worker }
235*e1eccf28SAndroid Build Coastguard Worker
vtxAttribSlot(const std::string & attrName) const236*e1eccf28SAndroid Build Coastguard Worker int32_t RsdShaderCache::vtxAttribSlot(const std::string &attrName) const {
237*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ct=0; ct < mCurrent->vtxAttrCount; ct++) {
238*e1eccf28SAndroid Build Coastguard Worker if (attrName == mCurrent->vtxAttrs[ct].name) {
239*e1eccf28SAndroid Build Coastguard Worker return mCurrent->vtxAttrs[ct].slot;
240*e1eccf28SAndroid Build Coastguard Worker }
241*e1eccf28SAndroid Build Coastguard Worker }
242*e1eccf28SAndroid Build Coastguard Worker return -1;
243*e1eccf28SAndroid Build Coastguard Worker }
244*e1eccf28SAndroid Build Coastguard Worker
cleanupVertex(RsdShader * s)245*e1eccf28SAndroid Build Coastguard Worker void RsdShaderCache::cleanupVertex(RsdShader *s) {
246*e1eccf28SAndroid Build Coastguard Worker int32_t numEntries = (int32_t)mEntries.size();
247*e1eccf28SAndroid Build Coastguard Worker uint32_t numShaderIDs = s->getStateBasedIDCount();
248*e1eccf28SAndroid Build Coastguard Worker for (uint32_t sId = 0; sId < numShaderIDs; sId ++) {
249*e1eccf28SAndroid Build Coastguard Worker uint32_t id = s->getStateBasedID(sId);
250*e1eccf28SAndroid Build Coastguard Worker for (int32_t ct = 0; ct < numEntries; ct ++) {
251*e1eccf28SAndroid Build Coastguard Worker if (mEntries[ct]->vtx == id) {
252*e1eccf28SAndroid Build Coastguard Worker glDeleteProgram(mEntries[ct]->program);
253*e1eccf28SAndroid Build Coastguard Worker
254*e1eccf28SAndroid Build Coastguard Worker delete mEntries[ct];
255*e1eccf28SAndroid Build Coastguard Worker mEntries.erase(mEntries.begin() + ct);
256*e1eccf28SAndroid Build Coastguard Worker numEntries = (int32_t)mEntries.size();
257*e1eccf28SAndroid Build Coastguard Worker ct --;
258*e1eccf28SAndroid Build Coastguard Worker }
259*e1eccf28SAndroid Build Coastguard Worker }
260*e1eccf28SAndroid Build Coastguard Worker }
261*e1eccf28SAndroid Build Coastguard Worker }
262*e1eccf28SAndroid Build Coastguard Worker
cleanupFragment(RsdShader * s)263*e1eccf28SAndroid Build Coastguard Worker void RsdShaderCache::cleanupFragment(RsdShader *s) {
264*e1eccf28SAndroid Build Coastguard Worker int32_t numEntries = (int32_t)mEntries.size();
265*e1eccf28SAndroid Build Coastguard Worker uint32_t numShaderIDs = s->getStateBasedIDCount();
266*e1eccf28SAndroid Build Coastguard Worker for (uint32_t sId = 0; sId < numShaderIDs; sId ++) {
267*e1eccf28SAndroid Build Coastguard Worker uint32_t id = s->getStateBasedID(sId);
268*e1eccf28SAndroid Build Coastguard Worker for (int32_t ct = 0; ct < numEntries; ct ++) {
269*e1eccf28SAndroid Build Coastguard Worker if (mEntries[ct]->frag == id) {
270*e1eccf28SAndroid Build Coastguard Worker glDeleteProgram(mEntries[ct]->program);
271*e1eccf28SAndroid Build Coastguard Worker
272*e1eccf28SAndroid Build Coastguard Worker delete mEntries[ct];
273*e1eccf28SAndroid Build Coastguard Worker mEntries.erase(mEntries.begin() + ct);
274*e1eccf28SAndroid Build Coastguard Worker numEntries = (int32_t)mEntries.size();
275*e1eccf28SAndroid Build Coastguard Worker ct --;
276*e1eccf28SAndroid Build Coastguard Worker }
277*e1eccf28SAndroid Build Coastguard Worker }
278*e1eccf28SAndroid Build Coastguard Worker }
279*e1eccf28SAndroid Build Coastguard Worker }
280*e1eccf28SAndroid Build Coastguard Worker
cleanupAll()281*e1eccf28SAndroid Build Coastguard Worker void RsdShaderCache::cleanupAll() {
282*e1eccf28SAndroid Build Coastguard Worker for (uint32_t ct=0; ct < mEntries.size(); ct++) {
283*e1eccf28SAndroid Build Coastguard Worker glDeleteProgram(mEntries[ct]->program);
284*e1eccf28SAndroid Build Coastguard Worker free(mEntries[ct]);
285*e1eccf28SAndroid Build Coastguard Worker }
286*e1eccf28SAndroid Build Coastguard Worker mEntries.clear();
287*e1eccf28SAndroid Build Coastguard Worker }
288