wined3d: shader_trace_init() shouldn't have side effects.

This moves setting baseShader.hex_version and baseShader.functionLength to
shader_get_registers_used(), where it's more appropriate.
This commit is contained in:
Henri Verbeet 2008-12-11 11:52:37 +01:00 committed by Alexandre Julliard
parent 9541c346b3
commit 8124f5e14a
4 changed files with 101 additions and 100 deletions

View File

@ -206,27 +206,28 @@ static void shader_delete_constant_list(struct list* clist) {
/* Note that this does not count the loop register /* Note that this does not count the loop register
* as an address register. */ * as an address register. */
HRESULT shader_get_registers_used( HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_maps *reg_maps,
IWineD3DBaseShader *iface, struct semantic *semantics_in, struct semantic *semantics_out, const DWORD *byte_code,
shader_reg_maps* reg_maps, IWineD3DStateBlockImpl *stateBlock)
semantic* semantics_in, {
semantic* semantics_out,
CONST DWORD* pToken,
IWineD3DStateBlockImpl *stateBlock) {
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
const SHADER_OPCODE *shader_ins = This->baseShader.shader_ins; const SHADER_OPCODE *shader_ins = This->baseShader.shader_ins;
DWORD shader_version = This->baseShader.hex_version; DWORD shader_version = This->baseShader.hex_version;
unsigned int cur_loop_depth = 0, max_loop_depth = 0; unsigned int cur_loop_depth = 0, max_loop_depth = 0;
const DWORD* pToken = byte_code;
char pshader;
/* There are some minor differences between pixel and vertex shaders */ /* There are some minor differences between pixel and vertex shaders */
char pshader = shader_is_pshader_version(This->baseShader.hex_version);
memset(reg_maps->bumpmat, 0, sizeof(reg_maps->bumpmat)); memset(reg_maps->bumpmat, 0, sizeof(reg_maps->bumpmat));
memset(reg_maps->luminanceparams, 0, sizeof(reg_maps->luminanceparams)); memset(reg_maps->luminanceparams, 0, sizeof(reg_maps->luminanceparams));
if (pToken == NULL) if (!pToken)
{
WARN("Got a NULL pFunction, returning.\n");
This->baseShader.functionLength = 0;
return WINED3D_OK; return WINED3D_OK;
}
/* get_registers_used is called on every compile on some 1.x shaders, which can result /* get_registers_used is called on every compile on some 1.x shaders, which can result
* in stacking up a collection of local constants. Delete the old constants if existing * in stacking up a collection of local constants. Delete the old constants if existing
@ -235,17 +236,23 @@ HRESULT shader_get_registers_used(
shader_delete_constant_list(&This->baseShader.constantsB); shader_delete_constant_list(&This->baseShader.constantsB);
shader_delete_constant_list(&This->baseShader.constantsI); shader_delete_constant_list(&This->baseShader.constantsI);
/* The version token is supposed to be the first token */
if (!shader_is_version_token(*pToken))
{
FIXME("First token is not a version token, invalid shader.\n");
return WINED3DERR_INVALIDCALL;
}
shader_version = *pToken++;
This->baseShader.hex_version = shader_version;
pshader = shader_is_pshader_version(shader_version);
while (WINED3DVS_END() != *pToken) { while (WINED3DVS_END() != *pToken) {
CONST SHADER_OPCODE* curOpcode; CONST SHADER_OPCODE* curOpcode;
DWORD opcode_token; DWORD opcode_token;
/* Skip version */
if (shader_is_version_token(*pToken)) {
++pToken;
continue;
/* Skip comments */ /* Skip comments */
} else if (shader_is_comment(*pToken)) { if (shader_is_comment(*pToken))
{
DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT; DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
++pToken; ++pToken;
pToken += comment_len; pToken += comment_len;
@ -499,8 +506,11 @@ HRESULT shader_get_registers_used(
} }
} }
} }
++pToken;
reg_maps->loop_depth = max_loop_depth; reg_maps->loop_depth = max_loop_depth;
This->baseShader.functionLength = ((char *)pToken - (char *)byte_code);
return WINED3D_OK; return WINED3D_OK;
} }
@ -980,38 +990,34 @@ static void shader_dump_ins_modifiers(const DWORD output)
FIXME("_unrecognized_modifier(%#x)", mmask >> WINED3DSP_DSTMOD_SHIFT); FIXME("_unrecognized_modifier(%#x)", mmask >> WINED3DSP_DSTMOD_SHIFT);
} }
/* First pass: trace shader, initialize length and version */ void shader_trace_init(const DWORD *pFunction, const SHADER_OPCODE *opcode_table)
void shader_trace_init( {
IWineD3DBaseShader *iface,
const DWORD* pFunction) {
IWineD3DBaseShaderImpl *This =(IWineD3DBaseShaderImpl *)iface;
const DWORD* pToken = pFunction; const DWORD* pToken = pFunction;
const SHADER_OPCODE* curOpcode = NULL; const SHADER_OPCODE* curOpcode = NULL;
DWORD shader_version;
DWORD opcode_token; DWORD opcode_token;
DWORD i; DWORD i;
TRACE("(%p) : Parsing program\n", This); TRACE("Parsing %p\n", pFunction);
if (!pFunction) if (!pFunction)
{ {
WARN("Got a NULL pFunction, returning.\n"); WARN("Got a NULL pFunction, returning.\n");
This->baseShader.functionLength = 0; /* no Function defined use fixed function vertex processing */
return; return;
} }
/* The version token is supposed to be the first token */
if (!shader_is_version_token(*pToken))
{
FIXME("First token is not a version token, invalid shader.\n");
return;
}
shader_version = *pToken++;
TRACE("%s_%u_%u\n", shader_is_pshader_version(shader_version) ? "ps": "vs",
WINED3DSHADER_VERSION_MAJOR(shader_version), WINED3DSHADER_VERSION_MINOR(shader_version));
while (WINED3DVS_END() != *pToken) while (WINED3DVS_END() != *pToken)
{ {
if (shader_is_version_token(*pToken)) /* version */
{
This->baseShader.hex_version = *pToken;
TRACE("%s_%u_%u\n", shader_is_pshader_version(This->baseShader.hex_version)? "ps": "vs",
WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version),
WINED3DSHADER_VERSION_MINOR(This->baseShader.hex_version));
++pToken;
continue;
}
if (shader_is_comment(*pToken)) /* comment */ if (shader_is_comment(*pToken)) /* comment */
{ {
DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT; DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
@ -1021,13 +1027,13 @@ void shader_trace_init(
continue; continue;
} }
opcode_token = *pToken++; opcode_token = *pToken++;
curOpcode = shader_get_opcode(This->baseShader.shader_ins, This->baseShader.hex_version, opcode_token); curOpcode = shader_get_opcode(opcode_table, shader_version, opcode_token);
if (!curOpcode) if (!curOpcode)
{ {
int tokens_read; int tokens_read;
FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token); FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token);
tokens_read = shader_skip_unrecognized(pToken, This->baseShader.hex_version); tokens_read = shader_skip_unrecognized(pToken, shader_version);
pToken += tokens_read; pToken += tokens_read;
} }
else else
@ -1037,10 +1043,10 @@ void shader_trace_init(
DWORD usage = *pToken; DWORD usage = *pToken;
DWORD param = *(pToken + 1); DWORD param = *(pToken + 1);
shader_dump_decl_usage(usage, param, This->baseShader.hex_version); shader_dump_decl_usage(usage, param, shader_version);
shader_dump_ins_modifiers(param); shader_dump_ins_modifiers(param);
TRACE(" "); TRACE(" ");
shader_dump_param(param, 0, 0, This->baseShader.hex_version); shader_dump_param(param, 0, 0, shader_version);
pToken += 2; pToken += 2;
} }
else if (curOpcode->opcode == WINED3DSIO_DEF) else if (curOpcode->opcode == WINED3DSIO_DEF)
@ -1079,7 +1085,7 @@ void shader_trace_init(
if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED) if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
{ {
TRACE("("); TRACE("(");
shader_dump_param(*(pToken + 2), 0, 1, This->baseShader.hex_version); shader_dump_param(*(pToken + 2), 0, 1, shader_version);
TRACE(") "); TRACE(") ");
} }
if (opcode_token & WINED3DSI_COISSUE) if (opcode_token & WINED3DSI_COISSUE)
@ -1107,7 +1113,7 @@ void shader_trace_init(
} }
} }
else if (curOpcode->opcode == WINED3DSIO_TEX else if (curOpcode->opcode == WINED3DSIO_TEX
&& This->baseShader.hex_version >= WINED3DPS_VERSION(2,0) && shader_version >= WINED3DPS_VERSION(2,0)
&& (opcode_token & WINED3DSI_TEXLD_PROJECT)) && (opcode_token & WINED3DSI_TEXLD_PROJECT))
{ {
TRACE("p"); TRACE("p");
@ -1116,12 +1122,12 @@ void shader_trace_init(
/* Destination token */ /* Destination token */
if (curOpcode->dst_token) if (curOpcode->dst_token)
{ {
tokens_read = shader_get_param(pToken, This->baseShader.hex_version, &param, &addr_token); tokens_read = shader_get_param(pToken, shader_version, &param, &addr_token);
pToken += tokens_read; pToken += tokens_read;
shader_dump_ins_modifiers(param); shader_dump_ins_modifiers(param);
TRACE(" "); TRACE(" ");
shader_dump_param(param, addr_token, 0, This->baseShader.hex_version); shader_dump_param(param, addr_token, 0, shader_version);
} }
/* Predication token - already printed out, just skip it */ /* Predication token - already printed out, just skip it */
@ -1133,19 +1139,16 @@ void shader_trace_init(
/* Other source tokens */ /* Other source tokens */
for (i = curOpcode->dst_token; i < curOpcode->num_params; ++i) for (i = curOpcode->dst_token; i < curOpcode->num_params; ++i)
{ {
tokens_read = shader_get_param(pToken, This->baseShader.hex_version, &param, &addr_token); tokens_read = shader_get_param(pToken, shader_version, &param, &addr_token);
pToken += tokens_read; pToken += tokens_read;
TRACE((i == 0)? " " : ", "); TRACE((i == 0)? " " : ", ");
shader_dump_param(param, addr_token, 1, This->baseShader.hex_version); shader_dump_param(param, addr_token, 1, shader_version);
} }
} }
TRACE("\n"); TRACE("\n");
} }
} }
++pToken;
This->baseShader.functionLength = ((char *)pToken - (char *)pFunction);
} }
void shader_cleanup(IWineD3DBaseShader *iface) void shader_cleanup(IWineD3DBaseShader *iface)

View File

@ -316,67 +316,67 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface; IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device; IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
unsigned int i, highest_reg_used = 0, num_regs_used = 0;
shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
HRESULT hr;
TRACE("(%p) : pFunction %p\n", iface, pFunction); TRACE("(%p) : pFunction %p\n", iface, pFunction);
/* First pass: trace shader */ /* First pass: trace shader */
shader_trace_init((IWineD3DBaseShader*) This, pFunction); shader_trace_init(pFunction, This->baseShader.shader_ins);
pshader_set_limits(This);
/* Initialize immediate constant lists */ /* Initialize immediate constant lists */
list_init(&This->baseShader.constantsF); list_init(&This->baseShader.constantsF);
list_init(&This->baseShader.constantsB); list_init(&This->baseShader.constantsB);
list_init(&This->baseShader.constantsI); list_init(&This->baseShader.constantsI);
if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) > 1) { /* Second pass: figure out which registers are used, what the semantics are, etc.. */
shader_reg_maps *reg_maps = &This->baseShader.reg_maps; memset(reg_maps, 0, sizeof(shader_reg_maps));
HRESULT hr; hr = shader_get_registers_used((IWineD3DBaseShader *)This, reg_maps,
unsigned int i, j, highest_reg_used = 0, num_regs_used = 0; This->semantics_in, NULL, pFunction, deviceImpl->stateBlock);
if (FAILED(hr)) return hr;
/* Second pass: figure out which registers are used, what the semantics are, etc.. */ pshader_set_limits(This);
memset(reg_maps, 0, sizeof(shader_reg_maps));
hr = shader_get_registers_used((IWineD3DBaseShader*) This, reg_maps,
This->semantics_in, NULL, pFunction, NULL);
if (FAILED(hr)) return hr;
/* FIXME: validate reg_maps against OpenGL */
for(i = 0; i < MAX_REG_INPUT; i++) { for (i = 0; i < MAX_REG_INPUT; ++i)
if(This->input_reg_used[i]) { {
num_regs_used++; if (This->input_reg_used[i])
highest_reg_used = i; {
} ++num_regs_used;
} highest_reg_used = i;
/* Don't do any register mapping magic if it is not needed, or if we can't
* achieve anything anyway
*/
if(highest_reg_used < (GL_LIMITS(glsl_varyings) / 4) ||
num_regs_used > (GL_LIMITS(glsl_varyings) / 4) ) {
if(num_regs_used > (GL_LIMITS(glsl_varyings) / 4)) {
/* This happens with relative addressing. The input mapper function
* warns about this if the higher registers are declared too, so
* don't write a FIXME here
*/
WARN("More varying registers used than supported\n");
}
for(i = 0; i < MAX_REG_INPUT; i++) {
This->input_reg_map[i] = i;
}
This->declared_in_count = highest_reg_used + 1;
} else {
j = 0;
for(i = 0; i < MAX_REG_INPUT; i++) {
if(This->input_reg_used[i]) {
This->input_reg_map[i] = j;
j++;
} else {
This->input_reg_map[i] = -1;
}
}
This->declared_in_count = j;
} }
} }
/* Don't do any register mapping magic if it is not needed, or if we can't
* achieve anything anyway */
if (highest_reg_used < (GL_LIMITS(glsl_varyings) / 4)
|| num_regs_used > (GL_LIMITS(glsl_varyings) / 4))
{
if (num_regs_used > (GL_LIMITS(glsl_varyings) / 4))
{
/* This happens with relative addressing. The input mapper function
* warns about this if the higher registers are declared too, so
* don't write a FIXME here */
WARN("More varying registers used than supported\n");
}
for (i = 0; i < MAX_REG_INPUT; ++i)
{
This->input_reg_map[i] = i;
}
This->declared_in_count = highest_reg_used + 1;
}
else
{
This->declared_in_count = 0;
for (i = 0; i < MAX_REG_INPUT; ++i)
{
if (This->input_reg_used[i]) This->input_reg_map[i] = This->declared_in_count++;
else This->input_reg_map[i] = -1;
}
}
This->baseShader.load_local_constsF = FALSE; This->baseShader.load_local_constsF = FALSE;
This->baseShader.shader_mode = deviceImpl->ps_selected_mode; This->baseShader.shader_mode = deviceImpl->ps_selected_mode;

View File

@ -435,8 +435,7 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
TRACE("(%p) : pFunction %p\n", iface, pFunction); TRACE("(%p) : pFunction %p\n", iface, pFunction);
/* First pass: trace shader */ /* First pass: trace shader */
shader_trace_init((IWineD3DBaseShader*) This, pFunction); shader_trace_init(pFunction, This->baseShader.shader_ins);
vshader_set_limits(This);
/* Initialize immediate constant lists */ /* Initialize immediate constant lists */
list_init(&This->baseShader.constantsF); list_init(&This->baseShader.constantsF);
@ -451,6 +450,8 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
This->semantics_in, This->semantics_out, pFunction, NULL); This->semantics_in, This->semantics_out, pFunction, NULL);
if (hr != WINED3D_OK) return hr; if (hr != WINED3D_OK) return hr;
vshader_set_limits(This);
This->baseShader.shader_mode = deviceImpl->vs_selected_mode; This->baseShader.shader_mode = deviceImpl->vs_selected_mode;
if(deviceImpl->vs_selected_mode == SHADER_ARB && if(deviceImpl->vs_selected_mode == SHADER_ARB &&

View File

@ -2229,6 +2229,7 @@ typedef struct IWineD3DBaseShaderImpl {
void shader_buffer_init(struct SHADER_BUFFER *buffer); void shader_buffer_init(struct SHADER_BUFFER *buffer);
void shader_buffer_free(struct SHADER_BUFFER *buffer); void shader_buffer_free(struct SHADER_BUFFER *buffer);
void shader_cleanup(IWineD3DBaseShader *iface); void shader_cleanup(IWineD3DBaseShader *iface);
void shader_trace_init(const DWORD *byte_code, const SHADER_OPCODE *opcode_table);
extern HRESULT shader_get_registers_used( extern HRESULT shader_get_registers_used(
IWineD3DBaseShader *iface, IWineD3DBaseShader *iface,
@ -2241,10 +2242,6 @@ extern HRESULT shader_get_registers_used(
extern void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer, extern 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);
extern void shader_trace_init(
IWineD3DBaseShader *iface,
const DWORD* pFunction);
static inline int shader_get_regtype(const DWORD param) { static inline int shader_get_regtype(const DWORD param) {
return (((param & WINED3DSP_REGTYPE_MASK) >> WINED3DSP_REGTYPE_SHIFT) | return (((param & WINED3DSP_REGTYPE_MASK) >> WINED3DSP_REGTYPE_SHIFT) |
((param & WINED3DSP_REGTYPE_MASK2) >> WINED3DSP_REGTYPE_SHIFT2)); ((param & WINED3DSP_REGTYPE_MASK2) >> WINED3DSP_REGTYPE_SHIFT2));