📄 prog_execute.c
字号:
else { return GL_FALSE; }}/** * Store 4 floats into a register. Observe the instructions saturate and * set-condition-code flags. */static voidstore_vector4(const struct prog_instruction *inst, struct gl_program_machine *machine, const GLfloat value[4]){ const struct prog_dst_register *dest = &(inst->DstReg); const GLboolean clamp = inst->SaturateMode == SATURATE_ZERO_ONE; GLfloat *dstReg; GLfloat dummyReg[4]; GLfloat clampedValue[4]; GLuint writeMask = dest->WriteMask; switch (dest->File) { case PROGRAM_OUTPUT: ASSERT(dest->Index < MAX_PROGRAM_OUTPUTS); dstReg = machine->Outputs[dest->Index]; break; case PROGRAM_TEMPORARY: ASSERT(dest->Index < MAX_PROGRAM_TEMPS); dstReg = machine->Temporaries[dest->Index]; break; case PROGRAM_WRITE_ONLY: dstReg = dummyReg; return; default: _mesa_problem(NULL, "bad register file in store_vector4(fp)"); return; }#if 0 if (value[0] > 1.0e10 || IS_INF_OR_NAN(value[0]) || IS_INF_OR_NAN(value[1]) || IS_INF_OR_NAN(value[2]) || IS_INF_OR_NAN(value[3])) printf("store %g %g %g %g\n", value[0], value[1], value[2], value[3]);#endif if (clamp) { clampedValue[0] = CLAMP(value[0], 0.0F, 1.0F); clampedValue[1] = CLAMP(value[1], 0.0F, 1.0F); clampedValue[2] = CLAMP(value[2], 0.0F, 1.0F); clampedValue[3] = CLAMP(value[3], 0.0F, 1.0F); value = clampedValue; } if (dest->CondMask != COND_TR) { /* condition codes may turn off some writes */ if (writeMask & WRITEMASK_X) { if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 0)], dest->CondMask)) writeMask &= ~WRITEMASK_X; } if (writeMask & WRITEMASK_Y) { if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 1)], dest->CondMask)) writeMask &= ~WRITEMASK_Y; } if (writeMask & WRITEMASK_Z) { if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 2)], dest->CondMask)) writeMask &= ~WRITEMASK_Z; } if (writeMask & WRITEMASK_W) { if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 3)], dest->CondMask)) writeMask &= ~WRITEMASK_W; } } if (writeMask & WRITEMASK_X) dstReg[0] = value[0]; if (writeMask & WRITEMASK_Y) dstReg[1] = value[1]; if (writeMask & WRITEMASK_Z) dstReg[2] = value[2]; if (writeMask & WRITEMASK_W) dstReg[3] = value[3]; if (inst->CondUpdate) { if (writeMask & WRITEMASK_X) machine->CondCodes[0] = generate_cc(value[0]); if (writeMask & WRITEMASK_Y) machine->CondCodes[1] = generate_cc(value[1]); if (writeMask & WRITEMASK_Z) machine->CondCodes[2] = generate_cc(value[2]); if (writeMask & WRITEMASK_W) machine->CondCodes[3] = generate_cc(value[3]);#if DEBUG_PROG printf("CondCodes=(%s,%s,%s,%s) for:\n", _mesa_condcode_string(machine->CondCodes[0]), _mesa_condcode_string(machine->CondCodes[1]), _mesa_condcode_string(machine->CondCodes[2]), _mesa_condcode_string(machine->CondCodes[3]));#endif }}/** * Execute the given vertex/fragment program. * * \param ctx rendering context * \param program the program to execute * \param machine machine state (must be initialized) * \return GL_TRUE if program completed or GL_FALSE if program executed KIL. */GLboolean_mesa_execute_program(GLcontext * ctx, const struct gl_program *program, struct gl_program_machine *machine){ const GLuint numInst = program->NumInstructions; const GLuint maxExec = 10000; GLint pc, numExec = 0; machine->CurProgram = program; if (DEBUG_PROG) { printf("execute program %u --------------------\n", program->Id); }#if FEATURE_MESA_program_debug CurrentMachine = machine;#endif if (program->Target == GL_VERTEX_PROGRAM_ARB) { machine->EnvParams = ctx->VertexProgram.Parameters; } else { machine->EnvParams = ctx->FragmentProgram.Parameters; } for (pc = 0; pc < numInst; pc++) { const struct prog_instruction *inst = program->Instructions + pc;#if FEATURE_MESA_program_debug if (ctx->FragmentProgram.CallbackEnabled && ctx->FragmentProgram.Callback) { ctx->FragmentProgram.CurrentPosition = inst->StringPos; ctx->FragmentProgram.Callback(program->Target, ctx->FragmentProgram.CallbackData); }#endif if (DEBUG_PROG) { _mesa_print_instruction(inst); } switch (inst->Opcode) { case OPCODE_ABS: { GLfloat a[4], result[4]; fetch_vector4(&inst->SrcReg[0], machine, a); result[0] = FABSF(a[0]); result[1] = FABSF(a[1]); result[2] = FABSF(a[2]); result[3] = FABSF(a[3]); store_vector4(inst, machine, result); } break; case OPCODE_ADD: { GLfloat a[4], b[4], result[4]; fetch_vector4(&inst->SrcReg[0], machine, a); fetch_vector4(&inst->SrcReg[1], machine, b); result[0] = a[0] + b[0]; result[1] = a[1] + b[1]; result[2] = a[2] + b[2]; result[3] = a[3] + b[3]; store_vector4(inst, machine, result); if (DEBUG_PROG) { printf("ADD (%g %g %g %g) = (%g %g %g %g) + (%g %g %g %g)\n", result[0], result[1], result[2], result[3], a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]); } } break; case OPCODE_ARL: { GLfloat t[4]; fetch_vector4(&inst->SrcReg[0], machine, t); machine->AddressReg[0][0] = (GLint) FLOORF(t[0]); } break; case OPCODE_BGNLOOP: /* no-op */ break; case OPCODE_ENDLOOP: /* subtract 1 here since pc is incremented by for(pc) loop */ pc = inst->BranchTarget - 1; /* go to matching BNGLOOP */ break; case OPCODE_BGNSUB: /* begin subroutine */ break; case OPCODE_ENDSUB: /* end subroutine */ break; case OPCODE_BRA: /* branch (conditional) */ /* fall-through */ case OPCODE_BRK: /* break out of loop (conditional) */ /* fall-through */ case OPCODE_CONT: /* continue loop (conditional) */ if (eval_condition(machine, inst)) { /* take branch */ /* Subtract 1 here since we'll do pc++ at end of for-loop */ pc = inst->BranchTarget - 1; } break; case OPCODE_CAL: /* Call subroutine (conditional) */ if (eval_condition(machine, inst)) { /* call the subroutine */ if (machine->StackDepth >= MAX_PROGRAM_CALL_DEPTH) { return GL_TRUE; /* Per GL_NV_vertex_program2 spec */ } machine->CallStack[machine->StackDepth++] = pc + 1; /* next inst */ /* Subtract 1 here since we'll do pc++ at end of for-loop */ pc = inst->BranchTarget - 1; } break; case OPCODE_CMP: { GLfloat a[4], b[4], c[4], result[4]; fetch_vector4(&inst->SrcReg[0], machine, a); fetch_vector4(&inst->SrcReg[1], machine, b); fetch_vector4(&inst->SrcReg[2], machine, c); result[0] = a[0] < 0.0F ? b[0] : c[0]; result[1] = a[1] < 0.0F ? b[1] : c[1]; result[2] = a[2] < 0.0F ? b[2] : c[2]; result[3] = a[3] < 0.0F ? b[3] : c[3]; store_vector4(inst, machine, result); } break; case OPCODE_COS: { GLfloat a[4], result[4]; fetch_vector1(&inst->SrcReg[0], machine, a); result[0] = result[1] = result[2] = result[3] = (GLfloat) _mesa_cos(a[0]); store_vector4(inst, machine, result); } break; case OPCODE_DDX: /* Partial derivative with respect to X */ { GLfloat result[4]; fetch_vector4_deriv(ctx, &inst->SrcReg[0], machine, 'X', result); store_vector4(inst, machine, result); } break; case OPCODE_DDY: /* Partial derivative with respect to Y */ { GLfloat result[4]; fetch_vector4_deriv(ctx, &inst->SrcReg[0], machine, 'Y', result); store_vector4(inst, machine, result); } break; case OPCODE_DP3: { GLfloat a[4], b[4], result[4]; fetch_vector4(&inst->SrcReg[0], machine, a); fetch_vector4(&inst->SrcReg[1], machine, b); result[0] = result[1] = result[2] = result[3] = DOT3(a, b); store_vector4(inst, machine, result); if (DEBUG_PROG) { printf("DP3 %g = (%g %g %g) . (%g %g %g)\n", result[0], a[0], a[1], a[2], b[0], b[1], b[2]); } } break; case OPCODE_DP4: { GLfloat a[4], b[4], result[4]; fetch_vector4(&inst->SrcReg[0], machine, a); fetch_vector4(&inst->SrcReg[1], machine, b); result[0] = result[1] = result[2] = result[3] = DOT4(a, b); store_vector4(inst, machine, result); if (DEBUG_PROG) { printf("DP4 %g = (%g, %g %g %g) . (%g, %g %g %g)\n", result[0], a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]); } } break; case OPCODE_DPH: { GLfloat a[4], b[4], result[4]; fetch_vector4(&inst->SrcReg[0], machine, a); fetch_vector4(&inst->SrcReg[1], machine, b); result[0] = result[1] = result[2] = result[3] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + b[3]; store_vector4(inst, machine, result); } break; case OPCODE_DST: /* Distance vector */ { GLfloat a[4], b[4], result[4]; fetch_vector4(&inst->SrcReg[0], machine, a); fetch_vector4(&inst->SrcReg[1], machine, b); result[0] = 1.0F; result[1] = a[1] * b[1]; result[2] = a[2]; result[3] = b[3]; store_vector4(inst, machine, result); } break; case OPCODE_EXP: { GLfloat t[4], q[4], floor_t0; fetch_vector1(&inst->SrcReg[0], machine, t); floor_t0 = FLOORF(t[0]); if (floor_t0 > FLT_MAX_EXP) { SET_POS_INFINITY(q[0]); SET_POS_INFINITY(q[2]); } else if (floor_t0 < FLT_MIN_EXP) { q[0] = 0.0F; q[2] = 0.0F; } else { q[0] = LDEXPF(1.0, (int) floor_t0); /* Note: GL_NV_vertex_program expects * result.z = result.x * APPX(result.y) * We do what the ARB extension says. */ q[2] = (GLfloat) pow(2.0, t[0]); } q[1] = t[0] - floor_t0; q[3] = 1.0F; store_vector4( inst, machine, q ); } break; case OPCODE_EX2: /* Exponential base 2 */ { GLfloat a[4], result[4]; fetch_vector1(&inst->SrcReg[0], machine, a); result[0] = result[1] = result[2] = result[3] = (GLfloat) _mesa_pow(2.0, a[0]); store_vector4(inst, machine, result); } break; case OPCODE_FLR: { GLfloat a[4], result[4]; fetch_vector4(&inst->SrcReg[0], machine, a); result[0] = FLOORF(a[0]); result[1] = FLOORF(a[1]); result[2] = FLOORF(a[2]); result[3] = FLOORF(a[3]); store_vector4(inst, machine, result); } break; case OPCODE_FRC: { GLfloat a[4], result[4]; fetch_vector4(&inst->SrcReg[0], machine, a); result[0] = a[0] - FLOORF(a[0]); result[1] = a[1] - FLOORF(a[1]); result[2] = a[2] - FLOORF(a[2]); result[3] = a[3] - FLOORF(a[3]); store_vector4(inst, machine, result); } break; case OPCODE_IF: { GLboolean cond; /* eval condition */ if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { GLfloat a[4]; fetch_vector1(&inst->SrcReg[0], machine, a); cond = (a[0] != 0.0); } else { cond = eval_condition(machine, inst); } if (DEBUG_PROG) { printf("IF: %d\n", cond); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -