wined3d: Emulate the 4 component address register in ARB.

This commit is contained in:
Stefan Dösinger 2009-05-15 13:56:40 +02:00 committed by Alexandre Julliard
parent 72e9e80f6e
commit 7b1d48721d
4 changed files with 52 additions and 14 deletions

View File

@ -84,6 +84,10 @@ struct shader_arb_priv {
struct hash_table_t *fragment_shaders;
};
struct shader_arb_ctx_priv {
char addr_reg[20];
};
/********************************************************
* ARB_[vertex/fragment]_program helper functions follow
********************************************************/
@ -503,6 +507,17 @@ static void shader_arb_get_swizzle(const struct wined3d_shader_src_param *param,
*ptr = '\0';
}
static void shader_arb_request_a0(const struct wined3d_shader_instruction *ins, const char *src)
{
struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
SHADER_BUFFER *buffer = ins->ctx->buffer;
if(strcmp(priv->addr_reg, src) == 0) return;
strcpy(priv->addr_reg, src);
shader_addline(buffer, "ARL A0.x, %s;\n", src);
}
static void shader_arb_get_src_param(const struct wined3d_shader_instruction *ins,
const struct wined3d_shader_src_param *src, unsigned int tmpreg, char *outregstr);
@ -543,7 +558,9 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction
if(This->baseShader.reg_maps.shader_version.major < 2) {
sprintf(rel_reg, "A0.x");
} else {
shader_arb_get_src_param(ins, reg->rel_addr, 0, rel_reg);
/* FIXME: GL_NV_vertex_progam2_option */
shader_arb_request_a0(ins, rel_reg);
sprintf(rel_reg, "A0.x");
}
if (reg->idx >= rel_offset)
@ -574,7 +591,17 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction
sprintf(register_name, "fragment.texcoord[%u]", reg->idx);
}
}
else sprintf(register_name, "A%u", reg->idx);
else
{
if(This->baseShader.reg_maps.shader_version.major == 1)
{
sprintf(register_name, "A%u", reg->idx);
}
else
{
sprintf(register_name, "A%u_SHADOW", reg->idx);
}
}
break;
case WINED3DSPR_COLOROUT:
@ -1016,9 +1043,11 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
if(ins->handler_idx == WINED3DSIH_MOVA) {
struct wined3d_shader_src_param tmp_src = ins->src[0];
char write_mask[6];
tmp_src.swizzle = (tmp_src.swizzle & 0x3) * 0x55;
shader_arb_get_src_param(ins, &tmp_src, 0, src0_param);
shader_arb_get_write_mask(ins, &ins->dst[0], write_mask);
/* This implements the mova formula used in GLSL. The first two instructions
* prepare the sign() part. Note that it is fine to have my_sign(0.0) = 1.0
@ -1027,16 +1056,20 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
*
* A0.x = arl(floor(abs(0.0) + 0.5) * 1.0) = floor(0.5) = 0.0 since arl does a floor
*
* The ARL is performed when A0 is used - the requested component is read from A0_SHADOW into
* A0.x. We can use the overwritten component of A0_shadow as temporary storage for the sign.
*
* TODO: ARR from GL_NV_vertex_program2_option
*/
shader_addline(buffer, "SGE TA.y, %s, mova_const.y;\n", src0_param);
shader_addline(buffer, "MAD TA.y, TA.y, mova_const.z, -mova_const.w;\n");
shader_addline(buffer, "SGE A0_SHADOW%s, %s, mova_const.y;\n", write_mask, src0_param);
shader_addline(buffer, "MAD A0_SHADOW%s, A0_SHADOW, mova_const.z, -mova_const.w;\n", write_mask);
shader_addline(buffer, "ABS TA.x, %s;\n", src0_param);
shader_addline(buffer, "ADD TA.x, TA.x, mova_const.x;\n");
shader_addline(buffer, "FLR TA.x, TA.x;\n");
shader_addline(buffer, "MUL TA.x, TA.x, TA.y;\n");
shader_addline(buffer, "ARL A0.x, TA.x;\n");
shader_addline(buffer, "ABS TA%s, %s;\n", write_mask, src0_param);
shader_addline(buffer, "ADD TA%s, TA, mova_const.x;\n", write_mask);
shader_addline(buffer, "FLR TA%s, TA;\n", write_mask);
shader_addline(buffer, "MUL A0_SHADOW%s, TA, A0_SHADOW;\n", write_mask);
((struct shader_arb_ctx_priv *)ins->ctx->backend_data)->addr_reg[0] = '\0';
} else if (ins->ctx->reg_maps->shader_version.major == 1
&& !shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)
&& ins->dst[0].reg.type == WINED3DSPR_ADDR)
@ -1982,7 +2015,7 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface,
shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, lconst_map);
/* Base Shader Body */
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function);
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, NULL);
if(args->srgb_correction) {
arbfp_add_sRGB_correction(buffer, fragcolor, "TA", "TB", "TC");
@ -2036,7 +2069,9 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
const local_constant *lconst;
GLuint ret;
DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This);
struct shader_arb_ctx_priv priv_ctx;
memset(&priv_ctx, 0, sizeof(priv_ctx));
/* Create the hw ARB shader */
shader_addline(buffer, "!!ARBvp1.0\n");
@ -2045,6 +2080,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
}
if(need_mova_const((IWineD3DBaseShader *) iface, gl_info)) {
shader_addline(buffer, "PARAM mova_const = { 0.5, 0.0, 2.0, 1.0 };\n");
shader_addline(buffer, "TEMP A0_SHADOW;\n");
}
/* Mesa supports only 95 constants */
@ -2086,7 +2122,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
}
/* Base Shader Body */
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function);
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
/* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
* or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),

View File

@ -929,7 +929,7 @@ void shader_dump_src_param(const struct wined3d_shader_src_param *param,
/* Shared code in order to generate the bulk of the shader string.
* NOTE: A description of how to parse tokens can be found on msdn */
void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer,
const shader_reg_maps *reg_maps, const DWORD *pFunction)
const shader_reg_maps *reg_maps, const DWORD *pFunction, void *backend_ctx)
{
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; /* To access shader backend callbacks */
@ -951,6 +951,7 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer,
ctx.shader = iface;
ctx.reg_maps = reg_maps;
ctx.buffer = buffer;
ctx.backend_data = backend_ctx;
ins.ctx = &ctx;
ins.dst = &dst_param;

View File

@ -4142,7 +4142,7 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface,
}
/* Base Shader Body */
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function);
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, NULL);
/* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
if (reg_maps->shader_version.major < 2)
@ -4229,7 +4229,7 @@ static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface,
shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, NULL);
/* Base Shader Body */
shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function);
shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function, NULL);
/* Unpack 3.0 outputs */
if (reg_maps->shader_version.major >= 3) shader_addline(buffer, "order_ps_input(OUT);\n");

View File

@ -648,6 +648,7 @@ struct wined3d_shader_context
IWineD3DBaseShader *shader;
const struct shader_reg_maps *reg_maps;
SHADER_BUFFER *buffer;
void *backend_data;
};
struct wined3d_shader_register
@ -2575,7 +2576,7 @@ void shader_dump_src_param(const struct wined3d_shader_src_param *param,
void shader_dump_dst_param(const struct wined3d_shader_dst_param *param,
const struct wined3d_shader_version *shader_version);
void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer,
const shader_reg_maps *reg_maps, const DWORD *pFunction);
const shader_reg_maps *reg_maps, const DWORD *pFunction, void *backend_ctx);
HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3d_shader_frontend *fe,
struct shader_reg_maps *reg_maps, struct wined3d_shader_semantic *semantics_in,
struct wined3d_shader_semantic *semantics_out, const DWORD *byte_code, DWORD constf_size);