Commit cc06ed3d authored by Jason Green's avatar Jason Green Committed by Alexandre Julliard

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.
parent da5cc563
......@@ -411,6 +411,9 @@ void shader_get_registers_used(
else if (D3DSPR_INPUT == regtype && !pshader)
reg_maps->attributes[reg] = 1;
else if (D3DSPR_LOOP == regtype)
reg_maps->loop = 1;
}
}
}
......@@ -792,6 +795,10 @@ void shader_generate_glsl_declarations(
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 @@ void shader_generate_main(
/* 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 {
......
......@@ -245,6 +245,9 @@ static void shader_glsl_get_register_name(
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 @@ void shader_glsl_map2gl(SHADER_OPCODE_ARG* arg) {
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 @@ void shader_glsl_def(SHADER_OPCODE_ARG* arg) {
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
********************************************/
......
......@@ -654,8 +654,8 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
{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 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
*/
{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 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
{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 */
......
......@@ -397,7 +397,7 @@ static void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3D
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 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
{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 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
/* 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 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
*/
{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 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
{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},
......
......@@ -1277,6 +1277,9 @@ typedef struct shader_reg_maps {
* 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 @@ extern const SHADER_OPCODE* shader_get_opcode(
/* 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_cnd(SHADER_OPCODE_ARG* arg);
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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment