From e0584dab80bac90f383ea3f2f38182e6ae1d3bc7 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 25 May 2008 03:35:38 -0400 Subject: [PATCH] Initial work on ARB1 profile. Not even close to complete. --HG-- branch : trunk --- mojoshader.c | 704 ++++++++++++++++++++++++++++++++++++++++++++ mojoshader.h | 5 + mojoshader_opengl.c | 142 +++++++-- 3 files changed, 826 insertions(+), 25 deletions(-) diff --git a/mojoshader.c b/mojoshader.c index 8b211d42..e7cac67a 100644 --- a/mojoshader.c +++ b/mojoshader.c @@ -49,6 +49,10 @@ #define SUPPORT_PROFILE_GLSL 1 #endif +#ifndef SUPPORT_PROFILE_ARB1 +#define SUPPORT_PROFILE_ARB1 1 +#endif + // Get basic wankery out of the way here... @@ -3281,6 +3285,702 @@ static void emit_GLSL_RESERVED(Context *ctx) +#if !SUPPORT_PROFILE_ARB1 +#define PROFILE_EMITTER_ARB1(op) +#else +#undef AT_LEAST_ONE_PROFILE +#define AT_LEAST_ONE_PROFILE 1 +#define PROFILE_EMITTER_ARB1(op) emit_ARB1_##op, + +static const char *make_ARB1_srcarg_string_in_buf(Context *ctx, + const SourceArgInfo *arg, + char *buf, size_t buflen) +{ + const char *premod_str = ""; + const char *postmod_str = ""; + switch (arg->src_mod) + { + case SRCMOD_NEGATE: + premod_str = "-"; + break; + + case SRCMOD_BIASNEGATE: + premod_str = "-"; + // fall through. + case SRCMOD_BIAS: + fail(ctx, "SRCMOD_BIAS currently unsupported in arb1"); + postmod_str = "_bias"; + break; + + case SRCMOD_SIGNNEGATE: + premod_str = "-"; + // fall through. + case SRCMOD_SIGN: + fail(ctx, "SRCMOD_SIGN currently unsupported in arb1"); + postmod_str = "_bx2"; + break; + + case SRCMOD_COMPLEMENT: + fail(ctx, "SRCMOD_COMPLEMENT currently unsupported in arb1"); + premod_str = "1-"; + break; + + case SRCMOD_X2NEGATE: + premod_str = "-"; + // fall through. + case SRCMOD_X2: + fail(ctx, "SRCMOD_X2 currently unsupported in arb1"); + postmod_str = "_x2"; + break; + + case SRCMOD_DZ: + fail(ctx, "SRCMOD_DZ currently unsupported in arb1"); + postmod_str = "_dz"; + break; + + case SRCMOD_DW: + fail(ctx, "SRCMOD_DW currently unsupported in arb1"); + postmod_str = "_dw"; + break; + + case SRCMOD_ABSNEGATE: + premod_str = "-"; + // fall through. + case SRCMOD_ABS: + fail(ctx, "SRCMOD_ABS currently unsupported in arb1"); + postmod_str = "_abs"; + break; + + case SRCMOD_NOT: + fail(ctx, "SRCMOD_NOT currently unsupported in arb1"); + premod_str = "!"; + break; + + case SRCMOD_NONE: + case SRCMOD_TOTAL: + break; // stop compiler whining. + } // switch + + + char regnum_str[16]; + const char *regtype_str = get_D3D_register_string(ctx, arg->regtype, + arg->regnum, regnum_str, + sizeof (regnum_str)); + + if (regtype_str == NULL) + { + fail(ctx, "Unknown source register type."); + return ""; + } // if + + const char *rel_lbracket = ""; + const char *rel_rbracket = ""; + char rel_swizzle[4] = { '\0' }; + char rel_regnum_str[16] = { '\0' }; + const char *rel_regtype_str = ""; + if (arg->relative) + { + rel_swizzle[0] = '.'; + rel_swizzle[1] = swizzle_channels[arg->relative_component]; + rel_swizzle[2] = '\0'; + rel_lbracket = "["; + rel_rbracket = "]"; + rel_regtype_str = get_D3D_register_string(ctx, arg->relative_regtype, + arg->relative_regnum, + rel_regnum_str, + sizeof (rel_regnum_str)); + + if (regtype_str == NULL) + { + fail(ctx, "Unknown relative source register type."); + return ""; + } // if + } // if + + char swizzle_str[6]; + int i = 0; + const int scalar = scalar_register(arg->regtype, arg->regnum); + if (!scalar && !no_swizzle(arg->swizzle)) + { + swizzle_str[i++] = '.'; + + // .xxxx is the same as .x, but .xx is illegal...scalar or full! + if (replicate_swizzle(arg->swizzle)) + swizzle_str[i++] = swizzle_channels[arg->swizzle_x]; + else + { + swizzle_str[i++] = swizzle_channels[arg->swizzle_x]; + swizzle_str[i++] = swizzle_channels[arg->swizzle_y]; + swizzle_str[i++] = swizzle_channels[arg->swizzle_z]; + swizzle_str[i++] = swizzle_channels[arg->swizzle_w]; + } // else + } // if + swizzle_str[i] = '\0'; + assert(i < sizeof (swizzle_str)); + + snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s", + premod_str, regtype_str, regnum_str, postmod_str, + rel_lbracket, rel_regtype_str, rel_regnum_str, rel_swizzle, + rel_rbracket, swizzle_str); + // !!! FIXME: make sure the scratch buffer was large enough. + return buf; +} // make_ARB1_srcarg_string_in_buf + + +static const char *make_ARB1_destarg_string(Context *ctx) +{ + const DestArgInfo *arg = &ctx->dest_arg; + + const char *result_shift_str = ""; + if (arg->result_shift != 0x0) + { + fail(ctx, "dest register shifting currently unsupported in arb1"); + return ""; + } // if + + switch (arg->result_shift) + { + case 0x1: result_shift_str = "_x2"; break; + case 0x2: result_shift_str = "_x4"; break; + case 0x3: result_shift_str = "_x8"; break; + case 0xD: result_shift_str = "_d8"; break; + case 0xE: result_shift_str = "_d4"; break; + case 0xF: result_shift_str = "_d2"; break; + } // switch + + const char *sat_str = (arg->result_mod & MOD_SATURATE) ? "_sat" : ""; + const char *pp_str = (arg->result_mod & MOD_PP) ? "_pp" : ""; + const char *cent_str = (arg->result_mod & MOD_CENTROID) ? "_centroid" : ""; + + if (arg->result_mod != 0x0) + { + fail(ctx, "dest register modifiers currently unsupported in arb1"); + return ""; + } // if + + char regnum_str[16]; + const char *regtype_str = get_D3D_register_string(ctx, arg->regtype, + arg->regnum, regnum_str, + sizeof (regnum_str)); + if (regtype_str == NULL) + { + fail(ctx, "Unknown destination register type."); + return ""; + } // if + + char writemask_str[6]; + int i = 0; + const int scalar = scalar_register(arg->regtype, arg->regnum); + if (!scalar && !writemask_xyzw(arg->writemask)) + { + writemask_str[i++] = '.'; + if (arg->writemask0) writemask_str[i++] = 'x'; + if (arg->writemask1) writemask_str[i++] = 'y'; + if (arg->writemask2) writemask_str[i++] = 'z'; + if (arg->writemask3) writemask_str[i++] = 'w'; + } // if + writemask_str[i] = '\0'; + assert(i < sizeof (writemask_str)); + + const char *pred_left = ""; + const char *pred_right = ""; + char pred[32] = { '\0' }; + if (ctx->predicated) + { + fail(ctx, "dest register predication currently unsupported in arb1"); + return ""; + pred_left = "("; + pred_right = ") "; + make_D3D_srcarg_string_in_buf(ctx, &ctx->predicate_arg, + pred, sizeof (pred)); + } // if + + // may turn out something like "_x2_sat_pp_centroid (!p0.x) r0.xyzw" ... + char *retval = get_scratch_buffer(ctx); + snprintf(retval, SCRATCH_BUFFER_SIZE, "%s%s%s%s %s%s%s%s%s%s", + result_shift_str, sat_str, pp_str, cent_str, + pred_left, pred, pred_right, + regtype_str, regnum_str, writemask_str); + // !!! FIXME: make sure the scratch buffer was large enough. + return retval; +} // make_ARB1_destarg_string + + +static const char *make_ARB1_srcarg_string(Context *ctx, const int idx) +{ + if (idx >= STATICARRAYLEN(ctx->source_args)) + { + fail(ctx, "Too many source args"); + return ""; + } // if + + const SourceArgInfo *arg = &ctx->source_args[idx]; + char *buf = get_scratch_buffer(ctx); + return make_ARB1_srcarg_string_in_buf(ctx, arg, buf, SCRATCH_BUFFER_SIZE); +} // make_ARB1_srcarg_string + + +static void emit_ARB1_opcode_d(Context *ctx, const char *opcode) +{ + const char *dst0 = make_ARB1_destarg_string(ctx); + output_line(ctx, "%s%s", opcode, dst0); +} // emit_ARB1_opcode_d + +static void emit_ARB1_opcode_s(Context *ctx, const char *opcode) +{ + const char *src0 = make_ARB1_srcarg_string(ctx, 0); + output_line(ctx, "%s %s", opcode, src0); +} // emit_ARB1_opcode_s + +static void emit_ARB1_opcode_ss(Context *ctx, const char *opcode) +{ + const char *src0 = make_ARB1_srcarg_string(ctx, 0); + const char *src1 = make_ARB1_srcarg_string(ctx, 1); + output_line(ctx, "%s %s, %s", opcode, src0, src1); +} // emit_ARB1_opcode_ss + +static void emit_ARB1_opcode_ds(Context *ctx, const char *opcode) +{ + const char *dst0 = make_ARB1_destarg_string(ctx); + const char *src0 = make_ARB1_srcarg_string(ctx, 0); + output_line(ctx, "%s%s, %s", opcode, dst0, src0); +} // emit_ARB1_opcode_ds + +static void emit_ARB1_opcode_dss(Context *ctx, const char *opcode) +{ + const char *dst0 = make_ARB1_destarg_string(ctx); + const char *src0 = make_ARB1_srcarg_string(ctx, 0); + const char *src1 = make_ARB1_srcarg_string(ctx, 1); + output_line(ctx, "%s%s, %s, %s", opcode, dst0, src0, src1); +} // emit_ARB1_opcode_dss + +static void emit_ARB1_opcode_dsss(Context *ctx, const char *opcode) +{ + const char *dst0 = make_ARB1_destarg_string(ctx); + const char *src0 = make_ARB1_srcarg_string(ctx, 0); + const char *src1 = make_ARB1_srcarg_string(ctx, 1); + const char *src2 = make_ARB1_srcarg_string(ctx, 2); + output_line(ctx, "%s%s, %s, %s, %s", opcode, dst0, src0, src1, src2); +} // emit_ARB1_opcode_dsss + + +static void emit_ARB1_opcode_dssss(Context *ctx, const char *opcode) +{ + const char *dst0 = make_ARB1_destarg_string(ctx); + const char *src0 = make_ARB1_srcarg_string(ctx, 0); + const char *src1 = make_ARB1_srcarg_string(ctx, 1); + const char *src2 = make_ARB1_srcarg_string(ctx, 2); + const char *src3 = make_ARB1_srcarg_string(ctx, 3); + output_line(ctx,"%s%s, %s, %s, %s, %s",opcode,dst0,src0,src1,src2,src3); +} // emit_ARB1_opcode_dssss + +#define EMIT_ARB1_OPCODE_FUNC(op) \ + static void emit_ARB1_##op(Context *ctx) { \ + emit_ARB1_opcode(ctx, #op); \ + } +#define EMIT_ARB1_OPCODE_D_FUNC(op) \ + static void emit_ARB1_##op(Context *ctx) { \ + emit_ARB1_opcode_d(ctx, #op); \ + } +#define EMIT_ARB1_OPCODE_S_FUNC(op) \ + static void emit_ARB1_##op(Context *ctx) { \ + emit_ARB1_opcode_s(ctx, #op); \ + } +#define EMIT_ARB1_OPCODE_SS_FUNC(op) \ + static void emit_ARB1_##op(Context *ctx) { \ + emit_ARB1_opcode_ss(ctx, #op); \ + } +#define EMIT_ARB1_OPCODE_DS_FUNC(op) \ + static void emit_ARB1_##op(Context *ctx) { \ + emit_ARB1_opcode_ds(ctx, #op); \ + } +#define EMIT_ARB1_OPCODE_DSS_FUNC(op) \ + static void emit_ARB1_##op(Context *ctx) { \ + emit_ARB1_opcode_dss(ctx, #op); \ + } +#define EMIT_ARB1_OPCODE_DSSS_FUNC(op) \ + static void emit_ARB1_##op(Context *ctx) { \ + emit_ARB1_opcode_dsss(ctx, #op); \ + } +#define EMIT_ARB1_OPCODE_DSSSS_FUNC(op) \ + static void emit_ARB1_##op(Context *ctx) { \ + emit_ARB1_opcode_dssss(ctx, #op); \ + } +#define EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(op) \ + static void emit_ARB1_##op(Context *ctx) { \ + fail(ctx, #op " unimplemented in arb1 profile"); \ + } + + +static void emit_ARB1_start(Context *ctx) +{ + const char *shader_str = NULL; + if (shader_is_vertex(ctx)) + shader_str = "vp"; + else if (shader_is_pixel(ctx)) + shader_str = "fp"; + else + { + failf(ctx, "Shader type %u unsupported in this profile.", + (uint) ctx->shader_type); + return; + } // if + + ctx->output = &ctx->globals; + output_line(ctx, "!!ARB%s1.0", shader_str); + ctx->output = &ctx->mainline; +} // emit_ARB1_start + +static void emit_ARB1_end(Context *ctx) +{ + output_line(ctx, "END"); +} // emit_ARB1_end + +static void emit_ARB1_finalize(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_finalize + +static void emit_ARB1_global(Context *ctx, RegisterType t, int n) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_global + +static void emit_ARB1_relative(Context *ctx, int size) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_relative + +static void emit_ARB1_uniform(Context *ctx, RegisterType t, int n) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_uniform + +static void emit_ARB1_sampler(Context *ctx, int s, TextureType ttype) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_sampler + +static void emit_ARB1_attribute(Context *ctx, RegisterType t, int n, + MOJOSHADER_usage u, int i, int w) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_attribute + +static void emit_ARB1_RESERVED(Context *ctx) { /* no-op. */ } + +static void emit_ARB1_NOP(Context *ctx) +{ + // There is no NOP in arb1. Just don't output anything here. +} // emit_ARB1_NOP + +EMIT_ARB1_OPCODE_DS_FUNC(MOV) +EMIT_ARB1_OPCODE_DSS_FUNC(ADD) +EMIT_ARB1_OPCODE_DSS_FUNC(SUB) +EMIT_ARB1_OPCODE_DSSS_FUNC(MAD) +EMIT_ARB1_OPCODE_DSS_FUNC(MUL) +EMIT_ARB1_OPCODE_DS_FUNC(RCP) +EMIT_ARB1_OPCODE_DS_FUNC(RSQ) +EMIT_ARB1_OPCODE_DSS_FUNC(DP3) +EMIT_ARB1_OPCODE_DSS_FUNC(DP4) +EMIT_ARB1_OPCODE_DSS_FUNC(MIN) +EMIT_ARB1_OPCODE_DSS_FUNC(MAX) + +static void emit_ARB1_SLT(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_SLT + +static void emit_ARB1_SGE(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_SGE + +static void emit_ARB1_EXP(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_EXP + +static void emit_ARB1_LOG(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_LOG + +static void emit_ARB1_LIT(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_LIT + +static void emit_ARB1_DST(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_DST + +static void emit_ARB1_LRP(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_LRP + +static void emit_ARB1_FRC(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_FRC + +static void emit_ARB1_M4X4(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_M4X4 + +static void emit_ARB1_M4X3(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_M4X3 + +static void emit_ARB1_M3X4(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_M3X4 + +static void emit_ARB1_M3X3(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_M3X3 + +static void emit_ARB1_M3X2(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_M3X2 + +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(CALL) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(CALLNZ) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(LOOP) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(RET) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(ENDLOOP) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(LABEL) + +static void emit_ARB1_POW(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_POW + +static void emit_ARB1_CRS(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_CRS + +static void emit_ARB1_SGN(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_SGN + +static void emit_ARB1_ABS(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_ABS + +static void emit_ARB1_NRM(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_NRM + +static void emit_ARB1_SINCOS(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_SINCOS + +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(REP) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(ENDREP) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(IF) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(ELSE) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(ENDIF) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(BREAK) + +static void emit_ARB1_MOVA(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_MOVA + +static void emit_ARB1_TEXKILL(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXKILL + +static void emit_ARB1_TEXBEM(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXBEM + +static void emit_ARB1_TEXBEML(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXBEML + +static void emit_ARB1_TEXREG2AR(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXREG2AR + +static void emit_ARB1_TEXREG2GB(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXREG2GB + +static void emit_ARB1_TEXM3X2PAD(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXM3X2PAD + +static void emit_ARB1_TEXM3X2TEX(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXM3X2TEX + +static void emit_ARB1_TEXM3X3PAD(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXM3X3PAD + +static void emit_ARB1_TEXM3X3TEX(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXM3X3TEX + +static void emit_ARB1_TEXM3X3SPEC(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXM3X3SPEC + +static void emit_ARB1_TEXM3X3VSPEC(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXM3X3VSPEC + +static void emit_ARB1_EXPP(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_EXPP + +static void emit_ARB1_LOGP(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_LOGP + +static void emit_ARB1_CND(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_CND + +static void emit_ARB1_TEXREG2RGB(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXREG2RGB + +static void emit_ARB1_TEXDP3TEX(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXDP3TEX + +static void emit_ARB1_TEXM3X2DEPTH(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXM3X2DEPTH + +static void emit_ARB1_TEXDP3(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXDP3 + +static void emit_ARB1_TEXM3X3(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXM3X3 + +static void emit_ARB1_TEXDEPTH(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXDEPTH + +static void emit_ARB1_CMP(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_CMP + +static void emit_ARB1_BEM(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_BEM + +static void emit_ARB1_DP2ADD(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_DP2ADD + +static void emit_ARB1_DSX(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_DSX + +static void emit_ARB1_DSY(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_DSY + +static void emit_ARB1_TEXLDD(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXLDD + +static void emit_ARB1_TEXLDL(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXLDL + +static void emit_ARB1_BREAKP(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_BREAKP + +static void emit_ARB1_BREAKC(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_BREAKC + +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(IFC) +EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(SETP) + +static void emit_ARB1_DEF(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_DEF + +static void emit_ARB1_DEFI(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_DEFI + +static void emit_ARB1_DEFB(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_DEFB + +static void emit_ARB1_DCL(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_DCL + +static void emit_ARB1_TEXCRD(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXCRD + +static void emit_ARB1_TEXLD(Context *ctx) +{ + failf(ctx, "%s unimplemented in arb1 profile", __FUNCTION__); +} // emit_ARB1_TEXLD + +#endif // SUPPORT_PROFILE_ARB1 + + #if !AT_LEAST_ONE_PROFILE #error No profiles are supported. Fix your build. #endif @@ -3308,6 +4008,9 @@ static const Profile profiles[] = #if SUPPORT_PROFILE_GLSL DEFINE_PROFILE(GLSL) #endif +#if SUPPORT_PROFILE_ARB1 + DEFINE_PROFILE(ARB1) +#endif }; #undef DEFINE_PROFILE @@ -3317,6 +4020,7 @@ static const Profile profiles[] = PROFILE_EMITTER_D3D(op) \ PROFILE_EMITTER_PASSTHROUGH(op) \ PROFILE_EMITTER_GLSL(op) \ + PROFILE_EMITTER_ARB1(op) \ } static int parse_destination_token(Context *ctx, DestArgInfo *info) diff --git a/mojoshader.h b/mojoshader.h index 102c02a8..73e9f98b 100644 --- a/mojoshader.h +++ b/mojoshader.h @@ -335,6 +335,11 @@ typedef struct */ #define MOJOSHADER_PROFILE_GLSL "glsl" +/* + * Profile string for OpenGL ARB 1.0 shaders: GL_ARB_(vertex|fragment)_program. + */ +#define MOJOSHADER_PROFILE_ARB1 "arb1" + /* * Parse a compiled Direct3D shader's bytecode. diff --git a/mojoshader_opengl.c b/mojoshader_opengl.c index 7547b6a8..144f4b39 100644 --- a/mojoshader_opengl.c +++ b/mojoshader_opengl.c @@ -48,10 +48,14 @@ typedef int32_t int32; #define SUPPORT_PROFILE_GLSL 1 #endif +#ifndef SUPPORT_PROFILE_ARB1 +#define SUPPORT_PROFILE_ARB1 1 +#endif + struct MOJOSHADER_glShader { const MOJOSHADER_parseData *parseData; - GLhandleARB handle; + GLuint handle; uint32 refcount; }; @@ -79,7 +83,7 @@ struct MOJOSHADER_glProgram { MOJOSHADER_glShader *vertex; MOJOSHADER_glShader *fragment; - GLhandleARB handle; + GLuint handle; uint32 constant_count; // !!! FIXME: misnamed. GLfloat *constants; // !!! FIXME: misnamed. uint32 uniform_count; @@ -124,6 +128,8 @@ struct MOJOSHADER_glContext // Extensions... int have_base_opengl; + int have_GL_ARB_vertex_program; + int have_GL_ARB_fragment_program; int have_GL_ARB_shader_objects; int have_GL_ARB_vertex_shader; int have_GL_ARB_fragment_shader; @@ -151,8 +157,24 @@ struct MOJOSHADER_glContext PFNGLUNIFORM4IVARBPROC glUniform4iv; PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObject; PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointer; + + // interface for profile-specific things. + int (*profileMaxUniforms)(MOJOSHADER_shaderType shader_type); + int (*profileCompileShader)(const MOJOSHADER_parseData *pd); + void (*profileDeleteShader)(const GLuint shader); + void (*profileDeleteProgram)(const GLuint program); }; +// predeclare some profile implementation stuff... +static int impl_GLSL_MaxUniforms(MOJOSHADER_shaderType shader_type); +static int impl_GLSL_CompileShader(const MOJOSHADER_parseData *pd); +static int impl_GLSL_DeleteShader(const GLuint shader); +static int impl_ARB1_MaxUniforms(MOJOSHADER_shaderType shader_type); +static int impl_ARB1_CompileShader(const MOJOSHADER_parseData *pd); +static int impl_ARB1_DeleteShader(const GLuint shader); + + + static MOJOSHADER_glContext *ctx = NULL; @@ -287,6 +309,8 @@ static void load_extensions(void *(*lookup)(const char *fnname)) const char *extlist = NULL; ctx->have_base_opengl = 1; + ctx->have_GL_ARB_vertex_program = 1; + ctx->have_GL_ARB_fragment_program = 1; ctx->have_GL_ARB_shader_objects = 1; ctx->have_GL_ARB_vertex_shader = 1; ctx->have_GL_ARB_fragment_shader = 1; @@ -309,6 +333,8 @@ static void load_extensions(void *(*lookup)(const char *fnname)) #define VERIFY_EXT(ext, major, minor) \ ctx->have_##ext = verify_extension(#ext, ctx->have_##ext, extlist, major, minor) + VERIFY_EXT(GL_ARB_vertex_program, -1, -1); + VERIFY_EXT(GL_ARB_fragment_program, -1, -1); VERIFY_EXT(GL_ARB_shader_objects, 2, 0); VERIFY_EXT(GL_ARB_vertex_shader, 2, 0); VERIFY_EXT(GL_ARB_fragment_shader, 2, 0); @@ -333,6 +359,14 @@ static int valid_profile(const char *profile) return 0; } // if + #if SUPPORT_PROFILE_ARB1 + else if (strcmp(profile, MOJOSHADER_PROFILE_ARB1) == 0) + { + MUST_HAVE(MOJOSHADER_PROFILE_ARB1, GL_ARB_vertex_program); + MUST_HAVE(MOJOSHADER_PROFILE_ARB1, GL_ARB_fragment_program); + } // else if + #endif + #if SUPPORT_PROFILE_GLSL else if (strcmp(profile, MOJOSHADER_PROFILE_GLSL) == 0) { @@ -369,6 +403,7 @@ const char *MOJOSHADER_glBestProfile(void *(*lookup)(const char *fnname)) { static const char *priority[] = { MOJOSHADER_PROFILE_GLSL, + MOJOSHADER_PROFILE_ARB1, }; int i; @@ -421,6 +456,34 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile, MOJOSHADER_glBindProgram(NULL); + // !!! FIXME: generalize this part. + if (profile == NULL) {} + +#if SUPPORT_PROFILE_GLSL + else if (strcmp(profile, MOJOSHADER_PROFILE_GLSL) == 0) + { + ctx->profileMaxUniforms = impl_GLSL_MaxUniforms; + ctx->profileCompileShader = impl_GLSL_CompileShader; + ctx->profileDeleteShader = impl_GLSL_DeleteShader; + ctx->profileDeleteProgram = impl_GLSL_DeleteProgram; + } // if +#endif + +#if SUPPORT_PROFILE_ARB1 + else if (strcmp(profile, MOJOSHADER_PROFILE_ARB1) == 0) + { + ctx->profileMaxUniforms = impl_ARB1_MaxUniforms; + ctx->profileCompileShader = impl_ARB1_CompileShader; + ctx->profileDeleteShader = impl_ARB1_DeleteShader; + ctx->profileDeleteProgram = impl_ARB1_DeleteProgram; + } // if +#endif + + assert(ctx->profileMaxUniforms != NULL); + assert(ctx->profileCompileShader != NULL); + assert(ctx->profileDeleteShader != NULL); + assert(ctx->profileDeleteProgram != NULL); + retval = ctx; ctx = current_ctx; return retval; @@ -439,7 +502,7 @@ void MOJOSHADER_glMakeContextCurrent(MOJOSHADER_glContext *_ctx) } // MOJOSHADER_glMakeContextCurrent -int MOJOSHADER_glMaxUniforms(MOJOSHADER_shaderType shader_type) +static int impl_GLSL_MaxUniforms(MOJOSHADER_shaderType shader_type) { GLenum pname = GL_NONE; GLint val = 0; @@ -452,22 +515,61 @@ int MOJOSHADER_glMaxUniforms(MOJOSHADER_shaderType shader_type) ctx->glGetIntegerv(pname, &val); return (int) val; +} // impl_GLSL_MaxUniforms + + +int MOJOSHADER_glMaxUniforms(MOJOSHADER_shaderType shader_type) +{ + return ctx->profileMaxUniforms(shader_type); } // MOJOSHADER_glMaxUniforms +static int impl_GLSL_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s) +{ + GLint ok = 0; + GLint shaderlen = (GLint) pd->output_len; + const GLenum shader_type = (pd->shader_type == MOJOSHADER_TYPE_PIXEL) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER; + GLuint shader = ctx->glCreateShaderObject(shader_type); + + ctx->glShaderSource(shader, 1, (const GLchar **) &pd->output, &shaderlen); + ctx->glCompileShader(shader); + ctx->glGetObjectParameteriv(shader, GL_OBJECT_COMPILE_STATUS_ARB, &ok); + + if (!ok) + { + GLsizei len = 0; + ctx->glGetInfoLog(shader, sizeof (error_buffer), &len, + (GLchar *) error_buffer); + *s = 0; + return 0; + } // if + + *s = shader; + return 1; +} // impl_GLSL_CompileShader + + +static void impl_GLSL_DeleteShader(const GLuint shader) +{ + ctx->glDeleteObject(shader); +} // impl_GLSL_DeleteShader + + +static void impl_GLSL_DeleteProgram(const GLuint program) +{ + ctx->glDeleteObject(program); +} // impl_GLSL_DeleteProgram + + MOJOSHADER_glShader *MOJOSHADER_glCompileShader(const unsigned char *tokenbuf, const unsigned int bufsize) { MOJOSHADER_glShader *retval = NULL; - GLhandleARB shader = 0; + GLuint shader = 0; const MOJOSHADER_parseData *pd = MOJOSHADER_parse(ctx->profile, tokenbuf, bufsize, ctx->malloc_fn, ctx->free_fn, ctx->malloc_data); - GLint ok = 0; - const GLenum shader_type = (pd->shader_type == MOJOSHADER_TYPE_PIXEL) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER; - GLint shaderlen = (GLint) pd->output_len; - if (pd->error != NULL) { set_error(pd->error); @@ -478,18 +580,8 @@ MOJOSHADER_glShader *MOJOSHADER_glCompileShader(const unsigned char *tokenbuf, if (retval == NULL) goto compile_shader_fail; - shader = ctx->glCreateShaderObject(shader_type); - - ctx->glShaderSource(shader, 1, (const GLchar **) &pd->output, &shaderlen); - ctx->glCompileShader(shader); - ctx->glGetObjectParameteriv(shader, GL_OBJECT_COMPILE_STATUS_ARB, &ok); - - if (!ok) - { - GLsizei len = 0; - ctx->glGetInfoLog(shader, sizeof (error_buffer), &len, (GLchar *) error_buffer); + if (!ctx->profileCompileShader(pd, &shader)) goto compile_shader_fail; - } // if retval->parseData = pd; retval->handle = shader; @@ -500,7 +592,7 @@ MOJOSHADER_glShader *MOJOSHADER_glCompileShader(const unsigned char *tokenbuf, MOJOSHADER_freeParseData(pd); Free(retval); if (shader != 0) - ctx->glDeleteObject(shader); + ctx->profileDeleteShader(shader); return NULL; } // MOJOSHADER_glCompileShader @@ -521,7 +613,7 @@ static void shader_unref(MOJOSHADER_glShader *shader) shader->refcount--; else { - ctx->glDeleteObject(shader->handle); + ctx->profileDeleteShader(shader->handle); MOJOSHADER_freeParseData(shader->parseData); Free(shader); } // else @@ -538,7 +630,7 @@ static void program_unref(MOJOSHADER_glProgram *program) program->refcount--; else { - ctx->glDeleteObject(program->handle); + ctx->profileDeleteProgram(program->handle); shader_unref(program->vertex); shader_unref(program->fragment); Free(program->constants); @@ -624,7 +716,7 @@ MOJOSHADER_glProgram *MOJOSHADER_glLinkProgram(MOJOSHADER_glShader *vshader, return NULL; MOJOSHADER_glProgram *retval = NULL; - const GLhandleARB program = ctx->glCreateProgramObject(); + const GLuint program = ctx->glCreateProgramObject(); int numregs = 0; int consts = 0; @@ -713,14 +805,14 @@ MOJOSHADER_glProgram *MOJOSHADER_glLinkProgram(MOJOSHADER_glShader *vshader, Free(retval); } // if - ctx->glDeleteObject(program); + ctx->profileDeleteProgram(program); return NULL; } // MOJOSHADER_glLinkProgram void MOJOSHADER_glBindProgram(MOJOSHADER_glProgram *program) { - GLhandleARB handle = 0; + GLuint handle = 0; int i; if (program == ctx->bound_program)