d3dx9: Add ID3DXEffectCompiler interface.
authorRico Schüller <kgbricola@web.de>
Sun, 27 Mar 2011 20:12:45 +0000 (22:12 +0200)
committerAlexandre Julliard <julliard@winehq.org>
Tue, 29 Mar 2011 16:05:29 +0000 (18:05 +0200)
dlls/d3dx9_36/effect.c

index 459c927..3c3a082 100644 (file)
@@ -28,6 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 static const struct ID3DXEffectVtbl ID3DXEffect_Vtbl;
 static const struct ID3DXBaseEffectVtbl ID3DXBaseEffect_Vtbl;
+static const struct ID3DXEffectCompilerVtbl ID3DXEffectCompiler_Vtbl;
 
 struct ID3DXBaseEffectImpl
 {
@@ -51,6 +52,14 @@ struct ID3DXEffectImpl
     ID3DXBaseEffect *base_effect;
 };
 
+struct ID3DXEffectCompilerImpl
+{
+    ID3DXEffectCompiler ID3DXEffectCompiler_iface;
+    LONG ref;
+
+    ID3DXBaseEffect *base_effect;
+};
+
 static inline void read_dword(const char **ptr, DWORD *d)
 {
     memcpy(d, *ptr, sizeof(*d));
@@ -87,6 +96,16 @@ static void free_effect(struct ID3DXEffectImpl *effect)
     IDirect3DDevice9_Release(effect->device);
 }
 
+static void free_effect_compiler(struct ID3DXEffectCompilerImpl *compiler)
+{
+    TRACE("Free effect compiler %p\n", compiler);
+
+    if (compiler->base_effect)
+    {
+        compiler->base_effect->lpVtbl->Release(compiler->base_effect);
+    }
+}
+
 static inline DWORD d3dx9_effect_version(DWORD major, DWORD minor)
 {
     return (0xfeff0000 | ((major) << 8) | (minor));
@@ -1568,185 +1587,950 @@ static const struct ID3DXEffectVtbl ID3DXEffect_Vtbl =
     ID3DXEffectImpl_SetRawValue
 };
 
-static HRESULT d3dx9_parse_effect(struct ID3DXBaseEffectImpl *base, const char *data, UINT data_size, DWORD start)
+static inline struct ID3DXEffectCompilerImpl *impl_from_ID3DXEffectCompiler(ID3DXEffectCompiler *iface)
 {
-    const char *ptr = data + start;
-
-    read_dword(&ptr, &base->parameter_count);
-    TRACE("Parameter count: %u\n", base->parameter_count);
+    return CONTAINING_RECORD(iface, struct ID3DXEffectCompilerImpl, ID3DXEffectCompiler_iface);
+}
 
-    read_dword(&ptr, &base->technique_count);
-    TRACE("Technique count: %u\n", base->technique_count);
+/*** IUnknown methods ***/
+static HRESULT WINAPI ID3DXEffectCompilerImpl_QueryInterface(ID3DXEffectCompiler *iface, REFIID riid, void **object)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
 
-    skip_dword_unknown(&ptr, 2);
+    TRACE("iface %p, riid %s, object %p\n", This, debugstr_guid(riid), object);
 
-    /* todo: Parse parameter */
+    if (IsEqualGUID(riid, &IID_IUnknown) ||
+        IsEqualGUID(riid, &IID_ID3DXEffectCompiler))
+    {
+        This->ID3DXEffectCompiler_iface.lpVtbl->AddRef(iface);
+        *object = This;
+        return S_OK;
+    }
 
-    /* todo: Parse techniques */
+    ERR("Interface %s not found\n", debugstr_guid(riid));
 
-    return S_OK;
+    return E_NOINTERFACE;
 }
 
-static HRESULT d3dx9_base_effect_init(struct ID3DXBaseEffectImpl *base,
-        const char *data, SIZE_T data_size, struct ID3DXEffectImpl *effect)
+static ULONG WINAPI ID3DXEffectCompilerImpl_AddRef(ID3DXEffectCompiler *iface)
 {
-    DWORD tag, offset;
-    const char *ptr = data;
-    HRESULT hr;
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
 
-    TRACE("base %p, data %p, data_size %lu, effect %p\n", base, data, data_size, effect);
+    TRACE("iface %p: AddRef from %u\n", iface, This->ref);
 
-    base->ID3DXBaseEffect_iface.lpVtbl = &ID3DXBaseEffect_Vtbl;
-    base->ref = 1;
-    base->effect = effect;
+    return InterlockedIncrement(&This->ref);
+}
 
-    read_dword(&ptr, &tag);
-    TRACE("Tag: %x\n", tag);
+static ULONG WINAPI ID3DXEffectCompilerImpl_Release(ID3DXEffectCompiler *iface)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ULONG ref = InterlockedDecrement(&This->ref);
 
-    if (tag != d3dx9_effect_version(9, 1))
-    {
-        /* todo: compile hlsl ascii code */
-        FIXME("HLSL ascii effects not supported, yet\n");
+    TRACE("iface %p: Release from %u\n", iface, ref + 1);
 
-        /* Show the start of the shader for debugging info. */
-        TRACE("effect:\n%s\n", debugstr_an(data, data_size > 40 ? 40 : data_size));
-    }
-    else
+    if (!ref)
     {
-        read_dword(&ptr, &offset);
-        TRACE("Offset: %x\n", offset);
-
-        hr = d3dx9_parse_effect(base, ptr, data_size, offset);
-        if (hr != S_OK)
-        {
-            FIXME("Failed to parse effect.\n");
-            return hr;
-        }
+        free_effect_compiler(This);
+        HeapFree(GetProcessHeap(), 0, This);
     }
 
-    return S_OK;
+    return ref;
 }
 
-static HRESULT d3dx9_effect_init(struct ID3DXEffectImpl *effect, LPDIRECT3DDEVICE9 device,
-        const char *data, SIZE_T data_size, LPD3DXEFFECTPOOL pool)
+/*** ID3DXBaseEffect methods ***/
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetDesc(ID3DXEffectCompiler *iface, D3DXEFFECT_DESC *desc)
 {
-    HRESULT hr;
-    struct ID3DXBaseEffectImpl *object = NULL;
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
 
-    TRACE("effect %p, device %p, data %p, data_size %lu, pool %p\n", effect, device, data, data_size, pool);
+    TRACE("Forward iface %p, base %p\n", This, base);
 
-    effect->ID3DXEffect_iface.lpVtbl = &ID3DXEffect_Vtbl;
-    effect->ref = 1;
+    return ID3DXBaseEffectImpl_GetDesc(base, desc);
+}
 
-    if (pool) pool->lpVtbl->AddRef(pool);
-    effect->pool = pool;
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetParameterDesc(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXPARAMETER_DESC *desc)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
 
-    IDirect3DDevice9_AddRef(device);
-    effect->device = device;
+    TRACE("Forward iface %p, base %p\n", This, base);
 
-    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
-    if (!object)
-    {
-        ERR("Out of memory\n");
-        hr = E_OUTOFMEMORY;
-        goto err_out;
-    }
+    return ID3DXBaseEffectImpl_GetParameterDesc(base, parameter, desc);
+}
 
-    hr = d3dx9_base_effect_init(object, data, data_size, effect);
-    if (hr != S_OK)
-    {
-        FIXME("Failed to parse effect.\n");
-        goto err_out;
-    }
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTechniqueDesc(ID3DXEffectCompiler *iface, D3DXHANDLE technique, D3DXTECHNIQUE_DESC *desc)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
 
-    effect->base_effect = &object->ID3DXBaseEffect_iface;
+    TRACE("Forward iface %p, base %p\n", This, base);
 
-    return S_OK;
+    return ID3DXBaseEffectImpl_GetTechniqueDesc(base, technique, desc);
+}
 
-err_out:
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPassDesc(ID3DXEffectCompiler *iface, D3DXHANDLE pass, D3DXPASS_DESC *desc)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
 
-    HeapFree(GetProcessHeap(), 0, object);
-    free_effect(effect);
+    TRACE("Forward iface %p, base %p\n", This, base);
 
-    return hr;
+    return ID3DXBaseEffectImpl_GetPassDesc(base, pass, desc);
 }
 
-HRESULT WINAPI D3DXCreateEffectEx(LPDIRECT3DDEVICE9 device,
-                                  LPCVOID srcdata,
-                                  UINT srcdatalen,
-                                  CONST D3DXMACRO* defines,
-                                  LPD3DXINCLUDE include,
-                                  LPCSTR skip_constants,
-                                  DWORD flags,
-                                  LPD3DXEFFECTPOOL pool,
-                                  LPD3DXEFFECT* effect,
-                                  LPD3DXBUFFER* compilation_errors)
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFunctionDesc(ID3DXEffectCompiler *iface, D3DXHANDLE shader, D3DXFUNCTION_DESC *desc)
 {
-    struct ID3DXEffectImpl *object;
-    HRESULT hr;
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
 
-    FIXME("(%p, %p, %u, %p, %p, %p, %#x, %p, %p, %p): semi-stub\n", device, srcdata, srcdatalen, defines, include,
-        skip_constants, flags, pool, effect, compilation_errors);
+    TRACE("Forward iface %p, base %p\n", This, base);
 
-    if (!device || !srcdata)
-        return D3DERR_INVALIDCALL;
+    return ID3DXBaseEffectImpl_GetFunctionDesc(base, shader, desc);
+}
 
-    if (!srcdatalen)
-        return E_FAIL;
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameter(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, UINT index)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
 
-    /* Native dll allows effect to be null so just return D3D_OK after doing basic checks */
-    if (!effect)
-        return D3D_OK;
+    TRACE("Forward iface %p, base %p\n", This, base);
 
-    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
-    if (!object)
-    {
-        ERR("Out of memory\n");
-        return E_OUTOFMEMORY;
-    }
+    return ID3DXBaseEffectImpl_GetParameter(base, parameter, index);
+}
 
-    hr = d3dx9_effect_init(object, device, srcdata, srcdatalen, pool);
-    if (FAILED(hr))
-    {
-        WARN("Failed to initialize shader reflection\n");
-        HeapFree(GetProcessHeap(), 0, object);
-        return hr;
-    }
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterByName(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, LPCSTR name)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
 
-    *effect = &object->ID3DXEffect_iface;
+    TRACE("Forward iface %p, base %p\n", This, base);
 
-    TRACE("Created ID3DXEffect %p\n", object);
+    return ID3DXBaseEffectImpl_GetParameterByName(base, parameter, name);
+}
 
-    return D3D_OK;
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterBySemantic(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, LPCSTR semantic)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetParameterBySemantic(base, parameter, semantic);
 }
 
-HRESULT WINAPI D3DXCreateEffect(LPDIRECT3DDEVICE9 device,
-                                LPCVOID srcdata,
-                                UINT srcdatalen,
-                                CONST D3DXMACRO* defines,
-                                LPD3DXINCLUDE include,
-                                DWORD flags,
-                                LPD3DXEFFECTPOOL pool,
-                                LPD3DXEFFECT* effect,
-                                LPD3DXBUFFER* compilation_errors)
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterElement(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, UINT index)
 {
-    TRACE("(%p, %p, %u, %p, %p, %#x, %p, %p, %p): Forwarded to D3DXCreateEffectEx\n", device, srcdata, srcdatalen, defines,
-        include, flags, pool, effect, compilation_errors);
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
 
-    return D3DXCreateEffectEx(device, srcdata, srcdatalen, defines, include, NULL, flags, pool, effect, compilation_errors);
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetParameterElement(base, parameter, index);
 }
 
-HRESULT WINAPI D3DXCreateEffectCompiler(LPCSTR srcdata,
-                                        UINT srcdatalen,
-                                        CONST D3DXMACRO* defines,
-                                        LPD3DXINCLUDE include,
-                                        DWORD flags,
-                                        LPD3DXEFFECTCOMPILER* compiler,
-                                        LPD3DXBUFFER* parse_errors)
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechnique(ID3DXEffectCompiler *iface, UINT index)
 {
-    FIXME("(%p, %u, %p, %p, %#x, %p, %p): stub\n", srcdata, srcdatalen, defines, include, flags, compiler, parse_errors);
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
 
-    return E_NOTIMPL;
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetTechnique(base, index);
+}
+
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechniqueByName(ID3DXEffectCompiler *iface, LPCSTR name)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetTechniqueByName(base, name);
+}
+
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPass(ID3DXEffectCompiler *iface, D3DXHANDLE technique, UINT index)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetPass(base, technique, index);
+}
+
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPassByName(ID3DXEffectCompiler *iface, D3DXHANDLE technique, LPCSTR name)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetPassByName(base, technique, name);
+}
+
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunction(ID3DXEffectCompiler *iface, UINT index)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetFunction(base, index);
+}
+
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunctionByName(ID3DXEffectCompiler *iface, LPCSTR name)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetFunctionByName(base, name);
+}
+
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotation(ID3DXEffectCompiler *iface, D3DXHANDLE object, UINT index)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetAnnotation(base, object, index);
+}
+
+static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotationByName(ID3DXEffectCompiler *iface, D3DXHANDLE object, LPCSTR name)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetAnnotationByName(base, object, name);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetValue(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, LPCVOID data, UINT bytes)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetValue(base, parameter, data, bytes);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetValue(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, LPVOID data, UINT bytes)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetValue(base, parameter, data, bytes);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL b)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetBool(base, parameter, b);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *b)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetBool(base, parameter, b);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBoolArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST BOOL *b, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetBoolArray(base, parameter, b, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBoolArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *b, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetBoolArray(base, parameter, b, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT n)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetInt(base, parameter, n);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT *n)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetInt(base, parameter, n);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetIntArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST INT *n, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetIntArray(base, parameter, n, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetIntArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT *n, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetIntArray(base, parameter, n, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, FLOAT f)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetFloat(base, parameter, f);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, FLOAT *f)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetFloat(base, parameter, f);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloatArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST FLOAT *f, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetFloatArray(base, parameter, f, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloatArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, FLOAT *f, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetFloatArray(base, parameter, f, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVector(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST D3DXVECTOR4 *vector)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetVector(base, parameter, vector);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVector(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetVector(base, parameter, vector);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVectorArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST D3DXVECTOR4 *vector, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetVectorArray(base, parameter, vector, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVectorArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetVectorArray(base, parameter, vector, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrix(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST D3DXMATRIX *matrix)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetMatrix(base, parameter, matrix);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrix(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetMatrix(base, parameter, matrix);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST D3DXMATRIX *matrix, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetMatrixArray(base, parameter, matrix, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetMatrixArray(base, parameter, matrix, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixPointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST D3DXMATRIX **matrix, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetMatrixPointerArray(base, parameter, matrix, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixPointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetMatrixPointerArray(base, parameter, matrix, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTranspose(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST D3DXMATRIX *matrix)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetMatrixTranspose(base, parameter, matrix);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTranspose(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetMatrixTranspose(base, parameter, matrix);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposeArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST D3DXMATRIX *matrix, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetMatrixTransposeArray(base, parameter, matrix, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposeArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetMatrixTransposeArray(base, parameter, matrix, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, CONST D3DXMATRIX **matrix, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetMatrixTransposePointerArray(base, parameter, matrix, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetMatrixTransposePointerArray(base, parameter, matrix, count);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetString(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, LPCSTR string)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetString(base, parameter, string);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetString(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, LPCSTR *string)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetString(base, parameter, string);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetTexture(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, LPDIRECT3DBASETEXTURE9 texture)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetTexture(base, parameter, texture);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTexture(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, LPDIRECT3DBASETEXTURE9 *texture)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetTexture(base, parameter, texture);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPixelShader(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, LPDIRECT3DPIXELSHADER9 *pshader)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetPixelShader(base, parameter, pshader);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVertexShader(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, LPDIRECT3DVERTEXSHADER9 *vshader)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_GetVertexShader(base, parameter, vshader);
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetArrayRange(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, UINT start, UINT end)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+    ID3DXBaseEffect *base = This->base_effect;
+
+    TRACE("Forward iface %p, base %p\n", This, base);
+
+    return ID3DXBaseEffectImpl_SetArrayRange(base, parameter, start, end);
+}
+
+/*** ID3DXEffectCompiler methods ***/
+static HRESULT WINAPI ID3DXEffectCompilerImpl_SetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL literal)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+
+    FIXME("iface %p, parameter %p, literal %u\n", This, parameter, literal);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_GetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *literal)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+
+    FIXME("iface %p, parameter %p, literal %p\n", This, parameter, literal);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileEffect(ID3DXEffectCompiler *iface, DWORD flags,
+        LPD3DXBUFFER *effect, LPD3DXBUFFER *error_msgs)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+
+    FIXME("iface %p, flags %#x, effect %p, error_msgs %p stub\n", This, flags, effect, error_msgs);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileShader(ID3DXEffectCompiler *iface, D3DXHANDLE function,
+        LPCSTR target, DWORD flags, LPD3DXBUFFER *shader, LPD3DXBUFFER *error_msgs, LPD3DXCONSTANTTABLE *constant_table)
+{
+    struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
+
+    FIXME("iface %p, function %p, target %p, flags %#x, shader %p, error_msgs %p, constant_table %p stub\n",
+            This, function, target, flags, shader, error_msgs, constant_table);
+
+    return E_NOTIMPL;
+}
+
+static const struct ID3DXEffectCompilerVtbl ID3DXEffectCompiler_Vtbl =
+{
+    /*** IUnknown methods ***/
+    ID3DXEffectCompilerImpl_QueryInterface,
+    ID3DXEffectCompilerImpl_AddRef,
+    ID3DXEffectCompilerImpl_Release,
+    /*** ID3DXBaseEffect methods ***/
+    ID3DXEffectCompilerImpl_GetDesc,
+    ID3DXEffectCompilerImpl_GetParameterDesc,
+    ID3DXEffectCompilerImpl_GetTechniqueDesc,
+    ID3DXEffectCompilerImpl_GetPassDesc,
+    ID3DXEffectCompilerImpl_GetFunctionDesc,
+    ID3DXEffectCompilerImpl_GetParameter,
+    ID3DXEffectCompilerImpl_GetParameterByName,
+    ID3DXEffectCompilerImpl_GetParameterBySemantic,
+    ID3DXEffectCompilerImpl_GetParameterElement,
+    ID3DXEffectCompilerImpl_GetTechnique,
+    ID3DXEffectCompilerImpl_GetTechniqueByName,
+    ID3DXEffectCompilerImpl_GetPass,
+    ID3DXEffectCompilerImpl_GetPassByName,
+    ID3DXEffectCompilerImpl_GetFunction,
+    ID3DXEffectCompilerImpl_GetFunctionByName,
+    ID3DXEffectCompilerImpl_GetAnnotation,
+    ID3DXEffectCompilerImpl_GetAnnotationByName,
+    ID3DXEffectCompilerImpl_SetValue,
+    ID3DXEffectCompilerImpl_GetValue,
+    ID3DXEffectCompilerImpl_SetBool,
+    ID3DXEffectCompilerImpl_GetBool,
+    ID3DXEffectCompilerImpl_SetBoolArray,
+    ID3DXEffectCompilerImpl_GetBoolArray,
+    ID3DXEffectCompilerImpl_SetInt,
+    ID3DXEffectCompilerImpl_GetInt,
+    ID3DXEffectCompilerImpl_SetIntArray,
+    ID3DXEffectCompilerImpl_GetIntArray,
+    ID3DXEffectCompilerImpl_SetFloat,
+    ID3DXEffectCompilerImpl_GetFloat,
+    ID3DXEffectCompilerImpl_SetFloatArray,
+    ID3DXEffectCompilerImpl_GetFloatArray,
+    ID3DXEffectCompilerImpl_SetVector,
+    ID3DXEffectCompilerImpl_GetVector,
+    ID3DXEffectCompilerImpl_SetVectorArray,
+    ID3DXEffectCompilerImpl_GetVectorArray,
+    ID3DXEffectCompilerImpl_SetMatrix,
+    ID3DXEffectCompilerImpl_GetMatrix,
+    ID3DXEffectCompilerImpl_SetMatrixArray,
+    ID3DXEffectCompilerImpl_GetMatrixArray,
+    ID3DXEffectCompilerImpl_SetMatrixPointerArray,
+    ID3DXEffectCompilerImpl_GetMatrixPointerArray,
+    ID3DXEffectCompilerImpl_SetMatrixTranspose,
+    ID3DXEffectCompilerImpl_GetMatrixTranspose,
+    ID3DXEffectCompilerImpl_SetMatrixTransposeArray,
+    ID3DXEffectCompilerImpl_GetMatrixTransposeArray,
+    ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray,
+    ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray,
+    ID3DXEffectCompilerImpl_SetString,
+    ID3DXEffectCompilerImpl_GetString,
+    ID3DXEffectCompilerImpl_SetTexture,
+    ID3DXEffectCompilerImpl_GetTexture,
+    ID3DXEffectCompilerImpl_GetPixelShader,
+    ID3DXEffectCompilerImpl_GetVertexShader,
+    ID3DXEffectCompilerImpl_SetArrayRange,
+    /*** ID3DXEffectCompiler methods ***/
+    ID3DXEffectCompilerImpl_SetLiteral,
+    ID3DXEffectCompilerImpl_GetLiteral,
+    ID3DXEffectCompilerImpl_CompileEffect,
+    ID3DXEffectCompilerImpl_CompileShader,
+};
+
+static HRESULT d3dx9_parse_effect(struct ID3DXBaseEffectImpl *base, const char *data, UINT data_size, DWORD start)
+{
+    const char *ptr = data + start;
+
+    read_dword(&ptr, &base->parameter_count);
+    TRACE("Parameter count: %u\n", base->parameter_count);
+
+    read_dword(&ptr, &base->technique_count);
+    TRACE("Technique count: %u\n", base->technique_count);
+
+    skip_dword_unknown(&ptr, 2);
+
+    /* todo: Parse parameter */
+
+    /* todo: Parse techniques */
+
+    return S_OK;
+}
+
+static HRESULT d3dx9_base_effect_init(struct ID3DXBaseEffectImpl *base,
+        const char *data, SIZE_T data_size, struct ID3DXEffectImpl *effect)
+{
+    DWORD tag, offset;
+    const char *ptr = data;
+    HRESULT hr;
+
+    TRACE("base %p, data %p, data_size %lu, effect %p\n", base, data, data_size, effect);
+
+    base->ID3DXBaseEffect_iface.lpVtbl = &ID3DXBaseEffect_Vtbl;
+    base->ref = 1;
+    base->effect = effect;
+
+    read_dword(&ptr, &tag);
+    TRACE("Tag: %x\n", tag);
+
+    if (tag != d3dx9_effect_version(9, 1))
+    {
+        /* todo: compile hlsl ascii code */
+        FIXME("HLSL ascii effects not supported, yet\n");
+
+        /* Show the start of the shader for debugging info. */
+        TRACE("effect:\n%s\n", debugstr_an(data, data_size > 40 ? 40 : data_size));
+    }
+    else
+    {
+        read_dword(&ptr, &offset);
+        TRACE("Offset: %x\n", offset);
+
+        hr = d3dx9_parse_effect(base, ptr, data_size, offset);
+        if (hr != S_OK)
+        {
+            FIXME("Failed to parse effect.\n");
+            return hr;
+        }
+    }
+
+    return S_OK;
+}
+
+static HRESULT d3dx9_effect_init(struct ID3DXEffectImpl *effect, LPDIRECT3DDEVICE9 device,
+        const char *data, SIZE_T data_size, LPD3DXEFFECTPOOL pool)
+{
+    HRESULT hr;
+    struct ID3DXBaseEffectImpl *object = NULL;
+
+    TRACE("effect %p, device %p, data %p, data_size %lu, pool %p\n", effect, device, data, data_size, pool);
+
+    effect->ID3DXEffect_iface.lpVtbl = &ID3DXEffect_Vtbl;
+    effect->ref = 1;
+
+    if (pool) pool->lpVtbl->AddRef(pool);
+    effect->pool = pool;
+
+    IDirect3DDevice9_AddRef(device);
+    effect->device = device;
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        hr = E_OUTOFMEMORY;
+        goto err_out;
+    }
+
+    hr = d3dx9_base_effect_init(object, data, data_size, effect);
+    if (hr != S_OK)
+    {
+        FIXME("Failed to parse effect.\n");
+        goto err_out;
+    }
+
+    effect->base_effect = &object->ID3DXBaseEffect_iface;
+
+    return S_OK;
+
+err_out:
+
+    HeapFree(GetProcessHeap(), 0, object);
+    free_effect(effect);
+
+    return hr;
+}
+
+HRESULT WINAPI D3DXCreateEffectEx(LPDIRECT3DDEVICE9 device,
+                                  LPCVOID srcdata,
+                                  UINT srcdatalen,
+                                  CONST D3DXMACRO* defines,
+                                  LPD3DXINCLUDE include,
+                                  LPCSTR skip_constants,
+                                  DWORD flags,
+                                  LPD3DXEFFECTPOOL pool,
+                                  LPD3DXEFFECT* effect,
+                                  LPD3DXBUFFER* compilation_errors)
+{
+    struct ID3DXEffectImpl *object;
+    HRESULT hr;
+
+    FIXME("(%p, %p, %u, %p, %p, %p, %#x, %p, %p, %p): semi-stub\n", device, srcdata, srcdatalen, defines, include,
+        skip_constants, flags, pool, effect, compilation_errors);
+
+    if (!device || !srcdata)
+        return D3DERR_INVALIDCALL;
+
+    if (!srcdatalen)
+        return E_FAIL;
+
+    /* Native dll allows effect to be null so just return D3D_OK after doing basic checks */
+    if (!effect)
+        return D3D_OK;
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        return E_OUTOFMEMORY;
+    }
+
+    hr = d3dx9_effect_init(object, device, srcdata, srcdatalen, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize shader reflection\n");
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    *effect = &object->ID3DXEffect_iface;
+
+    TRACE("Created ID3DXEffect %p\n", object);
+
+    return D3D_OK;
+}
+
+HRESULT WINAPI D3DXCreateEffect(LPDIRECT3DDEVICE9 device,
+                                LPCVOID srcdata,
+                                UINT srcdatalen,
+                                CONST D3DXMACRO* defines,
+                                LPD3DXINCLUDE include,
+                                DWORD flags,
+                                LPD3DXEFFECTPOOL pool,
+                                LPD3DXEFFECT* effect,
+                                LPD3DXBUFFER* compilation_errors)
+{
+    TRACE("(%p, %p, %u, %p, %p, %#x, %p, %p, %p): Forwarded to D3DXCreateEffectEx\n", device, srcdata, srcdatalen, defines,
+        include, flags, pool, effect, compilation_errors);
+
+    return D3DXCreateEffectEx(device, srcdata, srcdatalen, defines, include, NULL, flags, pool, effect, compilation_errors);
+}
+
+static HRESULT d3dx9_effect_compiler_init(struct ID3DXEffectCompilerImpl *compiler, const char *data, SIZE_T data_size)
+{
+    HRESULT hr;
+    struct ID3DXBaseEffectImpl *object = NULL;
+
+    TRACE("effect %p, data %p, data_size %lu\n", compiler, data, data_size);
+
+    compiler->ID3DXEffectCompiler_iface.lpVtbl = &ID3DXEffectCompiler_Vtbl;
+    compiler->ref = 1;
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        hr = E_OUTOFMEMORY;
+        goto err_out;
+    }
+
+    hr = d3dx9_base_effect_init(object, data, data_size, NULL);
+    if (hr != S_OK)
+    {
+        FIXME("Failed to parse effect.\n");
+        goto err_out;
+    }
+
+    compiler->base_effect = &object->ID3DXBaseEffect_iface;
+
+    return S_OK;
+
+err_out:
+
+    HeapFree(GetProcessHeap(), 0, object);
+    free_effect_compiler(compiler);
+
+    return hr;
+}
+
+HRESULT WINAPI D3DXCreateEffectCompiler(LPCSTR srcdata,
+                                        UINT srcdatalen,
+                                        CONST D3DXMACRO *defines,
+                                        LPD3DXINCLUDE include,
+                                        DWORD flags,
+                                        LPD3DXEFFECTCOMPILER *compiler,
+                                        LPD3DXBUFFER *parse_errors)
+{
+    struct ID3DXEffectCompilerImpl *object;
+    HRESULT hr;
+
+    TRACE("srcdata %p, srcdatalen %u, defines %p, include %p, flags %#x, compiler %p, parse_errors %p\n",
+            srcdata, srcdatalen, defines, include, flags, compiler, parse_errors);
+
+    if (!srcdata || !compiler)
+    {
+        WARN("Invalid arguments supplied\n");
+        return D3DERR_INVALIDCALL;
+    }
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        ERR("Out of memory\n");
+        return E_OUTOFMEMORY;
+    }
+
+    hr = d3dx9_effect_compiler_init(object, srcdata, srcdatalen);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize effect compiler\n");
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    *compiler = &object->ID3DXEffectCompiler_iface;
+
+    TRACE("Created ID3DXEffectCompiler %p\n", object);
+
+    return D3D_OK;
 }
 
 static const struct ID3DXEffectPoolVtbl ID3DXEffectPool_Vtbl;