From 59b01089a26ea463ff1cd6acd4f877c44da92aa3 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 26 Oct 2021 23:25:08 +0200 Subject: [PATCH] d3d10/effect: Fix buffer offsets for members and array elements. Signed-off-by: Nikolay Sivov Signed-off-by: Matteo Bruni Signed-off-by: Alexandre Julliard --- dlls/d3d10/effect.c | 24 ++++++++++++++++++++++-- dlls/d3d10/tests/effect.c | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c index 7590bba6317..3ceb1a1fbb3 100644 --- a/dlls/d3d10/effect.c +++ b/dlls/d3d10/effect.c @@ -21,6 +21,7 @@ #include "d3d10_private.h" #include +#include WINE_DEFAULT_DEBUG_CHANNEL(d3d10); @@ -2075,10 +2076,25 @@ static HRESULT parse_fx10_technique(const char *data, size_t data_size, return S_OK; } +static void d3d10_effect_variable_update_buffer_offsets(struct d3d10_effect_variable *v, + unsigned int offset) +{ + unsigned int i; + + for (i = 0; i < v->type->member_count; ++i) + d3d10_effect_variable_update_buffer_offsets(&v->members[i], offset); + + for (i = 0; i < v->type->element_count; ++i) + d3d10_effect_variable_update_buffer_offsets(&v->elements[i], offset); + + v->buffer_offset += offset; +} + static HRESULT parse_fx10_numeric_variable(const char *data, size_t data_size, const char **ptr, BOOL local, struct d3d10_effect_variable *v) { DWORD offset, flags, default_value_offset; + uint32_t buffer_offset; HRESULT hr; if (FAILED(hr = parse_fx10_variable_head(data, data_size, ptr, v))) @@ -2094,8 +2110,8 @@ static HRESULT parse_fx10_numeric_variable(const char *data, size_t data_size, } TRACE("Variable semantic: %s.\n", debugstr_a(v->semantic)); - read_dword(ptr, &v->buffer_offset); - TRACE("Variable offset in buffer: %#x.\n", v->buffer_offset); + read_dword(ptr, &buffer_offset); + TRACE("Variable offset in buffer: %#x.\n", buffer_offset); read_dword(ptr, &default_value_offset); @@ -2104,6 +2120,10 @@ static HRESULT parse_fx10_numeric_variable(const char *data, size_t data_size, v->flag |= flags; + /* At this point storage offsets for members and array elements are relative to containing + variable. Update them by moving to correct offset within a buffer. */ + d3d10_effect_variable_update_buffer_offsets(v, buffer_offset); + if (local) { if (default_value_offset) diff --git a/dlls/d3d10/tests/effect.c b/dlls/d3d10/tests/effect.c index bd5392fcd16..2844386ef51 100644 --- a/dlls/d3d10/tests/effect.c +++ b/dlls/d3d10/tests/effect.c @@ -5126,16 +5126,17 @@ static void test_effect_scalar_variable(void) {"i_a", D3D10_SVT_INT, TRUE}, {"b_a", D3D10_SVT_BOOL, TRUE}, }; + ID3D10EffectScalarVariable *s_v, *s_v2; + ID3D10EffectVariable *var, *var2; D3D10_EFFECT_TYPE_DESC type_desc; D3D10_EFFECT_DESC effect_desc; - ID3D10EffectScalarVariable *s_v; - ID3D10EffectVariable *var; ID3D10EffectType *type; ID3D10Device *device; ID3D10Effect *effect; unsigned int i; ULONG refcount; HRESULT hr; + float f; if (!(device = create_device())) { @@ -5176,6 +5177,22 @@ static void test_effect_scalar_variable(void) test_scalar_array_methods(s_v, tests[i].type, tests[i].name); } + /* Verify that offsets are working correctly between array elements and adjacent data. */ + var = effect->lpVtbl->GetVariableByName(effect, "f0"); + s_v = var->lpVtbl->AsScalar(var); + hr = s_v->lpVtbl->SetFloat(s_v, 1.0f); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + var2 = effect->lpVtbl->GetVariableByName(effect, "f_a"); + var2 = var2->lpVtbl->GetElement(var2, 0); + s_v2 = var->lpVtbl->AsScalar(var2); + hr = s_v2->lpVtbl->SetFloat(s_v2, 2.0f); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = s_v->lpVtbl->GetFloat(s_v, &f); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(f == 1.0f, "Unexpected value %f.\n", f); + effect->lpVtbl->Release(effect); refcount = ID3D10Device_Release(device); @@ -7310,10 +7327,11 @@ static DWORD fx_test_default_variable_value[] = static void test_effect_default_variable_value(void) { + D3D10_EFFECT_VARIABLE_DESC var_desc; ID3D10EffectVectorVariable *vector; ID3D10EffectScalarVariable *scalar; + ID3D10EffectVariable *v, *v2; float float_v[4], float_s; - ID3D10EffectVariable *v; ID3D10Effect *effect; ID3D10Device *device; int int_v[2], int_s; @@ -7373,6 +7391,17 @@ todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr); todo_wine ok(int_v[0] == 9 && int_v[1] == 12, "Unexpected vector {%d,%d}\n", int_v[0], int_v[1]); + hr = v->lpVtbl->GetDesc(v, &var_desc); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(var_desc.BufferOffset == 32, "Unexpected offset %u.\n", var_desc.BufferOffset); + v2 = v->lpVtbl->GetElement(v, 0); + hr = v2->lpVtbl->GetDesc(v2, &var_desc); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(var_desc.BufferOffset == 32, "Unexpected offset %u.\n", var_desc.BufferOffset); + v2 = v->lpVtbl->GetElement(v, 1); + hr = v2->lpVtbl->GetDesc(v2, &var_desc); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(var_desc.BufferOffset == 48, "Unexpected offset %u.\n", var_desc.BufferOffset); float_s = 0.0f; v = effect->lpVtbl->GetVariableByName(effect, "f");