wined3d: More shader fixes / new instructions.

- Replace gl_FragColor with gl_FragData[0] for GLSL pixel shader output.
- Subtract 1 more constant from total GLSL allowed float constants to
  accommodate the PROJECTION matrix row that we reference.
This commit is contained in:
Jason Green 2006-07-28 04:14:14 -04:00 committed by Alexandre Julliard
parent 6d16eff9a6
commit 72bfe131d1
6 changed files with 140 additions and 24 deletions

View File

@ -171,7 +171,6 @@ void shader_generate_arb_declarations(
/* Need to PARAM the environment parameters (constants) so we can use relative addressing */
shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
max_constantsF, max_constantsF - 1);
shader_addline(buffer, "PARAM PROJECTION = state.matrix.projection.row[1];\n");
}
static const char* shift_tab[] = {

View File

@ -243,8 +243,8 @@ void select_shader_max_constants(WineD3D_GL_Info *gl_info) {
switch (wined3d_settings.vs_selected_mode) {
case SHADER_GLSL:
/* Subtract the other potential uniforms from the max available (bools & ints) */
gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
/* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I - 1;
break;
case SHADER_ARB:
/* We have to subtract any other PARAMs that we might use in our shader programs.

View File

@ -638,12 +638,10 @@ static void shader_glsl_get_register_name(
sprintf(tmpStr, "Vsampler%lu", reg);
break;
case D3DSPR_COLOROUT:
if (reg == 0)
sprintf(tmpStr, "gl_FragColor");
else {
sprintf(tmpStr, "gl_FragData[%lu]", reg);
if (reg > 0) {
/* TODO: See GL_ARB_draw_buffers */
FIXME("Unsupported write to render target %lu\n", reg);
sprintf(tmpStr, "unsupported_register");
}
break;
case D3DSPR_RASTOUT:
@ -914,7 +912,6 @@ void shader_glsl_map2gl(SHADER_OPCODE_ARG* arg) {
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;
@ -942,6 +939,39 @@ void shader_glsl_map2gl(SHADER_OPCODE_ARG* arg) {
}
/** Process the D3DSIO_EXPP instruction in GLSL:
* For shader model 1.x, do the following (and honor the writemask, so use a temporary variable):
* dst.x = 2^(floor(src))
* dst.y = src - floor(src)
* dst.z = 2^src (partial precision is allowed, but optional)
* dst.w = 1.0;
* For 2.0 shaders, just do this (honoring writemask and swizzle):
* dst = 2^src; (partial precision is allowed, but optional)
*/
void shader_glsl_expp(SHADER_OPCODE_ARG* arg) {
char tmpLine[256];
char dst_str[100], src_str[100];
char dst_reg[50], src_reg[50];
char dst_mask[6], src_mask[6];
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
DWORD hex_version = This->baseShader.hex_version;
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, src_reg, src_mask, src_str);
shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
if (hex_version < D3DPS_VERSION(2,0)) {
shader_addline(arg->buffer, "tmp0.x = vec4(exp2(floor(%s))).x;\n", src_str);
shader_addline(arg->buffer, "tmp0.y = vec4(%s - floor(%s)).y;\n", src_str, src_str);
shader_addline(arg->buffer, "tmp0.z = vec4(exp2(%s)).x;\n", src_str);
shader_addline(arg->buffer, "tmp0.w = 1.0;\n");
shader_addline(arg->buffer, "%svec4(tmp0))%s;\n", tmpLine, dst_mask);
} else {
shader_addline(arg->buffer, "%svec4(exp2(%s)))%s;\n", tmpLine, src_str, dst_mask);
}
}
/** Process the RCP (reciprocal or inverse) opcode in GLSL (dst = 1 / src) */
void shader_glsl_rcp(SHADER_OPCODE_ARG* arg) {
@ -1354,6 +1384,73 @@ void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg) {
}
}
/** Process the D3DSIO_TEXDP3TEX instruction in GLSL:
* Take a 3-component dot product of the TexCoord[dstreg] and src,
* then perform a 1D texture lookup from stage dstregnum, place into dst. */
void pshader_glsl_texdp3tex(SHADER_OPCODE_ARG* arg) {
DWORD dstreg = arg->dst & D3DSP_REGNUM_MASK;
char src0_str[100], dst_str[100];
char src0_name[50], dst_name[50];
char src0_mask[6], dst_mask[6];
shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_name, dst_mask, dst_str);
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
shader_addline(arg->buffer, "tmp0.x = dot(vec3(gl_TexCoord[%lu]), vec3(%s));\n", dstreg, src0_str);
shader_addline(arg->buffer, "%s = vec4(texture1D(Psampler%lu, tmp0.x))%s;\n", dst_str, dstreg, dst_mask);
}
/** Process the D3DSIO_TEXDP3 instruction in GLSL:
* Take a 3-component dot product of the TexCoord[dstreg] and src. */
void pshader_glsl_texdp3(SHADER_OPCODE_ARG* arg) {
DWORD dstreg = arg->dst & D3DSP_REGNUM_MASK;
char src0_str[100], dst_str[100];
char src0_name[50], dst_name[50];
char src0_mask[6], dst_mask[6];
shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_name, dst_mask, dst_str);
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
shader_addline(arg->buffer, "%s = vec4(dot(vec3(T%lu), vec3(%s)))%s;\n",
dst_str, dstreg, src0_str, dst_mask);
}
/** Process the D3DSIO_TEXDEPTH instruction in GLSL:
* Calculate the depth as dst.x / dst.y */
void pshader_glsl_texdepth(SHADER_OPCODE_ARG* arg) {
char dst_str[100];
char dst_reg[50];
char dst_mask[6];
shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
shader_addline(arg->buffer, "gl_FragDepth = %s.x / %s.y;\n", dst_reg, dst_reg);
}
/** Process the D3DSIO_TEXM3X2DEPTH instruction in GLSL:
* Last row of a 3x2 matrix multiply, use the result to calculate the depth:
* Calculate tmp0.y = TexCoord[dstreg] . src.xyz; (tmp0.x has already been calculated)
* depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y
*/
void pshader_glsl_texm3x2depth(SHADER_OPCODE_ARG* arg) {
DWORD dstreg = arg->dst & D3DSP_REGNUM_MASK;
char src0_str[100], dst_str[100];
char src0_name[50], dst_name[50];
char src0_mask[6], dst_mask[6];
shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_name, dst_mask, dst_str);
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
shader_addline(arg->buffer, "tmp0.y = dot(vec3(T%lu), vec3(%s));\n", dstreg, src0_str);
shader_addline(arg->buffer, "gl_FragDepth = vec4((tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y)%s;\n", dst_str, dst_name);
}
/** Process the D3DSIO_TEXM3X2PAD instruction in GLSL
* Calculate the 1st of a 2-row matrix multiplication. */
void pshader_glsl_texm3x2pad(SHADER_OPCODE_ARG* arg) {
DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
@ -1363,7 +1460,7 @@ void pshader_glsl_texm3x2pad(SHADER_OPCODE_ARG* arg) {
char src0_mask[6];
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
shader_addline(buffer, "tmp0.x = dot(vec3(T%lu), vec3(%s));\n", reg, src0_name, src0_str);
shader_addline(buffer, "tmp0.x = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str);
}
/** Process the D3DSIO_TEXM3X3PAD instruction in GLSL
@ -1429,6 +1526,24 @@ void pshader_glsl_texm3x3tex(SHADER_OPCODE_ARG* arg) {
current_state->current_row = 0;
}
/** Process the D3DSIO_TEXM3X3 instruction in GLSL
* Perform the 3rd row of a 3x3 matrix multiply */
void pshader_glsl_texm3x3(SHADER_OPCODE_ARG* arg) {
char src0_str[100];
char src0_name[50];
char src0_mask[6];
DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
shader_addline(arg->buffer, "tmp0.z = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str);
shader_addline(arg->buffer, "T%lu = vec4(tmp0.x, tmp0.y, tmp0.z, 1.0);\n", reg);
current_state->current_row = 0;
}
/** Process the D3DSIO_TEXM3X3SPEC instruction in GLSL
* Peform the final texture lookup based on the previous 2 3x3 matrix multiplies */
void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg) {

View File

@ -618,9 +618,6 @@ static void pshader_texldl(WINED3DSHADERVECTOR* d) {
FIXME(" : Stub\n");
}
/**
* log, exp, frc, m*x* seems to be macros ins ... to see
*/
CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
/* Arithmethic */
@ -641,7 +638,7 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
{D3DSIO_ABS, "abs", "ABS", 1, 2, pshader_abs, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
{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_EXPP, "expp", "EXP", 1, 2, pshader_expp, pshader_hw_map2gl, shader_glsl_expp, 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},
@ -717,13 +714,12 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
{D3DSIO_TEXM3x3SPEC, "texm3x3spec", "undefined", 1, 3, pshader_texm3x3spec, pshader_hw_texm3x3spec, pshader_glsl_texm3x3spec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
{D3DSIO_TEXM3x3VSPEC, "texm3x3vspec", "undefined", 1, 2, pshader_texm3x3vspec, pshader_hw_texm3x3vspec, pshader_glsl_texm3x3vspec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
{D3DSIO_TEXM3x3TEX, "texm3x3tex", "undefined", 1, 2, pshader_texm3x3tex, pshader_hw_texm3x3tex, pshader_glsl_texm3x3tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
{D3DSIO_TEXDP3TEX, "texdp3tex", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3tex, NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
{D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x2depth, NULL, NULL, D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
{D3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3, NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
{D3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x3, NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
{D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL, 1, 1, pshader_texdepth, NULL, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
{D3DSIO_TEXDP3TEX, "texdp3tex", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3tex, NULL, pshader_glsl_texdp3tex, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
{D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x2depth, NULL, pshader_glsl_texm3x2depth, D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
{D3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3, NULL, pshader_glsl_texdp3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
{D3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x3, NULL, pshader_glsl_texm3x3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
{D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL, 1, 1, pshader_texdepth, NULL, pshader_glsl_texdepth, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
{D3DSIO_BEM, "bem", GLNAME_REQUIRE_GLSL, 1, 3, pshader_bem, NULL, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
/* TODO: dp2add can be made out of multiple instuctions */
{D3DSIO_DSX, "dsx", GLNAME_REQUIRE_GLSL, 1, 2, pshader_dsx, NULL, NULL, 0, 0},
{D3DSIO_DSY, "dsy", GLNAME_REQUIRE_GLSL, 1, 2, pshader_dsy, NULL, NULL, 0, 0},
{D3DSIO_TEXLDD, "texldd", GLNAME_REQUIRE_GLSL, 1, 5, pshader_texldd, NULL, NULL, D3DPS_VERSION(2,1), -1},
@ -854,7 +850,7 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateShader(
/* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
shader_addline(&buffer, "gl_FragColor = R0;\n");
shader_addline(&buffer, "gl_FragData[0] = R0;\n");
shader_addline(&buffer, "}\n\0");
TRACE("Compiling shader object %u\n", shader_obj);

View File

@ -472,9 +472,6 @@ static void vshader_texldl(WINED3DSHADERVECTOR* d) {
FIXME(" : Stub\n");
}
/**
* log, exp, frc, m*x* seems to be macros ins ... to see
*/
CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
/* Arithmetic */
@ -495,7 +492,7 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
{D3DSIO_ABS, "abs", "ABS", 1, 2, vshader_abs, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
{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_EXPP, "expp", "EXP", 1, 2, vshader_expp, vshader_hw_map2gl, shader_glsl_expp, 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},
@ -746,6 +743,9 @@ static VOID IWineD3DVertexShaderImpl_GenerateShader(
/* Base Declarations */
shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
/* We need the projection matrix to correctly render upside-down objects (render to texture) */
shader_addline(&buffer, "PARAM PROJECTION = state.matrix.projection.row[1];\n");
if (reg_maps->fog) {
This->usesFog = 1;

View File

@ -1493,6 +1493,7 @@ extern void shader_glsl_compare(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_def(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_defi(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_defb(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_expp(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);
@ -1512,8 +1513,13 @@ extern void shader_glsl_label(SHADER_OPCODE_ARG* arg);
/** GLSL Pixel Shader Prototypes */
extern void pshader_glsl_tex(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texdp3tex(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texdp3(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texdepth(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texm3x2depth(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texm3x2pad(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texm3x2tex(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texm3x3(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texm3x3pad(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texm3x3tex(SHADER_OPCODE_ARG* arg);
extern void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg);