wined3d: Implement loops with the NV extensions.

This commit is contained in:
Stefan Dösinger 2009-06-03 07:14:36 +02:00 committed by Alexandre Julliard
parent 298bd3c50d
commit 51cdc9d361
1 changed files with 313 additions and 66 deletions

View File

@ -74,21 +74,12 @@ static unsigned int reserved_vs_const(IWineD3DBaseShader *shader, const WineD3D_
#define ARB_SHADER_PRIVCONST_POS ARB_SHADER_PRIVCONST_BASE + 0
/* ARB_program_shader private data */
struct shader_arb_priv
struct control_frame
{
GLuint current_vprogram_id;
GLuint current_fprogram_id;
const struct arb_ps_compiled_shader *compiled_fprog;
GLuint depth_blt_vprogram_id;
GLuint depth_blt_fprogram_id[tex_type_count];
BOOL use_arbfp_fixed_func;
struct wine_rb_tree fragment_shaders;
};
struct if_frame {
struct list entry;
BOOL ifc;
BOOL muting;
unsigned int loop_no;
};
struct arb_ps_compile_args
@ -107,9 +98,25 @@ struct arb_ps_compiled_shader
{
struct arb_ps_compile_args args;
GLuint prgId;
struct stb_const_desc bumpenvmatconst[MAX_TEXTURES];
unsigned char numbumpenvmatconsts;
struct stb_const_desc luminanceconst[MAX_TEXTURES];
struct stb_const_desc bumpenvmatconst[MAX_TEXTURES];
unsigned char numbumpenvmatconsts;
struct stb_const_desc luminanceconst[MAX_TEXTURES];
UINT int_consts[MAX_CONST_I];
char num_int_consts;
};
struct arb_vs_compile_args
{
struct vs_compile_args super;
DWORD bools; /* WORD is enough, use DWORD for alignment */
};
struct arb_vs_compiled_shader
{
struct arb_vs_compile_args args;
GLuint prgId;
UINT int_consts[MAX_CONST_I];
char num_int_consts;
};
struct shader_arb_ctx_priv {
@ -126,8 +133,10 @@ struct shader_arb_ctx_priv {
const struct arb_vs_compile_args *cur_vs_args;
const struct arb_ps_compile_args *cur_ps_args;
const struct arb_ps_compiled_shader *compiled_fprog;
struct list if_frames;
const struct arb_vs_compiled_shader *compiled_vprog;
struct list control_frames;
BOOL muted;
unsigned int num_loops, loop_depth;
};
struct arb_pshader_private {
@ -135,21 +144,23 @@ struct arb_pshader_private {
UINT num_gl_shaders, shader_array_size;
};
struct arb_vs_compile_args {
struct vs_compile_args super;
DWORD bools; /* WORD is enough, use DWORD for alignment */
};
struct arb_vs_compiled_shader {
struct arb_vs_compile_args args;
GLuint prgId;
};
struct arb_vshader_private {
struct arb_vs_compiled_shader *gl_shaders;
UINT num_gl_shaders, shader_array_size;
};
struct shader_arb_priv
{
GLuint current_vprogram_id;
GLuint current_fprogram_id;
const struct arb_ps_compiled_shader *compiled_fprog;
const struct arb_vs_compiled_shader *compiled_vprog;
GLuint depth_blt_vprogram_id;
GLuint depth_blt_fprogram_id[tex_type_count];
BOOL use_arbfp_fixed_func;
struct wine_rb_tree fragment_shaders;
};
/********************************************************
* ARB_[vertex/fragment]_program helper functions follow
********************************************************/
@ -294,7 +305,52 @@ static inline void shader_arb_ps_local_constants(IWineD3DDeviceImpl* deviceImpl)
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->luminanceconst[i].const_num, scale));
}
}
if(gl_shader->num_int_consts == 0) return;
for(i = 0; i < MAX_CONST_I; i++)
{
if(gl_shader->int_consts[i] != WINED3D_CONST_NUM_UNUSED)
{
float val[4];
val[0] = stateBlock->pixelShaderConstantI[4 * i];
val[1] = stateBlock->pixelShaderConstantI[4 * i + 1];
val[2] = stateBlock->pixelShaderConstantI[4 * i + 2];
val[3] = -1.0;
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->int_consts[i], val));
}
}
}
static inline void shader_arb_vs_local_constants(IWineD3DDeviceImpl* deviceImpl)
{
IWineD3DStateBlockImpl* stateBlock;
const WineD3D_GL_Info *gl_info;
unsigned char i;
struct shader_arb_priv *priv = deviceImpl->shader_priv;
const struct arb_vs_compiled_shader *gl_shader = priv->compiled_vprog;
if(gl_shader->num_int_consts == 0) return;
gl_info = &deviceImpl->adapter->gl_info;
stateBlock = deviceImpl->stateBlock;
for(i = 0; i < MAX_CONST_I; i++)
{
if(gl_shader->int_consts[i] != WINED3D_CONST_NUM_UNUSED)
{
float val[4];
val[0] = stateBlock->vertexShaderConstantI[4 * i];
val[1] = stateBlock->vertexShaderConstantI[4 * i + 1];
val[2] = stateBlock->vertexShaderConstantI[4 * i + 2];
val[3] = -1.0;
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->int_consts[i], val));
}
}
}
/**
* Loads the app-supplied constants into the currently set ARB_[vertex/fragment]_programs.
*
@ -323,6 +379,8 @@ static void shader_arb_load_constants(
/* Upload the position fixup */
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, ARB_SHADER_PRIVCONST_POS, deviceImpl->posFixup));
shader_arb_vs_local_constants(deviceImpl);
}
if (usePixelShader) {
@ -406,6 +464,7 @@ static DWORD shader_generate_arb_declarations(IWineD3DBaseShader *iface, const s
if(This->baseShader.reg_maps.usesrelconstF) {
max_constantsF = GL_LIMITS(vshader_constantsF) - reserved_vs_const(iface, gl_info);
if(GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION)) max_constantsF -= GL_LIMITS(clipplanes);
max_constantsF -= count_bits(This->baseShader.reg_maps.integer_constants);
} else {
max_constantsF = GL_LIMITS(vshader_constantsF) - 1;
}
@ -670,6 +729,16 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction
else sprintf(register_name, "result.texcoord[%u]", reg->idx);
break;
case WINED3DSPR_LOOP:
/* Pshader has an implicitly declared loop index counter A0.x that cannot be renamed */
if(pshader) sprintf(register_name, "A0.x");
else sprintf(register_name, "aL.y");
break;
case WINED3DSPR_CONSTINT:
sprintf(register_name, "I%u", reg->idx);
break;
default:
FIXME("Unhandled register type %#x[%u]\n", reg->type, reg->idx);
sprintf(register_name, "unrecognized_register[%u]", reg->idx);
@ -1958,6 +2027,106 @@ static void shader_hw_sgn(const struct wined3d_shader_instruction *ins)
}
}
static void shader_hw_loop(const struct wined3d_shader_instruction *ins)
{
SHADER_BUFFER *buffer = ins->ctx->buffer;
char src_name[50];
BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
/* src0 is aL */
shader_arb_get_src_param(ins, &ins->src[1], 0, src_name);
if(vshader)
{
struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
struct list *e = list_head(&priv->control_frames);
struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
if(priv->loop_depth > 1) shader_addline(buffer, "PUSHA aL;\n");
/* The constant loader makes sure to load -1 into iX.w */
shader_addline(buffer, "ARLC aL, %s.xywz;\n", src_name);
shader_addline(buffer, "BRA loop_%u_end (LE.x);\n", control_frame->loop_no);
shader_addline(buffer, "loop_%u_start:\n", control_frame->loop_no);
}
else
{
shader_addline(buffer, "LOOP %s;\n", src_name);
}
}
static void shader_hw_rep(const struct wined3d_shader_instruction *ins)
{
SHADER_BUFFER *buffer = ins->ctx->buffer;
char src_name[50];
BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
shader_arb_get_src_param(ins, &ins->src[0], 0, src_name);
/* The constant loader makes sure to load -1 into iX.w */
if(vshader)
{
struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
struct list *e = list_head(&priv->control_frames);
struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
if(priv->loop_depth > 1) shader_addline(buffer, "PUSHA aL;\n");
shader_addline(buffer, "ARLC aL, %s.xywz;\n", src_name);
shader_addline(buffer, "BRA loop_%u_end (LE.x);\n", control_frame->loop_no);
shader_addline(buffer, "loop_%u_start:\n", control_frame->loop_no);
}
else
{
shader_addline(buffer, "REP %s;\n", src_name);
}
}
static void shader_hw_endloop(const struct wined3d_shader_instruction *ins)
{
SHADER_BUFFER *buffer = ins->ctx->buffer;
BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
if(vshader)
{
struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
struct list *e = list_head(&priv->control_frames);
struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
shader_addline(buffer, "ARAC aL.xy, aL;\n");
shader_addline(buffer, "BRA loop_%u_start (GT.x);\n", control_frame->loop_no);
shader_addline(buffer, "loop_%u_end:\n", control_frame->loop_no);
if(priv->loop_depth > 1) shader_addline(buffer, "POPA aL;\n");
}
else
{
shader_addline(buffer, "ENDLOOP;\n");
}
}
static void shader_hw_endrep(const struct wined3d_shader_instruction *ins)
{
SHADER_BUFFER *buffer = ins->ctx->buffer;
BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
if(vshader)
{
struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
struct list *e = list_head(&priv->control_frames);
struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
shader_addline(buffer, "ARAC aL.xy, aL;\n");
shader_addline(buffer, "BRA loop_%u_start (GT.x);\n", control_frame->loop_no);
shader_addline(buffer, "loop_%u_end:\n", control_frame->loop_no);
if(priv->loop_depth > 1) shader_addline(buffer, "POPA aL;\n");
}
else
{
shader_addline(buffer, "ENDREP;\n");
}
}
static GLuint create_arb_blt_vertex_program(const WineD3D_GL_Info *gl_info)
{
GLuint program_id = 0;
@ -2077,6 +2246,20 @@ static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcol
/* [0.0;1.0] clamping. Not needed, this is done implicitly */
}
static const DWORD *find_loop_control_values(IWineD3DBaseShaderImpl *This, DWORD idx)
{
const local_constant *constant;
LIST_FOR_EACH_ENTRY(constant, &This->baseShader.constantsI, local_constant, entry)
{
if (constant->idx == idx)
{
return constant->value;
}
}
return NULL;
}
/* GL locking is done by the caller */
static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This,
SHADER_BUFFER *buffer, const struct arb_ps_compile_args *args, struct arb_ps_compiled_shader *compiled)
@ -2135,7 +2318,7 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This,
memset(&priv_ctx, 0, sizeof(priv_ctx));
priv_ctx.cur_ps_args = args;
priv_ctx.compiled_fprog = compiled;
list_init(&priv_ctx.if_frames);
list_init(&priv_ctx.control_frames);
/* Avoid enabling NV_fragment_program* if we do not need it.
*
@ -2231,9 +2414,9 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This,
if(!reg_maps->bumpmat[i]) continue;
cur = compiled->numbumpenvmatconsts;
compiled->bumpenvmatconst[cur].const_num = -1;
compiled->bumpenvmatconst[cur].const_num = WINED3D_CONST_NUM_UNUSED;
compiled->bumpenvmatconst[cur].texunit = i;
compiled->luminanceconst[cur].const_num = -1;
compiled->luminanceconst[cur].const_num = WINED3D_CONST_NUM_UNUSED;
compiled->luminanceconst[cur].texunit = i;
/* We can fit the constants into the constant limit for sure because texbem, texbeml, bem and beml are only supported
@ -2257,6 +2440,27 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This,
i, compiled->luminanceconst[cur].const_num);
}
for(i = 0; i < MAX_CONST_I; i++)
{
compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED;
if (reg_maps->integer_constants & (1 << i) && priv_ctx.target_version >= NV2)
{
const DWORD *control_values = find_loop_control_values((IWineD3DBaseShaderImpl *) This, i);
if(control_values)
{
shader_addline(buffer, "PARAM I%u = {%u, %u, %u, -1};\n", i,
control_values[0], control_values[1], control_values[2]);
}
else
{
compiled->int_consts[i] = next_local;
compiled->num_int_consts++;
shader_addline(buffer, "PARAM I%u = program.local[%u];\n", i, next_local++);
}
}
}
/* Base Shader Body */
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
@ -2302,7 +2506,7 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This,
/* GL locking is done by the caller */
static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This,
SHADER_BUFFER *buffer, const struct arb_vs_compile_args *args)
SHADER_BUFFER *buffer, const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled)
{
const shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
@ -2310,13 +2514,13 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This,
const WineD3D_GL_Info *gl_info = &device->adapter->gl_info;
const local_constant *lconst;
GLuint ret;
DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This);
DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This), next_local;
struct shader_arb_ctx_priv priv_ctx;
unsigned int i;
memset(&priv_ctx, 0, sizeof(priv_ctx));
priv_ctx.cur_vs_args = args;
list_init(&priv_ctx.if_frames);
list_init(&priv_ctx.control_frames);
/* Create the hw ARB shader */
shader_addline(buffer, "!!ARBvp1.0\n");
@ -2327,6 +2531,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This,
if(GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION)) {
shader_addline(buffer, "OPTION NV_vertex_program2;\n");
priv_ctx.target_version = NV2;
shader_addline(buffer, "ADDRESS aL;\n");
} else {
priv_ctx.target_version = ARB;
}
@ -2343,7 +2548,28 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This,
shader_addline(buffer, "TEMP TA;\n");
/* Base Declarations */
shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, lconst_map);
next_local = shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, lconst_map);
for(i = 0; i < MAX_CONST_I; i++)
{
compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED;
if(reg_maps->integer_constants & (1 << i) && priv_ctx.target_version >= NV2)
{
const DWORD *control_values = find_loop_control_values((IWineD3DBaseShaderImpl *) This, i);
if(control_values)
{
shader_addline(buffer, "PARAM I%u = {%u, %u, %u, -1};\n", i,
control_values[0], control_values[1], control_values[2]);
}
else
{
compiled->int_consts[i] = next_local;
compiled->num_int_consts++;
shader_addline(buffer, "PARAM I%u = program.local[%u];\n", i, next_local++);
}
}
}
/* We need a constant to fixup the final position */
shader_addline(buffer, "PARAM posFixup = program.env[%d];\n", ARB_SHADER_PRIVCONST_POS);
@ -2518,7 +2744,7 @@ static inline BOOL vs_args_equal(const struct arb_vs_compile_args *stored, const
return stored->bools == new->bools;
}
static GLuint find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct arb_vs_compile_args *args)
static struct arb_vs_compiled_shader *find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct arb_vs_compile_args *args)
{
UINT i;
DWORD new_size;
@ -2539,7 +2765,7 @@ static GLuint find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct ar
*/
for(i = 0; i < shader_data->num_gl_shaders; i++) {
if(vs_args_equal(&shader_data->gl_shaders[i].args, args, use_map)) {
return shader_data->gl_shaders[i].prgId;
return &shader_data->gl_shaders[i];
}
}
@ -2549,10 +2775,10 @@ static GLuint find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct ar
if (shader_data->num_gl_shaders)
{
new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders,
new_array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, shader_data->gl_shaders,
new_size * sizeof(*shader_data->gl_shaders));
} else {
new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader_data->gl_shaders));
new_array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data->gl_shaders));
new_size = 1;
}
@ -2567,11 +2793,12 @@ static GLuint find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct ar
shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args;
shader_buffer_init(&buffer);
ret = shader_arb_generate_vshader(shader, &buffer, args);
ret = shader_arb_generate_vshader(shader, &buffer, args,
&shader_data->gl_shaders[shader_data->num_gl_shaders]);
shader_buffer_free(&buffer);
shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
shader_data->gl_shaders[shader_data->num_gl_shaders].prgId = ret;
return ret;
return &shader_data->gl_shaders[shader_data->num_gl_shaders++];
}
static inline void find_arb_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImpl *stateblock,
@ -2587,7 +2814,6 @@ static inline void find_arb_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWi
{
if(stateblock->pixelShaderConstantB[i]) args->bools |= ( 1 << i);
}
}
static inline void find_arb_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockImpl *stateblock,
@ -2615,10 +2841,13 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
if (useVS) {
struct arb_vs_compile_args compile_args;
struct arb_vs_compiled_shader *compiled;
TRACE("Using vertex shader\n");
find_arb_vs_compile_args((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, This->stateBlock, &compile_args);
priv->current_vprogram_id = find_arb_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args);
compiled = find_arb_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args);
priv->current_vprogram_id = compiled->prgId;
priv->compiled_vprog = compiled;
/* Bind the vertex program */
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
@ -2628,6 +2857,7 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
glEnable(GL_VERTEX_PROGRAM_ARB);
checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
shader_arb_vs_local_constants(This);
} else if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
priv->current_vprogram_id = 0;
glDisable(GL_VERTEX_PROGRAM_ARB);
@ -2878,8 +3108,8 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL
/* WINED3DSIH_DSY */ NULL,
/* WINED3DSIH_ELSE */ NULL,
/* WINED3DSIH_ENDIF */ NULL,
/* WINED3DSIH_ENDLOOP */ NULL,
/* WINED3DSIH_ENDREP */ NULL,
/* WINED3DSIH_ENDLOOP */ shader_hw_endloop,
/* WINED3DSIH_ENDREP */ shader_hw_endrep,
/* WINED3DSIH_EXP */ shader_hw_map2gl,
/* WINED3DSIH_EXPP */ shader_hw_map2gl,
/* WINED3DSIH_FRC */ shader_hw_map2gl,
@ -2889,7 +3119,7 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL
/* WINED3DSIH_LIT */ shader_hw_map2gl,
/* WINED3DSIH_LOG */ shader_hw_map2gl,
/* WINED3DSIH_LOGP */ shader_hw_map2gl,
/* WINED3DSIH_LOOP */ NULL,
/* WINED3DSIH_LOOP */ shader_hw_loop,
/* WINED3DSIH_LRP */ shader_hw_lrp,
/* WINED3DSIH_M3x2 */ shader_hw_mnxn,
/* WINED3DSIH_M3x3 */ shader_hw_mnxn,
@ -2907,7 +3137,7 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL
/* WINED3DSIH_PHASE */ NULL,
/* WINED3DSIH_POW */ shader_hw_map2gl,
/* WINED3DSIH_RCP */ shader_hw_rsq_rcp,
/* WINED3DSIH_REP */ NULL,
/* WINED3DSIH_REP */ shader_hw_rep,
/* WINED3DSIH_RET */ NULL,
/* WINED3DSIH_RSQ */ shader_hw_rsq_rcp,
/* WINED3DSIH_SETP */ NULL,
@ -2973,20 +3203,20 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
SHADER_HANDLER hw_fct;
struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
struct if_frame *if_frame;
struct control_frame *control_frame;
SHADER_BUFFER *buffer = ins->ctx->buffer;
/* boolean if */
if(ins->handler_idx == WINED3DSIH_IF)
{
if_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*if_frame));
list_add_head(&priv->if_frames, &if_frame->entry);
control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
list_add_head(&priv->control_frames, &control_frame->entry);
if(!priv->muted && get_bool_const(ins, This, ins->src[0].reg.idx) == FALSE)
{
shader_addline(buffer, "#if(FALSE){\n");
priv->muted = TRUE;
if_frame->muting = TRUE;
control_frame->muting = TRUE;
}
else shader_addline(buffer, "#if(TRUE) {\n");
@ -2995,48 +3225,56 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
else if(ins->handler_idx == WINED3DSIH_IFC)
{
/* IF(bool) and if_cond(a, b) use the same ELSE and ENDIF tokens */
if_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*if_frame));
if_frame->ifc = TRUE;
list_add_head(&priv->if_frames, &if_frame->entry);
control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
control_frame->ifc = TRUE;
list_add_head(&priv->control_frames, &control_frame->entry);
}
else if(ins->handler_idx == WINED3DSIH_ELSE)
{
struct list *e = list_head(&priv->if_frames);
if_frame = LIST_ENTRY(e, struct if_frame, entry);
struct list *e = list_head(&priv->control_frames);
control_frame = LIST_ENTRY(e, struct control_frame, entry);
if(if_frame->ifc == FALSE)
if(control_frame->ifc == FALSE)
{
shader_addline(buffer, "#} else {\n");
if(!priv->muted && !if_frame->muting)
if(!priv->muted && !control_frame->muting)
{
priv->muted = TRUE;
if_frame->muting = TRUE;
control_frame->muting = TRUE;
}
else if(if_frame->muting) priv->muted = FALSE;
else if(control_frame->muting) priv->muted = FALSE;
return; /* Instruction is handled. */
}
/* In case of an ifc, generate a HW shader instruction */
}
else if(ins->handler_idx == WINED3DSIH_ENDIF)
{
struct list *e = list_head(&priv->if_frames);
if_frame = LIST_ENTRY(e, struct if_frame, entry);
struct list *e = list_head(&priv->control_frames);
control_frame = LIST_ENTRY(e, struct control_frame, entry);
if(!if_frame->ifc)
if(!control_frame->ifc)
{
shader_addline(buffer, "#} endif\n");
if(if_frame->muting) priv->muted = FALSE;
list_remove(&if_frame->entry);
HeapFree(GetProcessHeap(), 0, if_frame);
if(control_frame->muting) priv->muted = FALSE;
list_remove(&control_frame->entry);
HeapFree(GetProcessHeap(), 0, control_frame);
return; /* Instruction is handled */
}
else
{
list_remove(&if_frame->entry);
HeapFree(GetProcessHeap(), 0, if_frame);
list_remove(&control_frame->entry);
HeapFree(GetProcessHeap(), 0, control_frame);
/* ifc - generate a hw endif */
}
}
else if(ins->handler_idx == WINED3DSIH_LOOP || ins->handler_idx == WINED3DSIH_REP)
{
control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
list_add_head(&priv->control_frames, &control_frame->entry);
control_frame->loop_no = priv->num_loops++;
priv->loop_depth++;
}
if(priv->muted) return;
@ -3051,6 +3289,15 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
}
hw_fct(ins);
if(ins->handler_idx == WINED3DSIH_ENDLOOP || ins->handler_idx == WINED3DSIH_ENDREP)
{
struct list *e = list_head(&priv->control_frames);
control_frame = LIST_ENTRY(e, struct control_frame, entry);
list_remove(&control_frame->entry);
HeapFree(GetProcessHeap(), 0, control_frame);
priv->loop_depth--;
}
shader_arb_add_instruction_modifiers(ins);
}