📄 glsl_shader.c
字号:
tmpArg.src[0] = arg->src[0];
tmpArg.src_addr[0] = arg->src_addr[0];
tmpArg.src_addr[1] = arg->src_addr[1];
tmpArg.reg_maps = arg->reg_maps;
switch(arg->opcode->opcode) {
case WINED3DSIO_M4x4:
nComponents = 4;
tmpArg.opcode = shader_get_opcode(arg->shader, WINED3DSIO_DP4);
break;
case WINED3DSIO_M4x3:
nComponents = 3;
tmpArg.opcode = shader_get_opcode(arg->shader, WINED3DSIO_DP4);
break;
case WINED3DSIO_M3x4:
nComponents = 4;
tmpArg.opcode = shader_get_opcode(arg->shader, WINED3DSIO_DP3);
break;
case WINED3DSIO_M3x3:
nComponents = 3;
tmpArg.opcode = shader_get_opcode(arg->shader, WINED3DSIO_DP3);
break;
case WINED3DSIO_M3x2:
nComponents = 2;
tmpArg.opcode = shader_get_opcode(arg->shader, WINED3DSIO_DP3);
break;
default:
break;
}
for (i = 0; i < nComponents; i++) {
tmpArg.dst = ((arg->dst) & ~WINED3DSP_WRITEMASK_ALL)|(WINED3DSP_WRITEMASK_0<<i);
tmpArg.src[1] = arg->src[1]+i;
shader_glsl_dot(&tmpArg);
}
}
/**
The LRP instruction performs a component-wise linear interpolation
between the second and third operands using the first operand as the
blend factor. Equation: (dst = src2 + src0 * (src1 - src2))
This is equivalent to mix(src2, src1, src0);
*/
void shader_glsl_lrp(SHADER_OPCODE_ARG* arg) {
glsl_src_param_t src0_param;
glsl_src_param_t src1_param;
glsl_src_param_t src2_param;
DWORD write_mask;
write_mask = shader_glsl_append_dst(arg->buffer, arg);
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], write_mask, &src0_param);
shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param);
shader_glsl_add_src_param(arg, arg->src[2], arg->src_addr[2], write_mask, &src2_param);
shader_addline(arg->buffer, "mix(%s, %s, %s));\n",
src2_param.param_str, src1_param.param_str, src0_param.param_str);
}
/** Process the WINED3DSIO_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) {
glsl_src_param_t src0_param;
glsl_src_param_t src1_param;
glsl_src_param_t src3_param;
char dst_mask[6];
shader_glsl_append_dst(arg->buffer, arg);
shader_glsl_get_write_mask(arg->dst, dst_mask);
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_1, &src1_param);
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_3, &src3_param);
shader_addline(arg->buffer, "vec4(1.0, (%s > 0.0 ? %s : 0.0), (%s > 0.0 ? ((%s > 0.0) ? pow(%s, clamp(%s, -128.0, 128.0)) : 0.0) : 0.0), 1.0)%s);\n",
src0_param.param_str, src0_param.param_str, src0_param.param_str, src1_param.param_str, src1_param.param_str, src3_param.param_str, dst_mask);
}
/** Process the WINED3DSIO_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) {
glsl_src_param_t src0y_param;
glsl_src_param_t src0z_param;
glsl_src_param_t src1y_param;
glsl_src_param_t src1w_param;
char dst_mask[6];
shader_glsl_append_dst(arg->buffer, arg);
shader_glsl_get_write_mask(arg->dst, dst_mask);
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_1, &src0y_param);
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_2, &src0z_param);
shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_1, &src1y_param);
shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_3, &src1w_param);
shader_addline(arg->buffer, "vec4(1.0, %s * %s, %s, %s))%s;\n",
src0y_param.param_str, src1y_param.param_str, src0z_param.param_str, src1w_param.param_str, dst_mask);
}
/** Process the WINED3DSIO_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) {
glsl_src_param_t src0_param;
DWORD write_mask;
write_mask = shader_glsl_append_dst(arg->buffer, arg);
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
switch (write_mask) {
case WINED3DSP_WRITEMASK_0:
shader_addline(arg->buffer, "cos(%s));\n", src0_param.param_str);
break;
case WINED3DSP_WRITEMASK_1:
shader_addline(arg->buffer, "sin(%s));\n", src0_param.param_str);
break;
case (WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1):
shader_addline(arg->buffer, "vec2(cos(%s), sin(%s)));\n", src0_param.param_str, src0_param.param_str);
break;
default:
ERR("Write mask should be .x, .y or .xy\n");
break;
}
}
/** Process the WINED3DSIO_LOOP instruction in GLSL:
* Start a for() loop where src1.y is the initial value of aL,
* increment aL by src1.z for a total of src1.x iterations.
* Need to use a temporary variable for this operation.
*/
/* FIXME: I don't think nested loops will work correctly this way. */
void shader_glsl_loop(SHADER_OPCODE_ARG* arg) {
glsl_src_param_t src1_param;
shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_ALL, &src1_param);
shader_addline(arg->buffer, "for (tmpInt = 0, aL = %s.y; tmpInt < %s.x; tmpInt++, aL += %s.z) {\n",
src1_param.reg_name, src1_param.reg_name, src1_param.reg_name);
}
void shader_glsl_end(SHADER_OPCODE_ARG* arg) {
shader_addline(arg->buffer, "}\n");
}
void shader_glsl_rep(SHADER_OPCODE_ARG* arg) {
glsl_src_param_t src0_param;
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
shader_addline(arg->buffer, "for (tmpInt = 0; tmpInt < %s; tmpInt++) {\n", src0_param.param_str);
}
void shader_glsl_if(SHADER_OPCODE_ARG* arg) {
glsl_src_param_t src0_param;
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
shader_addline(arg->buffer, "if (%s) {\n", src0_param.param_str);
}
void shader_glsl_ifc(SHADER_OPCODE_ARG* arg) {
glsl_src_param_t src0_param;
glsl_src_param_t src1_param;
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param);
shader_addline(arg->buffer, "if (%s %s %s) {\n",
src0_param.param_str, shader_get_comp_op(arg->opcode_token), src1_param.param_str);
}
void shader_glsl_else(SHADER_OPCODE_ARG* arg) {
shader_addline(arg->buffer, "} else {\n");
}
void shader_glsl_break(SHADER_OPCODE_ARG* arg) {
shader_addline(arg->buffer, "break;\n");
}
/* FIXME: According to MSDN the compare is done per component. */
void shader_glsl_breakc(SHADER_OPCODE_ARG* arg) {
glsl_src_param_t src0_param;
glsl_src_param_t src1_param;
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param);
shader_addline(arg->buffer, "if (%s %s %s) break;\n",
src0_param.param_str, shader_get_comp_op(arg->opcode_token), src1_param.param_str);
}
void shader_glsl_label(SHADER_OPCODE_ARG* arg) {
DWORD snum = (arg->src[0]) & WINED3DSP_REGNUM_MASK;
shader_addline(arg->buffer, "}\n");
shader_addline(arg->buffer, "void subroutine%lu () {\n", snum);
}
void shader_glsl_call(SHADER_OPCODE_ARG* arg) {
DWORD snum = (arg->src[0]) & WINED3DSP_REGNUM_MASK;
shader_addline(arg->buffer, "subroutine%lu();\n", snum);
}
void shader_glsl_callnz(SHADER_OPCODE_ARG* arg) {
glsl_src_param_t src1_param;
DWORD snum = (arg->src[0]) & WINED3DSP_REGNUM_MASK;
shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param);
shader_addline(arg->buffer, "if (%s) subroutine%lu();\n", src1_param.param_str, snum);
}
/*********************************************
* Pixel Shader Specific Code begins here
********************************************/
void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) {
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
DWORD hex_version = This->baseShader.hex_version;
char dst_swizzle[6];
glsl_sample_function_t sample_function;
DWORD sampler_type;
DWORD sampler_idx;
BOOL projected;
DWORD mask = 0;
/* All versions have a destination register */
shader_glsl_append_dst(arg->buffer, arg);
/* 1.0-1.4: Use destination register as sampler source.
* 2.0+: Use provided sampler source. */
if (hex_version < WINED3DPS_VERSION(1,4)) {
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
DWORD flags;
sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS];
if (flags & WINED3DTTFF_PROJECTED) {
projected = TRUE;
switch (flags & ~WINED3DTTFF_PROJECTED) {
case WINED3DTTFF_COUNT1: FIXME("WINED3DTTFF_PROJECTED with WINED3DTTFF_COUNT1?\n"); break;
case WINED3DTTFF_COUNT2: mask = WINED3DSP_WRITEMASK_1; break;
case WINED3DTTFF_COUNT3: mask = WINED3DSP_WRITEMASK_2; break;
case WINED3DTTFF_COUNT4:
case WINED3DTTFF_DISABLE: mask = WINED3DSP_WRITEMASK_3; break;
}
} else {
projected = FALSE;
}
} else if (hex_version < WINED3DPS_VERSION(2,0)) {
DWORD src_mod = arg->src[0] & WINED3DSP_SRCMOD_MASK;
sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
if (src_mod == WINED3DSPSM_DZ) {
projected = TRUE;
mask = WINED3DSP_WRITEMASK_2;
} else if (src_mod == WINED3DSPSM_DW) {
projected = TRUE;
mask = WINED3DSP_WRITEMASK_3;
} else {
projected = FALSE;
}
} else {
sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
if(arg->opcode_token & WINED3DSI_TEXLD_PROJECT) {
/* ps 2.0 texldp instruction always divides by the fourth component. */
projected = TRUE;
mask = WINED3DSP_WRITEMASK_3;
} else {
projected = FALSE;
}
}
sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
shader_glsl_get_sample_function(sampler_type, projected, &sample_function);
mask |= sample_function.coord_mask;
if (hex_version < WINED3DPS_VERSION(2,0)) {
shader_glsl_get_write_mask(arg->dst, dst_swizzle);
} else {
shader_glsl_get_swizzle(arg->src[1], FALSE, arg->dst, dst_swizzle);
}
/* 1.0-1.3: Use destination register as coordinate source.
1.4+: Use provided coordinate source register. */
if (hex_version < WINED3DPS_VERSION(1,4)) {
char coord_mask[6];
shader_glsl_get_write_mask(mask, coord_mask);
shader_addline(arg->buffer, "%s(Psampler%u, T%u%s)%s);\n",
sample_function.name, sampler_idx, sampler_idx, coord_mask, dst_swizzle);
} else {
glsl_src_param_t coord_param;
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], mask, &coord_param);
shader_addline(arg->buffer, "%s(Psampler%u, %s)%s);\n",
sample_function.name, sampler_idx, coord_param.param_str, dst_swizzle);
}
}
void shader_glsl_texldl(SHADER_OPCODE_ARG* arg) {
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*)arg->shader;
glsl_sample_function_t sample_function;
glsl_src_param_t coord_param, lod_param;
char dst_swizzle[6];
DWORD sampler_type;
DWORD sampler_idx;
shader_glsl_append_dst(arg->buffer, arg);
shader_glsl_get_swizzle(arg->src[1], FALSE, arg->dst, dst_swizzle);
sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_M
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -