Signed-off-by: Jactry Zeng jzeng@codeweavers.com --- dlls/d3dx11_43/async.c | 31 +++++- dlls/d3dx11_43/tests/d3dx11.c | 203 ++++++++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+), 6 deletions(-)
diff --git a/dlls/d3dx11_43/async.c b/dlls/d3dx11_43/async.c index cde87cec60..f9d9d0cf9e 100644 --- a/dlls/d3dx11_43/async.c +++ b/dlls/d3dx11_43/async.c @@ -236,24 +236,43 @@ HRESULT WINAPI D3DX11CompileFromFileA(const char *filename, const D3D10_SHADER_M ID3D10Include *include, const char *entry_point, const char *target, UINT sflags, UINT eflags, ID3DX11ThreadPump *pump, ID3D10Blob **shader, ID3D10Blob **error_messages, HRESULT *hresult) { - FIXME("filename %s, defines %p, include %p, entry_point %s, target %s, sflags %#x, " - "eflags %#x, pump %p, shader %p, error_messages %p, hresult %p stub.\n", + WCHAR filename_w[MAX_PATH]; + DWORD len; + + TRACE("filename %s, defines %p, include %p, entry_point %s, target %s, sflags %#x, " + "eflags %#x, pump %p, shader %p, error_messages %p, hresult %p.\n", debugstr_a(filename), defines, include, debugstr_a(entry_point), debugstr_a(target), sflags, eflags, pump, shader, error_messages, hresult);
- return E_NOTIMPL; + len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0); + MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len); + + return D3DX11CompileFromFileW(filename_w, defines, include, entry_point, target, + sflags, eflags, pump, shader, error_messages, hresult); }
HRESULT WINAPI D3DX11CompileFromFileW(const WCHAR *filename, const D3D10_SHADER_MACRO *defines, ID3D10Include *include, const char *entry_point, const char *target, UINT sflags, UINT eflags, ID3DX11ThreadPump *pump, ID3D10Blob **shader, ID3D10Blob **error_messages, HRESULT *hresult) { - FIXME("filename %s, defines %p, include %p, entry_point %s, target %s, sflags %#x, " - "eflags %#x, pump %p, shader %p, error_messages %p, hresult %p stub.\n", + HRESULT hr; + + TRACE("filename %s, defines %p, include %p, entry_point %s, target %s, sflags %#x, " + "eflags %#x, pump %p, shader %p, error_messages %p, hresult %p.\n", debugstr_w(filename), defines, include, debugstr_a(entry_point), debugstr_a(target), sflags, eflags, pump, shader, error_messages, hresult);
- return E_NOTIMPL; + if (pump) + FIXME("Unimplemented ID3DX11ThreadPump handling.\n"); + + if (!include) + include = D3D_COMPILE_STANDARD_FILE_INCLUDE; + + hr = D3DCompileFromFile(filename, defines, include, entry_point, target, sflags, eflags, shader, error_messages); + if (hresult) + *hresult = hr; + + return hr; }
HRESULT WINAPI D3DX11CreateAsyncMemoryLoader(const void *data, SIZE_T data_size, ID3DX11DataLoader **loader) diff --git a/dlls/d3dx11_43/tests/d3dx11.c b/dlls/d3dx11_43/tests/d3dx11.c index f7ced893b0..90d3417299 100644 --- a/dlls/d3dx11_43/tests/d3dx11.c +++ b/dlls/d3dx11_43/tests/d3dx11.c @@ -22,6 +22,63 @@ #include "d3dx11.h" #include "wine/test.h"
+static WCHAR temp_dir[MAX_PATH]; + +static BOOL create_file(const WCHAR *filename, const char *data, const unsigned int size, WCHAR *out_path) +{ + WCHAR path[MAX_PATH]; + DWORD written; + HANDLE file; + + if (!temp_dir[0]) + GetTempPathW(ARRAY_SIZE(temp_dir), temp_dir); + lstrcpyW(path, temp_dir); + lstrcatW(path, filename); + + file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (file == INVALID_HANDLE_VALUE) + return FALSE; + + if (WriteFile(file, data, size, &written, NULL)) + { + CloseHandle(file); + + if (out_path) + lstrcpyW(out_path, path); + return TRUE; + } + + CloseHandle(file); + return FALSE; +} + +static void delete_file(const WCHAR *filename) +{ + WCHAR path[MAX_PATH]; + + lstrcpyW(path, temp_dir); + lstrcatW(path, filename); + DeleteFileW(path); +} + +static BOOL create_directory(const WCHAR *dir) +{ + WCHAR path[MAX_PATH]; + + lstrcpyW(path, temp_dir); + lstrcatW(path, dir); + return CreateDirectoryW(path, NULL); +} + +static void delete_directory(const WCHAR *dir) +{ + WCHAR path[MAX_PATH]; + + lstrcpyW(path, temp_dir); + lstrcatW(path, dir); + RemoveDirectoryW(path); +} + static void test_D3DX11CreateAsyncMemoryLoader(void) { ID3DX11DataLoader *loader; @@ -205,9 +262,155 @@ static void test_D3DX11CreateAsyncResourceLoader(void) ok(hr == D3DX11_ERR_INVALID_DATA, "Got unexpected hr %#x.\n", hr); }
+static HRESULT WINAPI test_d3dinclude_open(ID3DInclude *iface, D3D_INCLUDE_TYPE include_type, + const char *filename, const void *parent_data, const void **data, UINT *bytes) +{ + static const char include1[] = + "#define LIGHT float4(0.0f, 0.2f, 0.5f, 1.0f)\n"; + static const char include2[] = + "#include "include1.h"\n" + "float4 light_color = LIGHT;\n"; + char *buffer; + + trace("filename %s.\n", filename); + trace("parent_data %p: %s.\n", parent_data, parent_data ? (char *)parent_data : "(null)"); + + if (!strcmp(filename, "include1.h")) + { + buffer = HeapAlloc(GetProcessHeap(), 0, strlen(include1)); + CopyMemory(buffer, include1, strlen(include1)); + *bytes = strlen(include1); + ok(include_type == D3D_INCLUDE_LOCAL, "Wrong include type %d.\n", include_type); + ok(parent_data != NULL && !strncmp(include2, parent_data, strlen(include2)), + "Wrong parent_data value.\n"); + } + else if (!strcmp(filename, "include\include2.h")) + { + buffer = HeapAlloc(GetProcessHeap(), 0, strlen(include2)); + CopyMemory(buffer, include2, strlen(include2)); + *bytes = strlen(include2); + ok(!parent_data, "Wrong parent_data value.\n"); + ok(include_type == D3D_INCLUDE_LOCAL, "Wrong include type %d.\n", include_type); + } + else + { + ok(0, "Unexpected #include for file %s.\n", filename); + return E_INVALIDARG; + } + + *data = buffer; + return S_OK; +} + +static HRESULT WINAPI test_d3dinclude_close(ID3DInclude *iface, const void *data) +{ + HeapFree(GetProcessHeap(), 0, (void *)data); + return S_OK; +} + +static const struct ID3DIncludeVtbl test_d3dinclude_vtbl = +{ + test_d3dinclude_open, + test_d3dinclude_close +}; + +struct test_d3dinclude +{ + ID3DInclude ID3DInclude_iface; +}; + +static void test_D3DX11CompileFromFile(void) +{ + WCHAR filename[MAX_PATH], directory[MAX_PATH]; + ID3D10Blob *blob = NULL, *errors = NULL; + struct test_d3dinclude include; + CHAR filename_a[MAX_PATH]; + HRESULT hr, result; + DWORD len; + static const char ps_code[] = + "#include "include\include2.h"\n" + "\n" + "float4 main() : COLOR\n" + "{\n" + " return light_color;\n" + "}"; + static const char include1[] = + "#define LIGHT float4(0.0f, 0.2f, 0.5f, 1.0f)\n"; + static const char include1_wrong[] = + "#define LIGHT nope\n"; + static const char include2[] = + "#include "include1.h"\n" + "float4 light_color = LIGHT;\n"; + + include.ID3DInclude_iface.lpVtbl = &test_d3dinclude_vtbl; + + create_file(L"source.ps", ps_code, strlen(ps_code), filename); + create_directory(L"include"); + create_file(L"include\include1.h", include1_wrong, strlen(include1_wrong), NULL); + create_file(L"include1.h", include1, strlen(include1), NULL); + create_file(L"include\include2.h", include2, strlen(include2), NULL); + + hr = D3DX11CompileFromFileW(filename, NULL, &include.ID3DInclude_iface, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result); + todo_wine ok(hr == S_OK && hr == result, "Got hr %#x, result %#x.\n", hr, result); + todo_wine ok(!!blob, "Got unexpected blob.\n"); + ok(!errors, "Got unexpected errors.\n"); + if (blob) + { + ID3D10Blob_Release(blob); + blob = NULL; + } + + /* Windows always seems to resolve includes from the initial file location + * instead of using the immediate parent, as it would be the case for + * standard C preprocessor includes. */ + hr = D3DX11CompileFromFileW(filename, NULL, NULL, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result); + todo_wine ok(hr == S_OK && hr == result, "Got hr %#x, result %#x.\n", hr, result); + todo_wine ok(!!blob, "Got unexpected blob.\n"); + ok(!errors, "Got unexpected errors.\n"); + if (blob) + { + ID3D10Blob_Release(blob); + blob = NULL; + } + + len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL); + hr = D3DX11CompileFromFileA(filename_a, NULL, NULL, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result); + todo_wine ok(hr == S_OK && hr == result, "Got hr %#x, result %#x.\n", hr, result); + todo_wine ok(!!blob, "Got unexpected blob.\n"); + ok(!errors, "Got unexpected errors.\n"); + if (blob) + { + ID3D10Blob_Release(blob); + blob = NULL; + } + + GetCurrentDirectoryW(MAX_PATH, directory); + SetCurrentDirectoryW(temp_dir); + + hr = D3DX11CompileFromFileW(L"source.ps", NULL, NULL, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result); + todo_wine ok(hr == S_OK && hr == result, "Got hr %#x, result %#x.\n", hr, result); + todo_wine ok(!!blob, "Got unexpected blob.\n"); + ok(!errors, "Got unexpected errors.\n"); + if (blob) + { + ID3D10Blob_Release(blob); + blob = NULL; + } + + SetCurrentDirectoryW(directory); + + delete_file(L"source.ps"); + delete_file(L"include\include1.h"); + delete_file(L"include1.h"); + delete_file(L"include\include2.h"); + delete_directory(L"include"); +} + START_TEST(d3dx11) { test_D3DX11CreateAsyncMemoryLoader(); test_D3DX11CreateAsyncFileLoader(); test_D3DX11CreateAsyncResourceLoader(); + test_D3DX11CompileFromFile(); }