ProgVar * GlesCreateProgVarParam(ShaderProgram * program, Type * type, const char * name, GLsizei length) { ProgVar * var = GlesMemoryPoolAllocate(program->memory, sizeof(ProgVarParam)); var->base.kind = ProgVarKindParam; var->base.id = program->numVars++; var->param.named.base.type = type; var->param.named.name = GlesMemoryPoolAllocate(program->memory, length); GlesMemcpy(var->param.named.name, name, length); var->param.named.length = length; var->param.named.base.next = program->param; program->param = var; return var; }
/** * Generate a branch or subroutine call instruction. * * @param gen reference to code generator object * @param op instruction opcode * @param target branch target * @param cond branch condition * @param selectX selector for 1st condition flag * @param selectY selector for 2nd condition flag * @param selectZ selector for 3rd condition flag * @param selectW selector for 4th condition flag */ void GlesGenInstBranch(ShaderProgramGenerator * gen, Opcode op, Label * target, Cond cond, GLubyte selectX, GLubyte selectY, GLubyte selectZ, GLubyte selectW) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(target); gen->instructionCount++; if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstBranch)); InitInstBranch(&inst->branch, op, target, cond, selectX, selectY, selectZ, selectW); AppendInst(gen->currentList->tail, inst); }
/** * Generate a texture access instruction. * * @param gen reference to code generator object * @param op instruction opcode * @param prec precision modifier * @param target texture target to use * @param dst destination * @param src texture coordinate vector * @param sampler texture sampler variable to access texture memory * @param offset offset for sampler array */ void GlesGenInstTex(ShaderProgramGenerator * gen, Opcode op, Precision prec, TextureTarget target, const DstReg * dst, const SrcReg * src, ProgVar * sampler, GLsizeiptr offset) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(dst); GLES_ASSERT(src); GLES_ASSERT(sampler); gen->instructionCount++; if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstTex)); InitInstTex(&inst->tex, op, prec, target, dst, src, sampler, offset); AppendInst(gen->currentList->tail, inst); }
/** * Generate an extended swizzle (SWZ) instruction. * * @param gen reference to code generator object * @param op instruction opcode * @param prec precision flags for instruction * @param dst destination * @param src source operand * @param optionX swizzle selector for x coordinate * @param optionY swizzle selector for y coordinate * @param optionZ swizzle selector for z coordinate * @param optionW swizzle selector for w coordinate */ void GlesGenInstSwizzle(ShaderProgramGenerator * gen, Opcode op, Precision prec, const DstReg * dst, SrcRef src, ExtSwizzleOption optionX, ExtSwizzleOption optionY, ExtSwizzleOption optionZ, ExtSwizzleOption optionW) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(dst); GLES_ASSERT(src.base); gen->instructionCount++; if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstSwizzle)); InitInstSwizzle(&inst->swizzle, op, prec, dst, src, optionX, optionY, optionZ, optionW); AppendInst(gen->currentList->tail, inst); }
Scope * GlesScopeCreate(struct MemoryPool * pool, Scope * parent) { Scope * scope = GlesMemoryPoolAllocate(pool, sizeof(Scope)); scope->parent = parent; if (parent) { /* inherit default precisions from parent */ scope->defaultIntPrec = parent->defaultIntPrec; scope->defaultFltPrec = parent->defaultFltPrec; scope->defaultS2DPrec = parent->defaultS2DPrec; scope->defaultS3DPrec = parent->defaultS3DPrec; scope->defaultSCubPrec = parent->defaultSCubPrec; } else { /* undefined default precisions; will load initial values into gloval scope */ scope->defaultIntPrec = PrecisionUndefined; scope->defaultFltPrec = PrecisionUndefined; scope->defaultS2DPrec = PrecisionUndefined; scope->defaultS3DPrec = PrecisionUndefined; scope->defaultSCubPrec = PrecisionUndefined; } return scope; }
ShaderProgram * GlesCreateShaderProgram(MemoryPool * pool) { ShaderProgram * result = GlesMemoryPoolAllocate(pool, sizeof(ShaderProgram)); result->memory = pool; return result; }
/** * Generate a binary instruction. * * @param gen reference to code generator object * @param op instruction opcode * @param prec precision flags for instruction * @param dst destination * @param arg0 source operand 0 * @param arg1 source operand 1 * @param arg2 source operand 2 */ void GlesGenInstTernary(ShaderProgramGenerator * gen, Opcode op, Precision prec, const DstReg * dst, const SrcReg * arg0, const SrcReg * arg1, const SrcReg * arg2) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(dst); GLES_ASSERT(arg0); GLES_ASSERT(arg1); GLES_ASSERT(arg2); gen->instructionCount++; if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstTernary)); InitInstTernary(&inst->ternary, op, prec, dst, arg0, arg1, arg2); AppendInst(gen->currentList->tail, inst); }
/** * Generate an conditional instruction. * * @param gen reference to code generator object * @param op instruction opcode * @param cond branch condition * @param selectX selector for 1st condition flag * @param selectY selector for 2nd condition flag * @param selectZ selector for 3rd condition flag * @param selectW selector for 4th condition flag */ void GlesGenInstCond(struct ShaderProgramGenerator * gen, Opcode op, Cond cond, GLubyte selectX, GLubyte selectY, GLubyte selectZ, GLubyte selectW) { Inst * inst; GLES_ASSERT(gen); /* this is a special case, since an IF with a constant condition will be removed */ if (cond != CondT && cond != CondF) { gen->instructionCount++; } if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstCond)); InitInstCond(&inst->cond, op, cond, selectX, selectY, selectZ, selectW); AppendInst(gen->currentList->tail, inst); }
/** * Begin a for loop with a constant number of iterations * * @param compiler reference to compiler object * @param loopIndex reference to the loop index variable * @param initial reference to the initial value of the loop index variable * @param boundary reference to the boundary value for the loop index * @param increment reference to the increment value for the loop index * @param condition the condition operation used in the loop condition clause * * @return GL_TRUE if successful, otherwise GL_FALSE */ GLboolean GlesCreateStmntFor(Compiler * compiler, union Symbol * loopIndex, Expression * initial, Expression * boundary, Expression * increment, Cond condition) { GLint numIterations; SrcReg regSrc; ForLoop * forLoop; if (loopIndex == NULL || loopIndex->base.type->base.kind != TypeInt && loopIndex->base.type->base.kind != TypeFloat) { /* loop index must be of type int or float */ GlesCompileError(compiler, ErrX0004); return GL_FALSE; } if (initial == NULL || initial->base.type->base.kind != loopIndex->base.type->base.kind || initial->base.kind != ExpressionKindConstant) { /* loop index variable must be initialized... */ GlesCompileError(compiler, ErrX0006); return GL_FALSE; } if (boundary == NULL || boundary->base.type->base.kind != loopIndex->base.type->base.kind || boundary->base.kind != ExpressionKindConstant || increment == NULL || increment->base.type->base.kind != loopIndex->base.type->base.kind || increment->base.kind != ExpressionKindConstant) { /* loop index variable must be incremented... */ GlesCompileError(compiler, ErrX0007); return GL_FALSE; } numIterations = CalcNumIterations(initial, boundary, increment, condition); if (numIterations == ~0 || numIterations == 0) { /* loop must be properly bounded... */ GlesCompileError(compiler, ErrX0008); return GL_FALSE; } GlesGenFetch(compiler, ®Src, GlesCreateExprIntConstant(compiler, numIterations), NULL); GlesGenInstSrc(&compiler->generator, OpcodeREP, ®Src); forLoop = GlesMemoryPoolAllocate(compiler->moduleMemory, sizeof(ForLoop)); forLoop->outer = compiler->currentLoop; compiler->currentLoop = forLoop; forLoop->continueFlag = GlesDeclareTempVariable(compiler, GlesBasicType(TypeBool, PrecisionUndefined)); /* initialize the continue flag for this loop with GL_FALSE at the beginning of the body */ GlesCreateExprAssign(compiler, GlesCreateExprReference(compiler, forLoop->continueFlag->base.type, forLoop->continueFlag, NULL, 0), GlesCreateExprBoolConstant(compiler, GL_FALSE)); return GL_TRUE; }
/** * Create a new label structure. * * @param gen reference to code generator object * @param sym (optional) associated source program symbol * * @return newly allocated label structure attached to generated program */ Label * GlesCreateLabel(struct ShaderProgramGenerator * gen, union Symbol * sym) { Label * label = GlesMemoryPoolAllocate(gen->result->memory, sizeof(Label)); label->next = gen->result->labels; label->symbol = sym; gen->result->labels = label; return label; }
ProgVarAddr * GlesCreateProgVarAddr(ShaderProgram * program) { ProgVarAddr * var = GlesMemoryPoolAllocate(program->memory, sizeof(ProgVarAddr)); var->next = program->addr; var->id = program->numAddrVars++; program->addr = var; return var; }
ProgVar * GlesCreateProgVarTemp(ShaderProgram * program, Type * type) { ProgVar * var = GlesMemoryPoolAllocate(program->memory, sizeof(ProgVarTemp)); var->base.kind = ProgVarKindTemp; var->base.type = type; var->base.next = program->temp; var->base.id = program->numVars++; program->temp = var; return var; }
char * GlesCompoundName(struct MemoryPool * pool, const char * base, GLsizei baseLength, const char * field, GLsizei fieldLength) { GLsizeiptr length = baseLength + fieldLength + 1; char * name = GlesMemoryPoolAllocate(pool, length); GlesMemcpy(name, base, baseLength); name[baseLength] = '.'; GlesMemcpy(name + baseLength + 1, field, fieldLength); return name; }
SymbolArray * GlesSymbolArrayCreate(struct MemoryPool * pool) { GLsizeiptr size = sizeof(struct SymbolArray) + sizeof(Symbol *) * SYMBOL_ARRAY_INIT_SIZE; SymbolArray * array = GlesMemoryPoolAllocate(pool, size); if (array) { array->allocated = SYMBOL_ARRAY_INIT_SIZE; array->used = 0; } return array; }
ProgVar * GlesCreateProgVarConst(ShaderProgram * program, Constant * constant, Type * type) { GLsizei hash = GlesHashConstant(constant, type) % GLES_CONSTANT_HASH; ProgVar * var; for (var = program->constants[hash]; var; var = var->base.next) { if (GlesCompareConstant(var->constant.values, constant, type)) { return var; } } var = GlesMemoryPoolAllocate(program->memory, sizeof(ProgVarConst)); var->base.kind = ProgVarKindConst; var->base.type = type; var->base.id = program->numVars++; var->constant.values = GlesMemoryPoolAllocate(program->memory, sizeof(Constant) * type->base.size); GlesMemcpy(var->constant.values, constant, sizeof(Constant) * type->base.size); var->base.next = program->constants[hash]; program->constants[hash] = var; return var; }
SymbolArray * GlesSymbolArrayGrow(struct MemoryPool * pool, SymbolArray * old) { GLsizeiptr newSize = old->allocated * 2; GLsizeiptr size = sizeof(struct SymbolArray) + sizeof(Symbol *) * newSize; SymbolArray * array = GlesMemoryPoolAllocate(pool, size); if (array) { array->allocated = newSize; array->used = old->used; GlesMemcpy(array->values, old->values, old->used * sizeof(Symbol *)); } return array; }
/** * Generate a base instruction. * * @param gen reference to code generator object * @param op instruction opcode */ void GlesGenInstBase(ShaderProgramGenerator * gen, Opcode op) { Inst * inst; GLES_ASSERT(gen); if (!gen->currentList) { return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstBase)); InitInstBase(&inst->base, InstKindBase, op); AppendInst(gen->currentList->tail, inst); }
/** * Generate an instruction that takes a vector argument but does not * have any result register. * * @param gen reference to code generator object * @param op instruction opcode * @param src source operand */ void GlesGenInstSrc(struct ShaderProgramGenerator * gen, Opcode op, const SrcReg * src) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(src); gen->instructionCount++; if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstSrc)); InitInstSrc(&inst->src, op, src); AppendInst(gen->currentList->tail, inst); }
/** * Create a new instruction sequence basic block. * * @param gen reference to compiler object * * @return a newly generated block appended to the current list of blocks */ Block * GlesCreateBlock(ShaderProgramGenerator * gen) { Block * result; if (!gen->currentList) { return NULL; } result = GlesMemoryPoolAllocate(gen->result->memory, sizeof(Block)); result->id = gen->result->numBlocks++; result->prev = gen->currentList->tail; if (gen->currentList->tail) { GLES_ASSERT(gen->currentList->head); gen->currentList->tail->next = result; } else { GLES_ASSERT(!gen->currentList->head); gen->currentList->head = result; } gen->currentList->tail = result; return result; }
/** * Generate memory access instruction (only used in low level IL). * * @param gen reference to code generator object * @param op instruction opcode * @param dst destination * @param src source operand * @param index index to use, can be NULL * @param offset constant offset to apply */ void GlesGenInstMemory(ShaderProgramGenerator * gen, Opcode op, const DstReg * dst, const SrcReg * src, const SrcReg * index, GLsizeiptr offset) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(dst); if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ gen->constViolation |= gen->constExpression; return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstMemory)); InitInstMemory(&inst->memory, op, dst, src, index, offset); AppendInst(gen->currentList->tail, inst); }
Symbol * GlesSymbolCreate(struct MemoryPool * pool, Scope * scope, const char * name, GLsizei length, GLsizei hash, Type * type, Qualifier qualifier) { GLsizeiptr size; Symbol * symbol; switch (qualifier) { case QualifierConstant: /* constant value */ case QualifierVariable: /* general variable */ case QualifierAttrib: /* vertex attrib */ case QualifierUniform: /* uniform value */ case QualifierVarying: /* varying value */ size = sizeof(SymbolVariable); break; case QualifierField: /* struct member */ size = sizeof(SymbolField); break; case QualifierFunction: /* user-defined function */ size = sizeof(SymbolFunction); break; case QualifierParameterIn: /* input parameter */ case QualifierParameterOut: /* output parameter */ case QualifierParameterInOut: /* input/output parameter */ size = sizeof(SymbolParameter); break; case QualifierTypeName: /* type name */ case QualifierPosition: /* gl_Position variable */ case QualifierPointSize: /* gl_PointSize */ case QualifierFragCoord: /* gl_FragCoord */ case QualifierFrontFacing: /* gl_FrontFacing */ case QualifierFragColor: /* gl_FragColor */ case QualifierFragData: /* gl_FragData */ case QualifierPointCoord: /* gl_PointCoord */ size = sizeof(SymbolBase); break; default: GLES_ASSERT(GL_FALSE); return NULL; } symbol = (Symbol *) GlesMemoryPoolAllocate(pool, size); symbol->base.name = (char *) GlesMemoryPoolAllocate(pool, length); GlesMemcpy(symbol->base.name, name, length); symbol->base.length = length; symbol->base.type = type; symbol->base.qualifier = qualifier; symbol->base.scope = scope; /*implied: symbol->base.next = NULL;*/ if (hash == ~0) { hash = GlesSymbolHash(name, length); } symbol->base.next = scope->buckets[hash]; scope->buckets[hash] = symbol; return symbol; }