[PATCH] d3dcompiler: Implement D3DCompileFromFile().

Jactry Zeng jzeng at codeweavers.com
Mon Apr 6 04:47:23 CDT 2020


Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
---
 dlls/d3dcompiler_43/compiler.c        | 41 ++++++++++++-
 dlls/d3dcompiler_43/tests/hlsl_d3d9.c | 85 ++++++++++++++++++++++++++-
 2 files changed, 122 insertions(+), 4 deletions(-)

diff --git a/dlls/d3dcompiler_43/compiler.c b/dlls/d3dcompiler_43/compiler.c
index 9fc7c1d773..06e8fb2534 100644
--- a/dlls/d3dcompiler_43/compiler.c
+++ b/dlls/d3dcompiler_43/compiler.c
@@ -949,10 +949,47 @@ HRESULT WINAPI D3DDisassemble(const void *data, SIZE_T size, UINT flags, const c
 HRESULT WINAPI D3DCompileFromFile(const WCHAR *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *includes,
         const char *entrypoint, const char *target, UINT flags1, UINT flags2, ID3DBlob **code, ID3DBlob **errors)
 {
-    FIXME("filename %s, defines %p, includes %p, entrypoint %s, target %s, flags1 %x, flags2 %x, code %p, errors %p\n",
+    char *source = NULL;
+    SIZE_T source_size;
+    DWORD read_size;
+    HANDLE file;
+    HRESULT hr;
+
+    TRACE("filename %s, defines %p, includes %p, entrypoint %s, target %s, flags1 %x, flags2 %x, code %p, errors %p.\n",
             debugstr_w(filename), defines, includes, debugstr_a(entrypoint), debugstr_a(target), flags1, flags2, code, errors);
 
-    return E_NOTIMPL;
+    file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (file == INVALID_HANDLE_VALUE)
+        return HRESULT_FROM_WIN32(GetLastError());
+
+    source_size = GetFileSize(file, NULL);
+    if (source_size == INVALID_FILE_SIZE)
+    {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        goto end;
+    }
+
+    if (!(source = heap_alloc_zero(source_size)))
+    {
+        hr = E_OUTOFMEMORY;
+        goto end;
+    }
+
+    if (!ReadFile(file, source, source_size, &read_size, NULL) || (read_size != source_size))
+    {
+        WARN("Failed to read file contents.\n");
+        hr = E_FAIL;
+        goto end;
+    }
+
+    hr = D3DCompile(source, strlen(source), NULL, defines, includes, entrypoint, target, flags1, flags2, code, errors);
+
+end:
+    CloseHandle(file);
+    if (source)
+        heap_free(source);
+
+    return hr;
 }
 
 HRESULT WINAPI D3DLoadModule(const void *data, SIZE_T size, ID3D11Module **module)
diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
index b96ab16679..cd93aa497d 100644
--- a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
+++ b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
@@ -26,6 +26,8 @@
 static pD3DCompile ppD3DCompile;
 
 static HRESULT (WINAPI *pD3DXGetShaderConstantTable)(const DWORD *byte_code, ID3DXConstantTable **constant_table);
+static HRESULT (WINAPI *pD3DCompileFromFile)(const WCHAR *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *includes,
+        const char *entrypoint, const char *target, UINT flags1, UINT flags2, ID3DBlob **code, ID3DBlob **errors);
 
 struct vec2
 {
@@ -37,10 +39,40 @@ struct vec4
     float x, y, z, w;
 };
 
+static BOOL create_file(WCHAR *filename, const char *code, DWORD code_size)
+{
+    static WCHAR temp_dir[MAX_PATH];
+    DWORD written;
+    HANDLE file;
+
+    if (!temp_dir[0])
+        GetTempPathW(ARRAY_SIZE(temp_dir), temp_dir);
+    GetTempFileNameW(temp_dir, NULL, 0, filename);
+    file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+    if (file == INVALID_HANDLE_VALUE)
+        return FALSE;
+
+    if (code)
+    {
+        WriteFile(file, code, code_size, &written, NULL);
+        if (written != code_size)
+        {
+            CloseHandle(file);
+            DeleteFileW(filename);
+            return FALSE;
+        }
+    }
+    CloseHandle(file);
+    return TRUE;
+}
+
 #define compile_shader(a, b) compile_shader_(__LINE__, a, b)
 static ID3D10Blob *compile_shader_(unsigned int line, const char *source, const char *target)
 {
-    ID3D10Blob *blob = NULL, *errors = NULL;
+    ID3D10Blob *blob = NULL, *errors = NULL, *file_blob = NULL, *file_errors = NULL;
+    WCHAR filename[MAX_PATH] = {0};
+    DWORD *data, *file_data;
+    SIZE_T size, file_size;
     HRESULT hr;
 
     hr = ppD3DCompile(source, strlen(source), NULL, NULL, NULL, "main", target, 0, 0, &blob, &errors);
@@ -49,8 +81,38 @@ static ID3D10Blob *compile_shader_(unsigned int line, const char *source, const
     {
         if (winetest_debug > 1)
             trace_(__FILE__, line)("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
-        ID3D10Blob_Release(errors);
     }
+
+    if (SUCCEEDED(hr))
+    {
+    if (!pD3DCompileFromFile || !create_file(filename, source, strlen(source)))
+        skip("D3DCompileFromFile() isn't supported or file creation failed.\n");
+    else
+    {
+        hr = pD3DCompileFromFile(filename, NULL, NULL, "main", target, 0, 0, &file_blob, &file_errors);
+        ok_(__FILE__, line)(hr == D3D_OK, "Failed to compile shader from file, hr %#x.\n", hr);
+        size = ID3D10Blob_GetBufferSize(blob);
+        file_size = ID3D10Blob_GetBufferSize(blob);
+        ok_(__FILE__, line)(hr == D3D_OK, "Got unexpected buffer size: %lu vs %lu.\n", size, file_size);
+        data = ID3D10Blob_GetBufferPointer(blob);
+        file_data = ID3D10Blob_GetBufferPointer(file_blob);
+        ok_(__FILE__, line)(!memcmp(data, file_data, size), "Got unexpected data.\n");
+        ok_(__FILE__, line)(!!file_errors == !!errors, "Got unexpected errors.\n");
+        if (file_errors)
+        {
+            if (winetest_debug > 1)
+                trace_(__FILE__, line)("%s\n", (char *)ID3D10Blob_GetBufferPointer(file_errors));
+            ID3D10Blob_Release(file_errors);
+        }
+
+        ID3D10Blob_Release(file_blob);
+        DeleteFileW(filename);
+    }
+    }
+
+    if (errors)
+        ID3D10Blob_Release(errors);
+
     return blob;
 }
 
@@ -1003,6 +1065,7 @@ static BOOL load_d3dcompiler(void)
 
 #if D3D_COMPILER_VERSION == 47
     if (!(module = LoadLibraryA("d3dcompiler_47.dll"))) return FALSE;
+    pD3DCompileFromFile = (void*)GetProcAddress(module, "D3DCompileFromFile");
 #else
     if (!(module = LoadLibraryA("d3dcompiler_43.dll"))) return FALSE;
 #endif
@@ -1011,6 +1074,23 @@ static BOOL load_d3dcompiler(void)
     return TRUE;
 }
 
+static void test_compile(void)
+{
+    ID3D10Blob *blob = NULL, *errors = NULL;
+    HRESULT hr;
+
+    if (!pD3DCompileFromFile)
+    {
+        skip("D3DCompileFromFile() isn't supported.\n");
+        return;
+    }
+
+    hr = pD3DCompileFromFile(L"nonexistent", NULL, NULL, "main", "vs_2_0", 0, 0, &blob, &errors);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Got hr %#x.\n", hr);
+    ok(!blob, "Got unexpected blob.\n");
+    ok(!errors, "Got unexpected errors.\n");
+}
+
 START_TEST(hlsl_d3d9)
 {
     HMODULE mod;
@@ -1038,4 +1118,5 @@ START_TEST(hlsl_d3d9)
     test_array_dimensions();
     test_constant_table();
     test_fail();
+    test_compile();
 }
-- 
2.26.0



More information about the wine-devel mailing list