blob: 72d1b02610f325dacc9c7a8915a08d19a7a3760e [file] [log] [blame]
Jason Sams326e0dd2009-05-22 14:03:28 -07001/*
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
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -070017#ifndef ANDROID_RS_BUILD_FOR_HOST
Jason Sams326e0dd2009-05-22 14:03:28 -070018#include "rsContext.h"
Jason Samsc460e552009-11-25 13:22:07 -080019#include <GLES2/gl2.h>
20#include <GLES2/gl2ext.h>
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -070021#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"
Jason Samsc460e552009-11-25 13:22:07 -080028
Jason Sams326e0dd2009-05-22 14:03:28 -070029using namespace android;
30using namespace android::renderscript;
31
Jason Sams4815c0d2009-12-15 12:58:36 -080032Program::Program(Context *rsc) : ObjectBase(rsc)
Jason Sams326e0dd2009-05-22 14:03:28 -070033{
Jason Samsc460e552009-11-25 13:22:07 -080034 mDirty = true;
35 mShaderID = 0;
36 mAttribCount = 0;
37 mUniformCount = 0;
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -070038 mTextureCount = 0;
Jason Samsf2649a92009-09-25 16:37:33 -070039
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -070040 mTextures = NULL;
41 mSamplers = NULL;
Jason Sams4815c0d2009-12-15 12:58:36 -080042 mInputElements = NULL;
43 mOutputElements = NULL;
44 mConstantTypes = NULL;
45 mInputCount = 0;
46 mOutputCount = 0;
47 mConstantCount = 0;
Jason Samsa2cf7552010-03-03 13:03:18 -080048 mIsValid = false;
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -070049 mIsInternal = false;
Jason Sams4815c0d2009-12-15 12:58:36 -080050}
51
52Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
53 const uint32_t * params, uint32_t paramLength) :
54 ObjectBase(rsc)
55{
Jason Sams4815c0d2009-12-15 12:58:36 -080056 mDirty = true;
57 mShaderID = 0;
58 mAttribCount = 0;
59 mUniformCount = 0;
Jason Samsf2e4fa22009-12-15 13:27:04 -080060 mTextureCount = 0;
Jason Sams4815c0d2009-12-15 12:58:36 -080061
62 mInputCount = 0;
63 mOutputCount = 0;
64 mConstantCount = 0;
65
66 for (uint32_t ct=0; ct < paramLength; ct+=2) {
67 if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
68 mInputCount++;
69 }
70 if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
71 mOutputCount++;
72 }
73 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
74 mConstantCount++;
75 }
Jason Samsf2e4fa22009-12-15 13:27:04 -080076 if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) {
77 mTextureCount = params[ct+1];
78 }
Jason Sams4815c0d2009-12-15 12:58:36 -080079 }
80
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -070081 mTextures = new ObjectBaseRef<Allocation>[mTextureCount];
82 mSamplers = new ObjectBaseRef<Sampler>[mTextureCount];
Jason Sams4815c0d2009-12-15 12:58:36 -080083 mInputElements = new ObjectBaseRef<Element>[mInputCount];
84 mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
85 mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
86
87 uint32_t input = 0;
88 uint32_t output = 0;
89 uint32_t constant = 0;
90 for (uint32_t ct=0; ct < paramLength; ct+=2) {
91 if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
92 mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
93 }
94 if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
95 mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
96 }
97 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
98 mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
99 }
100 }
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -0700101 mIsInternal = false;
102 uint32_t internalTokenLen = strlen(RS_SHADER_INTERNAL);
103 if(shaderLength > internalTokenLen &&
104 strncmp(RS_SHADER_INTERNAL, shaderText, internalTokenLen) == 0) {
105 mIsInternal = true;
106 shaderText += internalTokenLen;
107 shaderLength -= internalTokenLen;
108 }
Jason Sams4815c0d2009-12-15 12:58:36 -0800109 mUserShader.setTo(shaderText, shaderLength);
Jason Sams326e0dd2009-05-22 14:03:28 -0700110}
111
112Program::~Program()
113{
Alex Sakhartchouk889fe502010-10-01 10:54:06 -0700114 if(mRSC->props.mLogShaders) {
115 LOGV("Program::~Program with shader id %u", mShaderID);
116 }
117
118 if(mShaderID) {
119 glDeleteShader(mShaderID);
120 }
121
Jason Sams9ebb0c42010-01-12 12:12:28 -0800122 for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) {
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700123 bindAllocation(NULL, NULL, ct);
Jason Sams9ebb0c42010-01-12 12:12:28 -0800124 }
Jason Sams4815c0d2009-12-15 12:58:36 -0800125
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700126 for (uint32_t ct=0; ct < mTextureCount; ct++) {
127 bindTexture(NULL, ct, NULL);
128 bindSampler(NULL, ct, NULL);
129 }
130 delete[] mTextures;
131 delete[] mSamplers;
Jason Sams4815c0d2009-12-15 12:58:36 -0800132 delete[] mInputElements;
133 delete[] mOutputElements;
134 delete[] mConstantTypes;
135 mInputCount = 0;
136 mOutputCount = 0;
137 mConstantCount = 0;
Jason Sams326e0dd2009-05-22 14:03:28 -0700138}
139
140
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700141void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot)
Jason Sams326e0dd2009-05-22 14:03:28 -0700142{
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700143 if (alloc != NULL) {
144 if (slot >= mConstantCount) {
145 LOGE("Attempt to bind alloc at slot %u, on shader id %u, but const count is %u",
146 slot, (uint32_t)this, mConstantCount);
147 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
148 return;
149 }
150 if (!alloc->getType()->isEqual(mConstantTypes[slot].get())) {
151 LOGE("Attempt to bind alloc at slot %u, on shader id %u, but types mismatch",
152 slot, (uint32_t)this);
153 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
154 return;
155 }
156 }
Jason Sams9ebb0c42010-01-12 12:12:28 -0800157 if (mConstants[slot].get() == alloc) {
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700158 return;
159 }
Jason Sams9ebb0c42010-01-12 12:12:28 -0800160 if (mConstants[slot].get()) {
161 mConstants[slot].get()->removeProgramToDirty(this);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700162 }
Jason Sams9ebb0c42010-01-12 12:12:28 -0800163 mConstants[slot].set(alloc);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700164 if (alloc) {
165 alloc->addProgramToDirty(this);
166 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700167 mDirty = true;
168}
169
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700170void Program::bindTexture(Context *rsc, uint32_t slot, Allocation *a)
Jason Sams7dad9c32009-12-17 16:55:08 -0800171{
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700172 if (slot >= mTextureCount) {
173 LOGE("Attempt to bind texture to slot %u but tex count is %u", slot, mTextureCount);
174 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind texture");
Jason Sams7dad9c32009-12-17 16:55:08 -0800175 return;
176 }
177
178 //LOGE("bindtex %i %p", slot, a);
179 mTextures[slot].set(a);
180 mDirty = true;
181}
182
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700183void Program::bindSampler(Context *rsc, uint32_t slot, Sampler *s)
Jason Sams7dad9c32009-12-17 16:55:08 -0800184{
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700185 if (slot >= mTextureCount) {
186 LOGE("Attempt to bind sampler to slot %u but tex count is %u", slot, mTextureCount);
187 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind sampler");
Jason Sams7dad9c32009-12-17 16:55:08 -0800188 return;
189 }
190
191 mSamplers[slot].set(s);
192 mDirty = true;
193}
194
Jason Samsb4d35682010-01-04 16:52:27 -0800195String8 Program::getGLSLInputString() const
196{
197 String8 s;
198 for (uint32_t ct=0; ct < mInputCount; ct++) {
199 const Element *e = mInputElements[ct].get();
200 for (uint32_t field=0; field < e->getFieldCount(); field++) {
201 const Element *f = e->getField(field);
202
203 // Cannot be complex
204 rsAssert(!f->getFieldCount());
205 switch(f->getComponent().getVectorSize()) {
206 case 1: s.append("attribute float ATTRIB_"); break;
207 case 2: s.append("attribute vec2 ATTRIB_"); break;
208 case 3: s.append("attribute vec3 ATTRIB_"); break;
209 case 4: s.append("attribute vec4 ATTRIB_"); break;
210 default:
211 rsAssert(0);
212 }
213
214 s.append(e->getFieldName(field));
215 s.append(";\n");
216 }
217 }
218 return s;
219}
220
221String8 Program::getGLSLOutputString() const
222{
223 return String8();
224}
225
226String8 Program::getGLSLConstantString() const
227{
228 return String8();
229}
230
Jason Sams7dad9c32009-12-17 16:55:08 -0800231
Jason Samsc460e552009-11-25 13:22:07 -0800232void Program::createShader()
233{
234}
Jason Samscfb1d112009-08-05 13:57:03 -0700235
Jason Samscd506532009-12-15 19:10:11 -0800236bool Program::loadShader(Context *rsc, uint32_t type)
Jason Samsc460e552009-11-25 13:22:07 -0800237{
238 mShaderID = glCreateShader(type);
239 rsAssert(mShaderID);
240
Jason Samscd506532009-12-15 19:10:11 -0800241 if (rsc->props.mLogShaders) {
242 LOGV("Loading shader type %x, ID %i", type, mShaderID);
Nick Kralevich8492a702010-05-13 14:46:27 -0700243 LOGV("%s", mShader.string());
Jason Samscd506532009-12-15 19:10:11 -0800244 }
Jason Samsc460e552009-11-25 13:22:07 -0800245
246 if (mShaderID) {
247 const char * ss = mShader.string();
248 glShaderSource(mShaderID, 1, &ss, NULL);
249 glCompileShader(mShaderID);
250
251 GLint compiled = 0;
252 glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
253 if (!compiled) {
254 GLint infoLen = 0;
255 glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
256 if (infoLen) {
257 char* buf = (char*) malloc(infoLen);
258 if (buf) {
259 glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
260 LOGE("Could not compile shader \n%s\n", buf);
261 free(buf);
262 }
263 glDeleteShader(mShaderID);
264 mShaderID = 0;
Jason Samsa2cf7552010-03-03 13:03:18 -0800265 rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
Jason Samsc460e552009-11-25 13:22:07 -0800266 return false;
267 }
268 }
269 }
Jason Samscd506532009-12-15 19:10:11 -0800270
271 if (rsc->props.mLogShaders) {
272 LOGV("--Shader load result %x ", glGetError());
273 }
Jason Samsa2cf7552010-03-03 13:03:18 -0800274 mIsValid = true;
Jason Samsc460e552009-11-25 13:22:07 -0800275 return true;
276}
Jason Samsf2a5d732009-11-30 14:49:55 -0800277
278void Program::setShader(const char *txt, uint32_t len)
279{
280 mUserShader.setTo(txt, len);
281}
282
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700283void Program::appendUserConstants() {
284 for (uint32_t ct=0; ct < mConstantCount; ct++) {
285 const Element *e = mConstantTypes[ct]->getElement();
286 for (uint32_t field=0; field < e->getFieldCount(); field++) {
287 const Element *f = e->getField(field);
288 const char *fn = e->getFieldName(field);
Jason Sams4815c0d2009-12-15 12:58:36 -0800289
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700290 if (fn[0] == '#') {
291 continue;
292 }
293
294 // Cannot be complex
295 rsAssert(!f->getFieldCount());
296 if(f->getType() == RS_TYPE_MATRIX_4X4) {
297 mShader.append("uniform mat4 UNI_");
298 }
299 else if(f->getType() == RS_TYPE_MATRIX_3X3) {
300 mShader.append("uniform mat3 UNI_");
301 }
302 else if(f->getType() == RS_TYPE_MATRIX_2X2) {
303 mShader.append("uniform mat2 UNI_");
304 }
305 else {
306 switch(f->getComponent().getVectorSize()) {
307 case 1: mShader.append("uniform float UNI_"); break;
308 case 2: mShader.append("uniform vec2 UNI_"); break;
309 case 3: mShader.append("uniform vec3 UNI_"); break;
310 case 4: mShader.append("uniform vec4 UNI_"); break;
311 default:
312 rsAssert(0);
313 }
314 }
315
316 mShader.append(fn);
317 mShader.append(";\n");
318 }
319 }
320}
321
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700322void Program::setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment) {
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -0700323 uint32_t uidx = 0;
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700324 for (uint32_t ct=0; ct < mConstantCount; ct++) {
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -0700325 Allocation *alloc = mConstants[ct].get();
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700326 if (!alloc) {
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700327 LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set", (uint32_t)this, ct);
328 rsc->setError(RS_ERROR_BAD_SHADER, "No constant allocation bound");
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700329 continue;
330 }
331
332 const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
333 const Element *e = mConstantTypes[ct]->getElement();
334 for (uint32_t field=0; field < e->getFieldCount(); field++) {
335 const Element *f = e->getField(field);
336 const char *fieldName = e->getFieldName(field);
337 // If this field is padding, skip it
338 if(fieldName[0] == '#') {
339 continue;
340 }
341
342 uint32_t offset = e->getFieldOffsetBytes(field);
343 const float *fd = reinterpret_cast<const float *>(&data[offset]);
344
345 int32_t slot = -1;
346 if(!isFragment) {
347 slot = sc->vtxUniformSlot(uidx);
348 }
349 else {
350 slot = sc->fragUniformSlot(uidx);
351 }
352
Alex Sakhartchouk886f11a2010-09-29 09:49:13 -0700353 if(rsc->props.mLogShadersUniforms) {
354 LOGV("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
355 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700356 if (slot >= 0) {
357 if(f->getType() == RS_TYPE_MATRIX_4X4) {
Alex Sakhartchouk886f11a2010-09-29 09:49:13 -0700358 if(rsc->props.mLogShadersUniforms) {
359 LOGV("Matrix4x4");
360 LOGV("{%f, %f, %f, %f", fd[0], fd[4], fd[8], fd[12]);
361 LOGV(" %f, %f, %f, %f", fd[1], fd[5], fd[9], fd[13]);
362 LOGV(" %f, %f, %f, %f", fd[2], fd[6], fd[10], fd[14]);
363 LOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]);
364 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700365 glUniformMatrix4fv(slot, 1, GL_FALSE, fd);
366 }
367 else if(f->getType() == RS_TYPE_MATRIX_3X3) {
Alex Sakhartchouk886f11a2010-09-29 09:49:13 -0700368 if(rsc->props.mLogShadersUniforms) {
369 LOGV("Matrix3x3");
370 LOGV("{%f, %f, %f", fd[0], fd[3], fd[6]);
371 LOGV(" %f, %f, %f", fd[1], fd[4], fd[7]);
372 LOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]);
373 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700374 glUniformMatrix3fv(slot, 1, GL_FALSE, fd);
375 }
376 else if(f->getType() == RS_TYPE_MATRIX_2X2) {
Alex Sakhartchouk886f11a2010-09-29 09:49:13 -0700377 if(rsc->props.mLogShadersUniforms){
378 LOGV("Matrix2x2");
379 LOGV("{%f, %f", fd[0], fd[2]);
380 LOGV(" %f, %f}", fd[1], fd[3]);
381 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700382 glUniformMatrix2fv(slot, 1, GL_FALSE, fd);
383 }
384 else {
385 switch(f->getComponent().getVectorSize()) {
386 case 1:
Alex Sakhartchouk886f11a2010-09-29 09:49:13 -0700387 if(rsc->props.mLogShadersUniforms) {
388 LOGV("Uniform 1 = %f", fd[0]);
389 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700390 glUniform1fv(slot, 1, fd);
391 break;
392 case 2:
Alex Sakhartchouk886f11a2010-09-29 09:49:13 -0700393 if(rsc->props.mLogShadersUniforms) {
394 LOGV("Uniform 2 = %f %f", fd[0], fd[1]);
395 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700396 glUniform2fv(slot, 1, fd);
397 break;
398 case 3:
Alex Sakhartchouk886f11a2010-09-29 09:49:13 -0700399 if(rsc->props.mLogShadersUniforms) {
400 LOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
401 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700402 glUniform3fv(slot, 1, fd);
403 break;
404 case 4:
Alex Sakhartchouk886f11a2010-09-29 09:49:13 -0700405 if(rsc->props.mLogShadersUniforms) {
406 LOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
407 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700408 glUniform4fv(slot, 1, fd);
409 break;
410 default:
411 rsAssert(0);
412 }
413 }
414 }
415 uidx ++;
416 }
417 }
418}
419
420void Program::initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix)
421{
422 rsAssert(e->getFieldCount());
423 for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
424 const Element *ce = e->getField(ct);
425 if (ce->getFieldCount()) {
426 initAddUserElement(ce, names, count, prefix);
427 }
428 else if(e->getFieldName(ct)[0] != '#') {
429 String8 tmp(prefix);
430 tmp.append(e->getFieldName(ct));
431 names[*count].setTo(tmp.string());
432 (*count)++;
433 }
434 }
435}
Jason Sams4815c0d2009-12-15 12:58:36 -0800436
437namespace android {
438namespace renderscript {
439
440
441void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants)
442{
443 Program *p = static_cast<Program *>(vp);
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700444 p->bindAllocation(rsc, static_cast<Allocation *>(constants), slot);
Jason Sams4815c0d2009-12-15 12:58:36 -0800445}
446
Jason Sams7dad9c32009-12-17 16:55:08 -0800447void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a)
448{
449 Program *p = static_cast<Program *>(vpf);
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700450 p->bindTexture(rsc, slot, static_cast<Allocation *>(a));
Jason Sams7dad9c32009-12-17 16:55:08 -0800451}
452
453void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s)
454{
455 Program *p = static_cast<Program *>(vpf);
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700456 p->bindSampler(rsc, slot, static_cast<Sampler *>(s));
Jason Sams7dad9c32009-12-17 16:55:08 -0800457}
Jason Sams4815c0d2009-12-15 12:58:36 -0800458
459}
460}
461