[PATCH] d3dcompiler: Implement D3DReadFileToBlob().

Jactry Zeng jzeng at codeweavers.com
Fri Apr 26 05:15:45 CDT 2019


Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
---
 dlls/d3dcompiler_43/blob.c       |  54 +++++++++++++++-
 dlls/d3dcompiler_43/tests/blob.c | 106 +++++++++++++++++++++++++++++++
 2 files changed, 158 insertions(+), 2 deletions(-)

diff --git a/dlls/d3dcompiler_43/blob.c b/dlls/d3dcompiler_43/blob.c
index f22dc7183d..6b1b20317f 100644
--- a/dlls/d3dcompiler_43/blob.c
+++ b/dlls/d3dcompiler_43/blob.c
@@ -466,9 +466,59 @@ HRESULT WINAPI D3DStripShader(const void *data, SIZE_T data_size, UINT flags, ID
 
 HRESULT WINAPI D3DReadFileToBlob(const WCHAR *filename, ID3DBlob **contents)
 {
-    FIXME("filename %s, contents %p\n", debugstr_w(filename), contents);
+    struct d3dcompiler_blob *object;
+    HANDLE file;
+    SIZE_T data_size;
+    DWORD read_size;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("filename %s, contents %p\n", debugstr_w(filename), contents);
+
+    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());
+
+    data_size = GetFileSize(file, NULL);
+    if (data_size == INVALID_FILE_SIZE)
+    {
+        CloseHandle(file);
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        CloseHandle(file);
+        return E_OUTOFMEMORY;
+    }
+
+    hr = d3dcompiler_blob_init(object, data_size);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize blob, hr %#x.\n", hr);
+        CloseHandle(file);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    if (!ReadFile(file, object->data, data_size, &read_size, NULL) ||
+        (read_size != data_size))
+    {
+        WARN("Failed to read file contents.\n");
+        CloseHandle(file);
+        HeapFree(GetProcessHeap(), 0, object->data);
+        HeapFree(GetProcessHeap(), 0, object);
+        return E_FAIL;
+    }
+    CloseHandle(file);
+    object->size = read_size;
+
+    *contents = &object->ID3DBlob_iface;
+
+    TRACE("Returning ID3DBlob %p.\n", *contents);
+
+    return S_OK;
 }
 
 HRESULT WINAPI D3DWriteBlobToFile(ID3DBlob* blob, const WCHAR *filename, BOOL overwrite)
diff --git a/dlls/d3dcompiler_43/tests/blob.c b/dlls/d3dcompiler_43/tests/blob.c
index 443ed2754c..6a9fa5de8b 100644
--- a/dlls/d3dcompiler_43/tests/blob.c
+++ b/dlls/d3dcompiler_43/tests/blob.c
@@ -35,6 +35,7 @@
 
 static HRESULT (WINAPI *pD3DCreateBlob)(SIZE_T, ID3DBlob **);
 static HRESULT (WINAPI *pD3DGetBlobPart)(const void *, SIZE_T, D3D_BLOB_PART, UINT, ID3DBlob **);
+static HRESULT (WINAPI *pD3DReadFileToBlob)(const WCHAR *, ID3DBlob **);
 static HRESULT (WINAPI *pD3DStripShader)(const void *, SIZE_T, UINT, ID3DBlob **);
 
 #define MAKE_TAG(ch0, ch1, ch2, ch3) \
@@ -752,6 +753,103 @@ static BOOL load_d3dcompiler(void)
     return TRUE;
 }
 
+static BOOL load_d3dcompiler_47(void)
+{
+    HMODULE module;
+
+    if (!(module = LoadLibraryA("d3dcompiler_47.dll"))) return FALSE;
+
+    pD3DReadFileToBlob = (void*)GetProcAddress(module, "D3DReadFileToBlob");
+    return TRUE;
+}
+
+static void create_cso_file(LPCWSTR pathW, void *data, DWORD data_size)
+{
+    HANDLE file;
+    DWORD written;
+
+    file = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0,
+                       NULL, CREATE_ALWAYS, 0, 0);
+    ok(file != INVALID_HANDLE_VALUE, "File creation failed, at %s, error 0x%08x.\n",
+       wine_dbgstr_w(pathW), GetLastError());
+
+    if (data)
+    {
+        WriteFile(file, data, data_size, &written, NULL);
+        ok(written == data_size, "Couldn't write .cso file.\n" );
+    }
+    CloseHandle(file);
+}
+
+/* .cso file compiled by fxc.exe.
+   HLSL source:
+   ```
+   struct PSInput
+   {
+       float4 value : SV_POSITION;
+   };
+
+   PSInput main(float4 position : POSITION)
+   {
+       PSInput result;
+       result.value = position;
+       return result;
+   }
+   ```
+ */
+static byte test_cso_data[] =
+{
+    0x00,0x02,0xfe,0xff,0xfe,0xff,0x14,0x00,0x43,0x54,0x41,0x42,0x1c,0x00,0x00,0x00,0x23,0x00,
+    0x00,0x00,0x00,0x02,0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
+    0x1c,0x00,0x00,0x00,0x76,0x73,0x5f,0x32,0x5f,0x30,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,
+    0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,
+    0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x31,0x00,0xab,0x1f,0x00,
+    0x00,0x02,0x00,0x00,0x00,0x80,0x00,0x00,0x0f,0x90,0x01,0x00,0x00,0x02,0x00,0x00,0x0f,0xc0,
+    0x00,0x00,0xe4,0x90,0xff,0xff,0x00,0x00
+};
+
+static void test_D3DReadFileToBlob(void)
+{
+    ID3DBlob *blob = NULL;
+    HRESULT hr;
+    static const WCHAR filenameW[] = {'t','e','s','t','.','c','s','o',0};
+    byte *data_enter;
+    SIZE_T data_size;
+
+    hr = pD3DReadFileToBlob(filenameW, NULL);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+       "D3DReadFileToBlob returned: 0x%08x.\n", hr);
+
+    hr = pD3DReadFileToBlob(filenameW, &blob);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+       "D3DReadFileToBlob returned: 0x%08x.\n", hr);
+
+    /* Crash on Windows
+    create_cso_file(filenameW, test_cso_data, sizeof(test_cso_data));
+    pD3DReadFileToBlob(filenameW, NULL);
+    DeleteFileW(filenameW);
+    */
+
+    create_cso_file(filenameW, NULL, 0);
+    hr = pD3DReadFileToBlob(filenameW, &blob);
+    ok(hr == S_OK, "D3DReadFileToBlob failed: 0x%08x.\n", hr);
+    data_size = ID3D10Blob_GetBufferSize(blob);
+    ok(data_size == 0, "got wrong data size: %lu, expected %u.\n", data_size, 0);
+    DeleteFileW(filenameW);
+    ID3D10Blob_Release(blob);
+
+    create_cso_file(filenameW, test_cso_data, sizeof(test_cso_data));
+    hr = pD3DReadFileToBlob(filenameW, &blob);
+    ok(hr == S_OK, "D3DReadFileToBlob failed: 0x%08x.\n", hr);
+    data_size = ID3D10Blob_GetBufferSize(blob);
+    ok(data_size == sizeof(test_cso_data), "got wrong data size: %lu, expected %u.\n",
+       data_size, sizeof(test_cso_data));
+    data_enter = ID3D10Blob_GetBufferPointer(blob);
+    ok(!memcmp(data_enter, test_cso_data, sizeof(test_cso_data)), "got wrong data.\n");
+    DeleteFileW(filenameW);
+    ID3D10Blob_Release(blob);
+}
+
 START_TEST(blob)
 {
     if (!load_d3dcompiler())
@@ -763,4 +861,12 @@ START_TEST(blob)
     test_create_blob();
     test_get_blob_part();
     test_get_blob_part2();
+
+    if (!load_d3dcompiler_47())
+    {
+        win_skip("Could not load d3dcompiler_47.dll\n");
+        return;
+    }
+
+    test_D3DReadFileToBlob();
 }
-- 
2.20.1




More information about the wine-devel mailing list