On Tue, Nov 9, 2021 at 12:40 PM Nikolay Sivov <nsivov(a)codeweavers.com> wrote:
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> --- dlls/d3d10/effect.c | 595 +++++++++++++++++++++++++++++++++++++- dlls/d3d10/tests/effect.c | 147 ++++++++++ 2 files changed, 734 insertions(+), 8 deletions(-)
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c index 78a3d0c386a..3f35e9cc28a 100644 --- a/dlls/d3d10/effect.c +++ b/dlls/d3d10/effect.c
+static HRESULT d3d10_effect_preshader_eval(struct d3d10_effect_preshader *p) +{ + unsigned int i, j, regt, offset, instr_count, input_count; + const DWORD *ip = ID3D10Blob_GetBufferPointer(p->code); + float *dst, *args[4], *retval; + struct preshader_instr ins; + + dst = d3d10_effect_preshader_get_reg_ptr(p, D3D10_REG_TABLE_RESULT, 0); + memset(dst, 0, sizeof(float) * p->reg_tables[D3D10_REG_TABLE_RESULT].count); + + /* Update constant buffer */ + dst = d3d10_effect_preshader_get_reg_ptr(p, D3D10_REG_TABLE_CB, 0); + for (i = 0; i < p->vars_count; ++i) + { + struct d3d10_ctab_var *v = &p->vars[i]; + memcpy(dst + v->offset, v->v->buffer->u.buffer.local_buffer + v->v->buffer_offset, + v->length * sizeof(*dst)); + } + + instr_count = *ip++; + + for (i = 0; i < instr_count; ++i) + { + *(DWORD *)&ins = *ip++; + input_count = *ip++; + + if (input_count > ARRAY_SIZE(args)) + { + FIXME("Unexpected argument count %u.\n", input_count); + return E_FAIL; + } + + /* Arguments */ + for (j = 0; j < input_count; ++j) + { + ip++; /* TODO: argument register flags are currently ignored */ + regt = *ip++; + offset = *ip++; + + args[j] = d3d10_effect_preshader_get_reg_ptr(p, regt, offset); + } + + ip++; /* TODO: result register flags are currently ignored */ + regt = *ip++; + offset = *ip++; + retval = d3d10_effect_preshader_get_reg_ptr(p, regt, offset); + + *retval = d3d10_effect_get_op_info(ins.opcode)->func(args, input_count);
Making sure I get this right: in d3d10 FXLVM all instructions / operands are scalar, correct?
@@ -528,24 +727,58 @@ static void d3d10_effect_update_dependent_props(struct d3d10_effect_prop_depende property_info = &property_infos[d->id];
dst = (char *)container + property_info->offset; + dst_index = (unsigned int *)((char *)container + property_info->index_offset);
switch (d->operation) { case D3D10_EOO_VAR: case D3D10_EOO_CONST_INDEX:
- v = d->u.var.v; + v = d->var.v;
count = v->type->type_class == D3D10_SVC_VECTOR ? 4 : 1;
for (j = 0; j < count; ++j) { - d3d10_effect_variable_get_raw_value(v, &value, d->u.var.offset + j * sizeof(value), sizeof(value)); + d3d10_effect_variable_get_raw_value(v, &value, d->var.offset + j * sizeof(value), sizeof(value)); d3d10_effect_read_numeric_value(value, v->type->basetype, property_info->type, dst, j); }
break;
+ case D3D10_EOO_INDEX_EXPRESSION: + + v = d->index_expr.v; + + if (FAILED(hr = d3d10_effect_preshader_eval(&d->index_expr.index))) + { + WARN("Failed to evaluate index expression, hr %#x.\n", hr); + return; + } + + variable_idx = *d->index_expr.index.reg_tables[D3D10_REG_TABLE_RESULT].dword; + + if (variable_idx >= v->type->element_count) + { + WARN("Expression evaluated to invalid index value %u, array %s of size %u.\n", + variable_idx, debugstr_a(v->name), v->type->element_count); + return; + } + + /* Ignoring destination index here, there are no object typed array properties. */ + switch (property_info->type) + { + case D3D10_SVT_VERTEXSHADER: + case D3D10_SVT_PIXELSHADER: + case D3D10_SVT_GEOMETRYSHADER: + *(void **)dst = v; + *dst_index = variable_idx; + break; + default: + *(void **)dst = &v->elements[variable_idx];
I guess we could have explicit D3D10_SVT_BLEND and such cases in the switch and print a WARN for those, to be super safe.