[PATCH 1/2] d3dx9: Add 'exp' preshader opcode.
Paul Gofman
gofmanp at gmail.com
Thu Apr 21 03:56:44 CDT 2016
Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
dlls/d3dx9_36/preshader.c | 3 ++
dlls/d3dx9_36/tests/effect.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+)
diff --git a/dlls/d3dx9_36/preshader.c b/dlls/d3dx9_36/preshader.c
index 2287f15..a16c065 100644
--- a/dlls/d3dx9_36/preshader.c
+++ b/dlls/d3dx9_36/preshader.c
@@ -43,6 +43,7 @@ enum pres_ops
PRESHADER_OP_SIN,
PRESHADER_OP_COS,
PRESHADER_OP_RSQ,
+ PRESHADER_OP_EXP,
};
typedef double (*pres_op_func)(double *args, int n);
@@ -80,6 +81,7 @@ static double pres_rsq(double *args, int n)
else
return 1.0 / sqrt(v);
}
+static double pres_exp(double *args, int n) {return pow(2.0, args[0]);}
#define PRES_OPCODE_MASK 0x7ff00000
#define PRES_OPCODE_SHIFT 20
@@ -119,6 +121,7 @@ static const struct op_info pres_op_info[] =
{0x108, "sin", 1, 0, pres_sin}, /* PRESHADER_OP_SIN */
{0x109, "cos", 1, 0, pres_cos}, /* PRESHADER_OP_COS */
{0x107, "rsq", 1, 0, pres_rsq}, /* PRESHADER_OP_RSQ */
+ {0x105, "exp", 1, 0, pres_exp}, /* PRESHADER_OP_EXP */
};
enum pres_value_type
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c
index 9d58a80..cfd058a 100644
--- a/dlls/d3dx9_36/tests/effect.c
+++ b/dlls/d3dx9_36/tests/effect.c
@@ -3634,6 +3634,12 @@ static const DWORD test_effect_preshader_effect_blob[] =
#define TEST_EFFECT_PRESHADER_VSHADER_POS 1035
#define TEST_EFFECT_PRESHADER_VSHADER_LEN 13
+#define TEST_EFFECT_PRESHADER_OP0_POS 2468
+#define TEST_EFFECT_PRESHADER_OP0_INS_SIZE 8
+
+#define TEST_EFFECT_PRESHADER_OPMUL_POS 2319
+#define TEST_EFFECT_PRESHADER_OPMUL_INS_SIZE 11
+
static void test_effect_preshader(IDirect3DDevice9 *device)
{
static const D3DXVECTOR4 test_effect_preshader_fconstsv[] =
@@ -3886,6 +3892,91 @@ static void test_effect_preshader(IDirect3DDevice9 *device)
effect->lpVtbl->Release(effect);
}
+static void test_preshader_op(IDirect3DDevice9 *device, const char *op_mnem,
+ unsigned int opcode, unsigned int args_count, unsigned int *expected_result,
+ D3DXVECTOR4 *fvect1, D3DXVECTOR4 *fvect2, unsigned int ulps, BOOL *todo)
+{
+ DWORD test_effect_blob[ARRAY_SIZE(test_effect_preshader_effect_blob)];
+ HRESULT hr;
+ ID3DXEffect *effect;
+ D3DLIGHT9 light;
+ unsigned int i, npasses;
+ float *v;
+ unsigned int op_pos, op_step, result_index;
+ D3DXHANDLE param;
+
+ if (args_count == 1)
+ {
+ op_pos = TEST_EFFECT_PRESHADER_OP0_POS;
+ op_step = TEST_EFFECT_PRESHADER_OP0_INS_SIZE;
+ result_index = 0;
+ }
+ else if (args_count == 2)
+ {
+ op_pos = TEST_EFFECT_PRESHADER_OPMUL_POS;
+ op_step = TEST_EFFECT_PRESHADER_OPMUL_INS_SIZE;
+ result_index = 2;
+ }
+ else
+ {
+ return;
+ }
+
+ memcpy(test_effect_blob, test_effect_preshader_effect_blob, sizeof test_effect_blob);
+ for (i = 0; i < 4; i++)
+ test_effect_blob[op_pos + i * op_step] = opcode;
+
+ hr = D3DXCreateEffect(device, test_effect_blob, sizeof(test_effect_blob),
+ NULL, NULL, 0, NULL, &effect, NULL);
+ ok(hr == D3D_OK, "Got result %#x.\n", hr);
+ hr = effect->lpVtbl->Begin(effect, &npasses, 0);
+ ok(hr == D3D_OK, "Got result %#x.\n", hr);
+
+ if (fvect1)
+ {
+ param = effect->lpVtbl->GetParameterByName(effect, NULL, "opvect1");
+ ok(!!param, "GetParameterByName failed.\n");
+ hr = effect->lpVtbl->SetVector(effect, param, fvect1);
+ ok(hr == D3D_OK, "SetVector failed, hr %#x.\n", hr);
+ }
+ if (fvect2)
+ {
+ param = effect->lpVtbl->GetParameterByName(effect, NULL, "opvect2");
+ ok(!!param, "GetParameterByName failed.\n");
+ hr = effect->lpVtbl->SetVector(effect, param, fvect2);
+ ok(hr == D3D_OK, "SetVector failed, hr %#x.\n", hr);
+ }
+
+ hr = effect->lpVtbl->BeginPass(effect, 0);
+ ok(hr == D3D_OK, "Got result %#x.\n", hr);
+
+ hr = IDirect3DDevice9_GetLight(device, result_index, &light);
+ ok(hr == D3D_OK, "Got result %#x.\n", hr);
+ v = &light.Diffuse.r;
+ for (i = 0; i < 4; ++i)
+ todo_wine_if(todo && todo[i])
+ ok(compare_float(v[i], ((float *)expected_result)[i], ulps),
+ "Operation %s, component %u, expected %#x (%g), got %#x (%g).\n", op_mnem,
+ i, expected_result[i], ((float *)expected_result)[i], ((unsigned int *)v)[i], v[i]);
+
+ hr = effect->lpVtbl->EndPass(effect);
+ ok(hr == D3D_OK, "Got result %#x.\n", hr);
+ hr = effect->lpVtbl->End(effect);
+ ok(hr == D3D_OK, "Got result %#x.\n", hr);
+ effect->lpVtbl->Release(effect);
+}
+
+static void test_effect_preshader_ops(IDirect3DDevice9 *device)
+{
+ unsigned int expected_result[4];
+
+ expected_result[0] = 0x3f800000;
+ expected_result[1] = 0x3f800000;
+ expected_result[2] = 0x3e5edc66;
+ expected_result[3] = 0x7f800000;
+ test_preshader_op(device, "exp", 0x10500001, 1, expected_result, NULL, NULL, 0, NULL);
+}
+
START_TEST(effect)
{
HWND wnd;
@@ -3927,6 +4018,7 @@ START_TEST(effect)
test_effect_compilation_errors(device);
test_effect_states(device);
test_effect_preshader(device);
+ test_effect_preshader_ops(device);
count = IDirect3DDevice9_Release(device);
ok(count == 0, "The device was not properly freed: refcount %u\n", count);
--
2.5.5
More information about the wine-patches
mailing list