diff --git a/dlls/d3dx9_36/preshader.c b/dlls/d3dx9_36/preshader.c index 3b06f66972c..25374a3d97c 100644 --- a/dlls/d3dx9_36/preshader.c +++ b/dlls/d3dx9_36/preshader.c @@ -269,6 +269,7 @@ struct const_upload_info unsigned int major_stride; unsigned int major_count; unsigned int count; + unsigned int minor_remainder; }; static enum pres_value_type table_type_from_param_type(D3DXPARAMETER_TYPE type) @@ -1038,10 +1039,22 @@ static void get_const_upload_info(struct d3dx_const_param_eval_output *const_set info->major = param->rows; info->minor = param->columns; } - info->major_stride = max(info->minor, get_reg_components(table)); - info->major_count = min(info->major * info->major_stride, - get_offset_reg(table, const_set->register_count) + info->major_stride - 1) / info->major_stride; - info->count = info->major_count * info->minor; + + if (get_reg_components(table) == 1) + { + unsigned int const_length = get_offset_reg(table, const_set->register_count); + + info->major_stride = info->minor; + info->major_count = const_length / info->major_stride; + info->minor_remainder = const_length % info->major_stride; + } + else + { + info->major_stride = get_reg_components(table); + info->major_count = const_set->register_count; + info->minor_remainder = 0; + } + info->count = info->major_count * info->minor + info->minor_remainder; } static void pres_int_from_float(void *out, const void *in, unsigned int count) @@ -1172,16 +1185,19 @@ static void set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const { for (j = 0; j < info.minor; ++j) { - unsigned int offset; - - offset = i * info.major_stride + j; - if (get_reg_offset(table, offset) >= const_set->register_count) - break; if (info.transpose) param_offset = i + j * info.major; else param_offset = i * info.minor + j; - out[offset] = data[param_offset]; + out[i * info.major_stride + j] = data[param_offset]; + } + } + if (info.transpose) + { + for (j = 0; j < info.minor_remainder; ++j) + { + param_offset = i + j * info.major; + out[i * info.major_stride + j] = data[param_offset]; } } start_offset += get_offset_reg(table, const_set->register_count); @@ -1417,6 +1433,16 @@ static HRESULT init_set_constants_param(struct d3dx_const_tab *const_tab, ID3DXC && !info.transpose && info.minor == info.major_stride && info.count == get_offset_reg(const_set.table, const_set.register_count) && info.count * sizeof(unsigned int) <= param->bytes; + if (info.minor_remainder && !const_set.direct_copy && !info.transpose) + FIXME("Incomplete last row for not transposed matrix which cannot be directly copied, parameter %s.\n", + debugstr_a(param->name)); + + if (info.major_count > info.major + || (info.major_count == info.major && info.minor_remainder)) + { + WARN("Constant dimensions exceed parameter size.\n"); + return D3DERR_INVALIDCALL; + } if (FAILED(hr = append_const_set(const_tab, &const_set))) return hr;