wined3d: Implement more GLSL instructions. - Implemented: D3DSIO_SGN, LOOP, ENDLOOP, LOGP, LIT, DST, SINCOS - Process instruction-based modifiers (function existed, it just wasn't being called) - Add loop checking to register maps. - Renamed "sng" to "sgn" for D3DSIO_SGN - it's not handled anywhere except for GLSL, so won't matter.
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index b148bb3..f19a03b 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c
@@ -411,6 +411,9 @@ else if (D3DSPR_INPUT == regtype && !pshader) reg_maps->attributes[reg] = 1; + + else if (D3DSPR_LOOP == regtype) + reg_maps->loop = 1; } } } @@ -792,6 +795,10 @@ shader_addline(buffer, "attribute vec4 attrib%i;\n", i); } + /* Declare loop register aL */ + if (reg_maps->loop) + shader_addline(buffer, "int aL;\n"); + /* Temporary variables for matrix operations */ shader_addline(buffer, "vec4 tmp0;\n"); shader_addline(buffer, "vec4 tmp1;\n"); @@ -901,6 +908,10 @@ /* Call appropriate function for output target */ hw_fct(&hw_arg); + /* Process instruction modifiers for GLSL apps ( _sat, etc. ) */ + if (wined3d_settings.shader_mode == SHADER_GLSL) + shader_glsl_add_instruction_modifiers(&hw_arg); + /* Unhandled opcode */ } else {
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 3661d06..e99a2a2 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c
@@ -245,6 +245,9 @@ sprintf(tmpStr, "A%lu", reg); } break; + case D3DSPR_LOOP: + sprintf(tmpStr, "aL"); + break; case D3DSPR_SAMPLER: if (pshader) sprintf(tmpStr, "psampler%lu", reg); @@ -508,11 +511,13 @@ case D3DSIO_POW: strcat(tmpLine, "pow"); break; case D3DSIO_CRS: strcat(tmpLine, "cross"); break; case D3DSIO_NRM: strcat(tmpLine, "normalize"); break; + case D3DSIO_LOGP: case D3DSIO_LOG: strcat(tmpLine, "log2"); break; case D3DSIO_EXPP: case D3DSIO_EXP: strcat(tmpLine, "exp2"); break; case D3DSIO_SGE: strcat(tmpLine, "greaterThanEqual"); break; case D3DSIO_SLT: strcat(tmpLine, "lessThan"); break; + case D3DSIO_SGN: strcat(tmpLine, "sign"); break; default: FIXME("Opcode %s not yet handled in GLSL\n", curOpcode->name); break; @@ -728,6 +733,93 @@ arg->reg_maps->constantsF[reg] = 1; } +/** Process the D3DSIO_LIT instruction in GLSL: + * dst.x = dst.w = 1.0 + * dst.y = (src0.x > 0) ? src0.x + * dst.z = (src0.x > 0) ? ((src0.y > 0) ? pow(src0.y, src.w) : 0) : 0 + * where src.w is clamped at +- 128 + */ +void shader_glsl_lit(SHADER_OPCODE_ARG* arg) { + + char dst_str[100], src0_str[100]; + char dst_reg[50], src0_reg[50]; + char dst_mask[6], src0_mask[6]; + + shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str); + shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str); + + shader_addline(arg->buffer, + "%s = vec4(1.0, (%s.x > 0.0 ? %s.x : 0.0), (%s.x > 0.0 ? ((%s.y > 0.0) ? pow(%s.y, clamp(%s.w, -128.0, 128.0)) : 0.0) : 0.0), 1.0)%s;\n", + dst_str, src0_reg, src0_reg, src0_reg, src0_reg, src0_reg, src0_reg, dst_mask); +} + +/** Process the D3DSIO_DST instruction in GLSL: + * dst.x = 1.0 + * dst.y = src0.x * src0.y + * dst.z = src0.z + * dst.w = src1.w + */ +void shader_glsl_dst(SHADER_OPCODE_ARG* arg) { + + char dst_str[100], src0_str[100], src1_str[100]; + char dst_reg[50], src0_reg[50], src1_reg[50]; + char dst_mask[6], src0_mask[6], src1_mask[6]; + + shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str); + shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str); + shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str); + + shader_addline(arg->buffer, "%s = vec4(1.0, %s.x * %s.y, %s.z, %s.w)%s;\n", + dst_str, src0_reg, src1_reg, src0_reg, src1_reg, dst_mask); +} + +/** Process the D3DSIO_SINCOS instruction in GLSL: + * VS 2.0 requires that specific cosine and sine constants be passed to this instruction so the hardware + * can handle it. But, these functions are built-in for GLSL, so we can just ignore the last 2 params. + * + * dst.x = cos(src0.?) + * dst.y = sin(src0.?) + * dst.z = dst.z + * dst.w = dst.w + */ +void shader_glsl_sincos(SHADER_OPCODE_ARG* arg) { + + char dst_str[100], src0_str[100]; + char dst_reg[50], src0_reg[50]; + char dst_mask[6], src0_mask[6]; + + shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str); + shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str); + + shader_addline(arg->buffer, "%s = vec4(cos(%s), sin(%s), %s.z, %s.w)%s;\n", + dst_str, src0_str, src0_str, dst_reg, dst_reg, dst_mask); +} + +/** Process the D3DSIO_LOOP instruction in GLSL: + * Start a for() loop where src0.y is the initial value of aL, + * increment aL by src0.z while (aL < src0.x). + */ +void shader_glsl_loop(SHADER_OPCODE_ARG* arg) { + + char src0_str[100]; + char src0_reg[50]; + char src0_mask[6]; + + shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str); + + shader_addline(arg->buffer, "for (aL = %s.y; aL < %s.x; aL += %s.z) {\n", + src0_reg, src0_reg, src0_reg); +} + +/** Process the D3DSIO_ENDLOOP instruction in GLSL: + * End the for() loop + */ +void shader_glsl_endloop(SHADER_OPCODE_ARG* arg) { + + shader_addline(arg->buffer, "}\n"); +} + + /********************************************* * Pixel Shader Specific Code begins here ********************************************/
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 60bbfaf..4c72390 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c
@@ -654,8 +654,8 @@ {D3DSIO_EXP, "exp", "EX2", 1, 2, pshader_exp, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_LOG, "log", "LG2", 1, 2, pshader_log, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_EXPP, "expp", "EXP", 1, 2, pshader_expp, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, - {D3DSIO_LOGP, "logp", "LOG", 1, 2, pshader_logp, pshader_hw_map2gl, NULL, 0, 0}, - {D3DSIO_DST, "dst", "DST", 1, 3, pshader_dst, pshader_hw_map2gl, NULL, 0, 0}, + {D3DSIO_LOGP, "logp", "LOG", 1, 2, pshader_logp, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, + {D3DSIO_DST, "dst", "DST", 1, 3, pshader_dst, pshader_hw_map2gl, shader_glsl_dst, 0, 0}, {D3DSIO_LRP, "lrp", "LRP", 1, 4, pshader_lrp, pshader_hw_map2gl, shader_glsl_lrp, 0, 0}, {D3DSIO_FRC, "frc", "FRC", 1, 2, pshader_frc, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_CND, "cnd", NULL, 1, 4, pshader_cnd, pshader_hw_cnd, shader_glsl_cnd, D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)}, @@ -673,8 +673,8 @@ */ {D3DSIO_NRM, "nrm", NULL, 1, 2, pshader_nrm, NULL, shader_glsl_map2gl, 0, 0}, - {D3DSIO_SINCOS, "sincos", NULL, 1, 4, pshader_sincos2, NULL, NULL, D3DPS_VERSION(2,0), D3DPS_VERSION(2,0)}, - {D3DSIO_SINCOS, "sincos", NULL, 1, 2, pshader_sincos3, NULL, NULL, D3DPS_VERSION(3,0), -1}, + {D3DSIO_SINCOS, "sincos", NULL, 1, 4, pshader_sincos2, NULL, shader_glsl_sincos, D3DPS_VERSION(2,0), D3DPS_VERSION(2,0)}, + {D3DSIO_SINCOS, "sincos", NULL, 1, 2, pshader_sincos3, NULL, shader_glsl_sincos, D3DPS_VERSION(3,0), -1}, /* TODO: dp2add can be made out of multiple instuctions */ {D3DSIO_DP2ADD, "dp2add", GLNAME_REQUIRE_GLSL, 1, 4, pshader_dp2add, NULL, NULL, D3DPS_VERSION(2,0), -1}, @@ -700,9 +700,9 @@ {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 0, 1, pshader_breakp, NULL, NULL, 0, 0}, {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 0, 1, pshader_call, NULL, NULL, 0, 0}, {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 0, 2, pshader_callnz, NULL, NULL, 0, 0}, - {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 0, 2, pshader_loop, NULL, NULL, 0, 0}, + {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 0, 2, pshader_loop, NULL, shader_glsl_loop, 0, 0}, {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, 0, pshader_ret, NULL, NULL, 0, 0}, - {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, 0, pshader_endloop, NULL, NULL, 0, 0}, + {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, 0, pshader_endloop, NULL, shader_glsl_endloop, 0, 0}, {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 0, 1, pshader_label, NULL, NULL, 0, 0}, /* Constant definitions */
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index 56648b9..d2028f2 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c
@@ -397,7 +397,7 @@ FIXME(" : Stub\n"); } -static void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) { +static void vshader_sgn(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) { FIXME(" : Stub\n"); } @@ -501,9 +501,9 @@ {D3DSIO_EXP, "exp", "EX2", 1, 2, vshader_exp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_LOG, "log", "LG2", 1, 2, vshader_log, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_EXPP, "expp", "EXP", 1, 2, vshader_expp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, - {D3DSIO_LOGP, "logp", "LOG", 1, 2, vshader_logp, vshader_hw_map2gl, NULL, 0, 0}, - {D3DSIO_LIT, "lit", "LIT", 1, 2, vshader_lit, vshader_hw_map2gl, NULL, 0, 0}, - {D3DSIO_DST, "dst", "DST", 1, 3, vshader_dst, vshader_hw_map2gl, NULL, 0, 0}, + {D3DSIO_LOGP, "logp", "LOG", 1, 2, vshader_logp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, + {D3DSIO_LIT, "lit", "LIT", 1, 2, vshader_lit, vshader_hw_map2gl, shader_glsl_lit, 0, 0}, + {D3DSIO_DST, "dst", "DST", 1, 3, vshader_dst, vshader_hw_map2gl, shader_glsl_dst, 0, 0}, {D3DSIO_LRP, "lrp", "LRP", 1, 4, vshader_lrp, NULL, shader_glsl_lrp, 0, 0}, {D3DSIO_FRC, "frc", "FRC", 1, 2, vshader_frc, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0}, {D3DSIO_POW, "pow", "POW", 1, 3, vshader_pow, NULL, shader_glsl_map2gl, 0, 0}, @@ -511,7 +511,7 @@ /* TODO: sng can possibly be performed a s RCP tmp, vec MUL out, tmp, vec*/ - {D3DSIO_SGN, "sng", NULL, 1, 2, vshader_sng, NULL, NULL, 0, 0}, + {D3DSIO_SGN, "sgn", NULL, 1, 2, vshader_sgn, NULL, shader_glsl_map2gl, 0, 0}, /* TODO: xyz normalise can be performed as VS_ARB using one temporary register, DP3 tmp , vec, vec; RSQ tmp, tmp.x; @@ -523,8 +523,8 @@ */ {D3DSIO_NRM, "nrm", NULL, 1, 2, vshader_nrm, NULL, shader_glsl_map2gl, 0, 0}, - {D3DSIO_SINCOS, "sincos", NULL, 1, 4, vshader_sincos2, NULL, NULL, D3DVS_VERSION(2,0), D3DVS_VERSION(2,0)}, - {D3DSIO_SINCOS, "sincos", NULL, 1, 2, vshader_sincos3, NULL, NULL, D3DVS_VERSION(3,0), -1}, + {D3DSIO_SINCOS, "sincos", NULL, 1, 4, vshader_sincos2, NULL, shader_glsl_sincos, D3DVS_VERSION(2,0), D3DVS_VERSION(2,0)}, + {D3DSIO_SINCOS, "sincos", NULL, 1, 2, vshader_sincos3, NULL, shader_glsl_sincos, D3DVS_VERSION(3,0), -1}, /* Matrix */ {D3DSIO_M4x4, "m4x4", "undefined", 1, 3, vshader_m4x4, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0}, @@ -553,9 +553,9 @@ {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 0, 1, vshader_breakp, NULL, NULL, 0, 0}, {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 0, 1, vshader_call, NULL, NULL, 0, 0}, {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 0, 2, vshader_callnz, NULL, NULL, 0, 0}, - {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 0, 2, vshader_loop, NULL, NULL, 0, 0}, + {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 0, 2, vshader_loop, NULL, shader_glsl_loop, 0, 0}, {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, 0, vshader_ret, NULL, NULL, 0, 0}, - {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, 0, vshader_endloop, NULL, NULL, 0, 0}, + {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, 0, vshader_endloop, NULL, shader_glsl_endloop, 0, 0}, {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 0, 1, vshader_label, NULL, NULL, 0, 0}, {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 1, 2, vshader_mova, NULL, shader_glsl_mov, 0, 0},
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 9155caf..10d21d8 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h
@@ -1277,6 +1277,9 @@ * Use 0 as default (bit 31 is always 1 on a valid token) */ DWORD samplers[MAX_SAMPLERS]; + /* Whether or not a loop is used in this shader */ + char loop; + } shader_reg_maps; #define SHADER_PGMSIZE 65535 @@ -1344,8 +1347,9 @@ /* ARB shader program Prototypes */ extern void shader_hw_def(SHADER_OPCODE_ARG *arg); -/* GLSL helper programs */ +/* GLSL helper functions */ extern void set_glsl_shader_program(IWineD3DDevice *iface); +extern void shader_glsl_add_instruction_modifiers(SHADER_OPCODE_ARG *arg); /** The following translate DirectX pixel/vertex shader opcodes to GLSL lines */ extern void shader_glsl_map2gl(SHADER_OPCODE_ARG* arg); @@ -1360,6 +1364,11 @@ extern void shader_glsl_compare(SHADER_OPCODE_ARG* arg); extern void shader_glsl_def(SHADER_OPCODE_ARG* arg); extern void shader_glsl_cmp(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_lit(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_dst(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_sincos(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_loop(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_endloop(SHADER_OPCODE_ARG* arg); /** GLSL Pixel Shader Prototypes */ extern void pshader_glsl_tex(SHADER_OPCODE_ARG* arg);