diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 556d213d6ab..a0e62f1b881 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -195,5 +195,7 @@ void d3dx_create_param_eval(struct d3dx9_base_effect *base_effect, void *byte_co void d3dx_free_param_eval(struct d3dx_param_eval *peval) DECLSPEC_HIDDEN; HRESULT d3dx_evaluate_parameter(struct d3dx_param_eval *peval, const struct d3dx_parameter *param, void *param_value) DECLSPEC_HIDDEN; +HRESULT d3dx_param_eval_set_shader_constants(struct IDirect3DDevice9 *device, + struct d3dx_param_eval *peval) DECLSPEC_HIDDEN; #endif /* __WINE_D3DX9_PRIVATE_H */ diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 1c836eb452c..da7de540e50 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -2718,7 +2718,53 @@ static HRESULT d3dx_set_shader_const_state(IDirect3DDevice9 *device, enum SHADER } static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pass *pass, - struct d3dx_state *state, int parent_index) + struct d3dx_state *state, unsigned int parent_index); + +static HRESULT d3dx_set_shader_constants(struct ID3DXEffectImpl *effect, struct d3dx_pass *pass, + struct d3dx_parameter *param, BOOL vs) +{ + IDirect3DDevice9 *device = effect->device; + HRESULT hr, ret; + struct d3dx_parameter **params; + D3DXCONSTANT_DESC *cdesc; + unsigned int parameters_count; + unsigned int i, j; + + if (!param->param_eval) + { + FIXME("param_eval structure is null.\n"); + return D3DERR_INVALIDCALL; + } + if (FAILED(hr = d3dx_param_eval_set_shader_constants(device, param->param_eval))) + return hr; + params = param->param_eval->shader_inputs.inputs_param; + cdesc = param->param_eval->shader_inputs.inputs; + parameters_count = param->param_eval->shader_inputs.input_count; + ret = D3D_OK; + for (i = 0; i < parameters_count; ++i) + { + if (params[i] && params[i]->class == D3DXPC_OBJECT && (params[i]->type == D3DXPT_SAMPLER + || params[i]->type == D3DXPT_SAMPLER1D || params[i]->type == D3DXPT_SAMPLER2D + || params[i]->type == D3DXPT_SAMPLER3D || params[i]->type == D3DXPT_SAMPLERCUBE)) + { + struct d3dx_sampler *sampler; + + sampler = (struct d3dx_sampler *)params[i]->data; + TRACE("sampler %s, register index %u, state count %u.\n", debugstr_a(params[i]->name), + cdesc[i].RegisterIndex, sampler->state_count); + for (j = 0; j < sampler->state_count; ++j) + { + if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[j], + cdesc[i].RegisterIndex + (vs ? D3DVERTEXTEXTURESAMPLER0 : 0)))) + ret = hr; + } + } + } + return ret; +} + +static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pass *pass, + struct d3dx_state *state, unsigned int parent_index) { IDirect3DDevice9 *device = effect->device; struct d3dx_parameter *param; @@ -2744,7 +2790,7 @@ static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pas { UINT unit; - unit = parent_index == -1 ? state->index : parent_index; + unit = parent_index == ~0u ? state->index : parent_index; TRACE("%s, unit %u, value %p.\n", state_table[state->operation].name, unit, *(IDirect3DBaseTexture9 **)param_value); return IDirect3DDevice9_SetTexture(device, unit, *(IDirect3DBaseTexture9 **)param_value); @@ -2774,7 +2820,7 @@ static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pas { UINT sampler; - sampler = parent_index == -1 ? state->index : parent_index; + sampler = parent_index == ~0u ? state->index : parent_index; TRACE("%s, sampler %u, value %u.\n", state_table[state->operation].name, sampler, *(DWORD *)param_value); return IDirect3DDevice9_SetSamplerState(device, sampler, state_table[state->operation].op, *(DWORD *)param_value); @@ -2783,13 +2829,15 @@ static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pas TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DVertexShader9 **)param_value); if (FAILED(hr = IDirect3DDevice9_SetVertexShader(device, *(IDirect3DVertexShader9 **)param_value))) ERR("Could not set vertex shader, hr %#x.\n", hr); - FIXME("Not executing preshader and not setting constants.\n"); + else if (*(IDirect3DVertexShader9 **)param_value) + hr = d3dx_set_shader_constants(effect, pass, param, TRUE); return hr; case SC_PIXELSHADER: TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DPixelShader9 **)param_value); if (FAILED(hr = IDirect3DDevice9_SetPixelShader(device, *(IDirect3DPixelShader9 **)param_value))) ERR("Could not set pixel shader, hr %#x.\n", hr); - FIXME("Not executing preshader and not setting constants.\n"); + else if (*(IDirect3DPixelShader9 **)param_value) + hr = d3dx_set_shader_constants(effect, pass, param, FALSE); return hr; case SC_TRANSFORM: TRACE("%s, state %u.\n", state_table[state->operation].name, state->index); @@ -2853,7 +2901,7 @@ static HRESULT d3dx9_apply_pass_states(struct ID3DXEffectImpl *effect, struct d3 { HRESULT hr; - if (FAILED(hr = d3dx9_apply_state(effect, pass, &pass->states[i], -1))) + if (FAILED(hr = d3dx9_apply_state(effect, pass, &pass->states[i], ~0u))) { WARN("Error applying state, hr %#x.\n", hr); ret = hr; diff --git a/dlls/d3dx9_36/preshader.c b/dlls/d3dx9_36/preshader.c index b831be1ed75..2287f15fb39 100644 --- a/dlls/d3dx9_36/preshader.c +++ b/dlls/d3dx9_36/preshader.c @@ -297,6 +297,18 @@ static void regstore_set_double(struct d3dx_regstore *rs, unsigned int table, un 1u << (reg_idx % PRES_BITMASK_BLOCK_SIZE); } +static void regstore_reset_table(struct d3dx_regstore *rs, unsigned int table) +{ + unsigned int size; + + size = rs->table_sizes[table] * table_info[table].reg_component_count * table_info[table].component_size; + + memset(rs->tables[table], 0, size); + memset(rs->table_value_set[table], 0, + sizeof(*rs->table_value_set[table]) * + ((rs->table_sizes[table] + PRES_BITMASK_BLOCK_SIZE - 1) / PRES_BITMASK_BLOCK_SIZE)); +} + static void dump_bytecode(void *data, unsigned int size) { unsigned int *bytecode = (unsigned int *)data; @@ -1059,3 +1071,104 @@ HRESULT d3dx_evaluate_parameter(struct d3dx_param_eval *peval, const struct d3dx set_number((unsigned int *)param_value + i, param->type, oc + i, D3DXPT_FLOAT); return D3D_OK; } + +static HRESULT set_shader_constants_device(struct IDirect3DDevice9 *device, struct d3dx_regstore *rs, + D3DXPARAMETER_TYPE type, enum pres_reg_tables table) +{ + unsigned int start, count; + void *ptr; + HRESULT hr, result; + + result = D3D_OK; + start = 0; + while (start < rs->table_sizes[table]) + { + count = 0; + while (start < rs->table_sizes[table] && !regstore_is_val_set_reg(rs, table, start)) + ++start; + while (start + count < rs->table_sizes[table] && regstore_is_val_set_reg(rs, table, start + count)) + ++count; + if (!count) + break; + TRACE("Setting %u constants at %u.\n", count, start); + ptr = (BYTE *)rs->tables[table] + start * table_info[table].reg_component_count + * table_info[table].component_size; + if (type == D3DXPT_VERTEXSHADER) + { + switch(table) + { + case PRES_REGTAB_OCONST: + hr = IDirect3DDevice9_SetVertexShaderConstantF(device, start, (const float *)ptr, count); + break; + case PRES_REGTAB_OICONST: + hr = IDirect3DDevice9_SetVertexShaderConstantI(device, start, (const int *)ptr, count); + break; + case PRES_REGTAB_OBCONST: + hr = IDirect3DDevice9_SetVertexShaderConstantB(device, start, (const BOOL *)ptr, count); + break; + default: + FIXME("Unexpected register table %u.\n", table); + return D3DERR_INVALIDCALL; + } + } + else if (type == D3DXPT_PIXELSHADER) + { + switch(table) + { + case PRES_REGTAB_OCONST: + hr = IDirect3DDevice9_SetPixelShaderConstantF(device, start, (const float *)ptr, count); + break; + case PRES_REGTAB_OICONST: + hr = IDirect3DDevice9_SetPixelShaderConstantI(device, start, (const int *)ptr, count); + break; + case PRES_REGTAB_OBCONST: + hr = IDirect3DDevice9_SetPixelShaderConstantB(device, start, (const BOOL *)ptr, count); + break; + default: + FIXME("Unexpected register table %u.\n", table); + return D3DERR_INVALIDCALL; + } + } + else + { + FIXME("Unexpected parameter type %u.\n", type); + return D3DERR_INVALIDCALL; + } + + if (FAILED(hr)) + { + ERR("Setting constants failed, type %u, table %u, hr %#x.\n", type, table, hr); + result = hr; + } + start += count; + } + regstore_reset_table(rs, table); + return result; +} + +HRESULT d3dx_param_eval_set_shader_constants(struct IDirect3DDevice9 *device, struct d3dx_param_eval *peval) +{ + static const enum pres_reg_tables set_tables[] = + {PRES_REGTAB_OCONST, PRES_REGTAB_OICONST, PRES_REGTAB_OBCONST}; + HRESULT hr, result; + struct d3dx_preshader *pres = &peval->pres; + struct d3dx_regstore *rs = &pres->regs; + unsigned int i; + + TRACE("device %p, peval %p, param_type %u.\n", device, peval, peval->param_type); + + if (FAILED(hr = set_constants(rs, &pres->inputs))) + return hr; + if (FAILED(hr = execute_preshader(pres))) + return hr; + if (FAILED(hr = set_constants(rs, &peval->shader_inputs))) + return hr; + + result = D3D_OK; + for (i = 0; i < ARRAY_SIZE(set_tables); ++i) + { + if (FAILED(hr = set_shader_constants_device(device, rs, peval->param_type, set_tables[i]))) + result = hr; + } + return result; +} diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index b38128bcec0..9d58a809eef 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -3790,7 +3790,7 @@ static void test_effect_preshader(IDirect3DDevice9 *device) hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, &fdata[0].x, TEST_EFFECT_PRES_NFLOATV); ok(hr == D3D_OK, "Got result %#x.\n", hr); - todo_wine ok(!memcmp(fdata, test_effect_preshader_fconstsv, sizeof(test_effect_preshader_fconstsv)), + ok(!memcmp(fdata, test_effect_preshader_fconstsv, sizeof(test_effect_preshader_fconstsv)), "Vertex shader float constants do not match.\n"); for (i = TEST_EFFECT_PRES_NFLOATV; i < 256; ++i) { @@ -3801,7 +3801,7 @@ static void test_effect_preshader(IDirect3DDevice9 *device) } hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, &fdata[0].x, TEST_EFFECT_PRES_NFLOATP); ok(hr == D3D_OK, "Got result %#x.\n", hr); - todo_wine ok(!memcmp(fdata, test_effect_preshader_fconstsp, sizeof(test_effect_preshader_fconstsp)), + ok(!memcmp(fdata, test_effect_preshader_fconstsp, sizeof(test_effect_preshader_fconstsp)), "Pixel shader float constants do not match.\n"); for (i = TEST_EFFECT_PRES_NFLOATP; i < 224; ++i) {