[3/3] d3dx9: D3DXPreprocessShader implementation with tests.
Matteo Bruni
matteo.mystral at gmail.com
Thu Sep 9 12:23:27 CDT 2010
-------------- next part --------------
From ea736401edeba45a501f58656561775212f89352 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Thu, 9 Sep 2010 18:41:39 +0200
Subject: d3dx9: D3DXPreprocessShader implementation with tests.
---
dlls/d3dx9_36/d3dx9_36.spec | 10 ++--
dlls/d3dx9_36/shader.c | 117 +++++++++++++++++++++++++++++++++++++-
dlls/d3dx9_36/tests/asm.c | 132 +++++++++++++++++++++++++++++++++++++++++++
include/d3dx9shader.h | 33 +++++++++++
4 files changed, 286 insertions(+), 6 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
index 9c84dbf..0901b48 100644
--- a/dlls/d3dx9_36/d3dx9_36.spec
+++ b/dlls/d3dx9_36/d3dx9_36.spec
@@ -236,11 +236,11 @@
@ stdcall D3DXPlaneNormalize(ptr ptr)
@ stdcall D3DXPlaneTransform(ptr ptr ptr)
@ stdcall D3DXPlaneTransformArray(ptr long ptr long ptr long)
-@ stub D3DXPreprocessShader
-@ stub D3DXPreprocessShaderFromFileA
-@ stub D3DXPreprocessShaderFromFileW
-@ stub D3DXPreprocessShaderFromResourceA
-@ stub D3DXPreprocessShaderFromResourceW
+@ stdcall D3DXPreprocessShader(ptr long ptr ptr ptr ptr)
+@ stdcall D3DXPreprocessShaderFromFileA(str ptr ptr ptr ptr)
+@ stdcall D3DXPreprocessShaderFromFileW(wstr ptr ptr ptr ptr)
+@ stdcall D3DXPreprocessShaderFromResourceA(long str ptr ptr ptr ptr)
+@ stdcall D3DXPreprocessShaderFromResourceW(long wstr ptr ptr ptr ptr)
@ stdcall D3DXQuaternionBaryCentric(ptr ptr ptr ptr float float)
@ stdcall D3DXQuaternionExp(ptr ptr)
@ stdcall D3DXQuaternionInverse(ptr ptr)
diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c
index a3648c2..7361e85 100644
--- a/dlls/d3dx9_36/shader.c
+++ b/dlls/d3dx9_36/shader.c
@@ -446,7 +446,7 @@ HRESULT WINAPI D3DXCompileShaderFromFileW(LPCWSTR filename,
}
WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
- hr = D3DCompile(buffer, len, filename_a, (D3D_SHADER_MACRO *)defines,
+ hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
(ID3DInclude *)include, entrypoint, profile, flags, 0,
(ID3DBlob **)shader, (ID3DBlob **)error_messages);
@@ -505,6 +505,121 @@ HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module,
flags, shader, error_messages, constant_table);
}
+HRESULT WINAPI D3DXPreprocessShader(LPCSTR data,
+ UINT data_len,
+ CONST D3DXMACRO* defines,
+ LPD3DXINCLUDE include,
+ LPD3DXBUFFER* shader,
+ LPD3DXBUFFER* error_messages)
+{
+ TRACE("Forward to D3DPreprocess\n");
+ return D3DPreprocess(data, data_len, NULL,
+ (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
+ (ID3DBlob **)shader, (ID3DBlob **)error_messages);
+}
+
+HRESULT WINAPI D3DXPreprocessShaderFromFileA(LPCSTR filename,
+ CONST D3DXMACRO* defines,
+ LPD3DXINCLUDE include,
+ LPD3DXBUFFER* shader,
+ LPD3DXBUFFER* error_messages)
+{
+ WCHAR *filename_w = NULL;
+ DWORD len;
+ HRESULT ret;
+
+ if (!filename) return D3DXERR_INVALIDDATA;
+
+ len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
+ filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!filename_w) return E_OUTOFMEMORY;
+ MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
+
+ ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
+
+ HeapFree(GetProcessHeap(), 0, filename_w);
+ return ret;
+}
+
+HRESULT WINAPI D3DXPreprocessShaderFromFileW(LPCWSTR filename,
+ CONST D3DXMACRO* defines,
+ LPD3DXINCLUDE include,
+ LPD3DXBUFFER* shader,
+ LPD3DXBUFFER* error_messages)
+{
+ void *buffer;
+ DWORD len, filename_len;
+ HRESULT hr;
+ struct D3DXIncludeImpl includefromfile;
+ char *filename_a;
+
+ if (FAILED(map_view_of_file(filename, &buffer, &len)))
+ return D3DXERR_INVALIDDATA;
+
+ if (!include)
+ {
+ includefromfile.lpVtbl = &D3DXInclude_Vtbl;
+ include = (LPD3DXINCLUDE)&includefromfile;
+ }
+
+ filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
+ filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
+ if (!filename_a)
+ {
+ UnmapViewOfFile(buffer);
+ return E_OUTOFMEMORY;
+ }
+ WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
+
+ hr = D3DPreprocess(buffer, len, NULL,
+ (const D3D_SHADER_MACRO *)defines,
+ (ID3DInclude *) include,
+ (ID3DBlob **)shader, (ID3DBlob **)error_messages);
+
+ HeapFree(GetProcessHeap(), 0, filename_a);
+ UnmapViewOfFile(buffer);
+ return hr;
+}
+
+HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module,
+ LPCSTR resource,
+ CONST D3DXMACRO* defines,
+ LPD3DXINCLUDE include,
+ LPD3DXBUFFER* shader,
+ LPD3DXBUFFER* error_messages)
+{
+ HRSRC res;
+ const char *buffer;
+ DWORD len;
+
+ if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
+ return D3DXERR_INVALIDDATA;
+ if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
+ return D3DXERR_INVALIDDATA;
+ return D3DXPreprocessShader(buffer, len, defines, include,
+ shader, error_messages);
+}
+
+HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
+ LPCWSTR resource,
+ CONST D3DXMACRO* defines,
+ LPD3DXINCLUDE include,
+ LPD3DXBUFFER* shader,
+ LPD3DXBUFFER* error_messages)
+{
+ HRSRC res;
+ const char *buffer;
+ DWORD len;
+
+ if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
+ return D3DXERR_INVALIDDATA;
+ if (FAILED(load_resource_into_memory(module, res, (void **)&buffer, &len)))
+ return D3DXERR_INVALIDDATA;
+ return D3DXPreprocessShader(buffer, len, defines, include,
+ shader, error_messages);
+
+}
+
static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
typedef struct ID3DXConstantTableImpl {
diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c
index 4d319ed..f6a0cb2 100644
--- a/dlls/d3dx9_36/tests/asm.c
+++ b/dlls/d3dx9_36/tests/asm.c
@@ -325,7 +325,139 @@ static void assembleshader_test(void) {
}
}
+static void d3dxpreprocess_test(void) {
+ const char testincl[] = {
+ "#define REGISTER r0\n"
+ "vs.1.1\n"
+ };
+ const char testshader[] = {
+ "#include \"incl.vsh\"\n"
+ "mov REGISTER, v0\n"
+ };
+ const char testshader3[] = {
+ "#include \"include/incl3.vsh\"\n"
+ "mov REGISTER, v0\n"
+ };
+ const char testincl3[] = {
+ "#include \"incl4.vsh\"\n"
+ };
+ const char testincl4_ok[] = {
+ "#define REGISTER r0\n"
+ "vs.1.1\n"
+ };
+ const char testincl4_wrong[] = {
+ "#error \"wrong include\"\n"
+ };
+ HRESULT hr;
+ LPD3DXBUFFER shader, messages;
+ HRESULT shader_vsh_res;
+ struct D3DXIncludeImpl include = {&D3DXInclude_Vtbl};
+
+ shader_vsh_res = create_file("shader.vsh", testshader, sizeof(testshader) - 1);
+ if(SUCCEEDED(shader_vsh_res)) {
+ create_file("incl.vsh", testincl, sizeof(testincl) - 1);
+ create_file("shader3.vsh", testshader3, sizeof(testshader3) - 1);
+ create_file("incl4.vsh", testincl4_wrong, sizeof(testincl4_wrong) - 1);
+ if(CreateDirectoryA("include", NULL)) {
+ create_file("include/incl3.vsh", testincl3, sizeof(testincl3) - 1);
+ create_file("include/incl4.vsh", testincl4_ok, sizeof(testincl4_ok) - 1);
+
+ /* path search #include test */
+ shader = NULL;
+ messages = NULL;
+ hr = D3DXPreprocessShaderFromFileA("shader3.vsh", NULL, NULL,
+ &shader, &messages);
+ ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile path search test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+ if(messages) {
+ trace("D3DXPreprocessShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+ ID3DXBuffer_Release(messages);
+ }
+ if(shader) ID3DXBuffer_Release(shader);
+ } else skip("Couldn't create \"include\" directory\n");
+
+ /* D3DXPreprocessShaderFromFile + #include test */
+ shader = NULL;
+ messages = NULL;
+ hr = D3DXPreprocessShaderFromFileA("shader.vsh",
+ NULL, NULL,
+ &shader, &messages);
+ ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+ if(messages) {
+ trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+ ID3DXBuffer_Release(messages);
+ }
+ if(shader) ID3DXBuffer_Release(shader);
+
+ /* D3DXPreprocessShaderFromFile + pInclude test */
+ shader = NULL;
+ messages = NULL;
+ hr = D3DXPreprocessShaderFromFileA("shader.vsh",
+ NULL, (LPD3DXINCLUDE)&include,
+ &shader, &messages);
+ ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+ if(messages) {
+ trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+ ID3DXBuffer_Release(messages);
+ }
+ if(shader) ID3DXBuffer_Release(shader);
+ } else skip("Couldn't create \"shader.vsh\"\n");
+
+ /* NULL shader tests */
+ shader = NULL;
+ messages = NULL;
+ hr = D3DXPreprocessShaderFromFileA("nonexistent.vsh",
+ NULL, NULL,
+ &shader, &messages);
+ ok(hr == D3DXERR_INVALIDDATA || hr == E_FAIL, /* I get this on WinXP */
+ "D3DXPreprocessShaderFromFile nonexistent file test failed with error 0x%x - %d\n",
+ hr, hr & 0x0000FFFF);
+ if(messages) {
+ trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+ ID3DXBuffer_Release(messages);
+ }
+ if(shader) ID3DXBuffer_Release(shader);
+
+ /* D3DXPreprocessShaderFromResource test */
+ shader = NULL;
+ messages = NULL;
+ hr = D3DXPreprocessShaderFromResourceA(NULL, MAKEINTRESOURCEA(IDB_ASMSHADER),
+ NULL, NULL,
+ &shader, &messages);
+ ok(hr == D3D_OK, "D3DXPreprocessShaderFromResource test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+ if(messages) {
+ trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+ ID3DXBuffer_Release(messages);
+ }
+ if(shader) ID3DXBuffer_Release(shader);
+
+ /* D3DXPreprocessShaderFromResource with missing shader resource test */
+ shader = NULL;
+ messages = NULL;
+ hr = D3DXPreprocessShaderFromResourceA(NULL, "notexisting",
+ NULL, NULL,
+ &shader, &messages);
+ ok(hr == D3DXERR_INVALIDDATA, "D3DXPreprocessShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+ if(messages) {
+ trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+ ID3DXBuffer_Release(messages);
+ }
+ if(shader) ID3DXBuffer_Release(shader);
+
+ /* cleanup */
+ if(SUCCEEDED(shader_vsh_res)) {
+ DeleteFileA("shader.vsh");
+ DeleteFileA("incl.vsh");
+ DeleteFileA("shader3.vsh");
+ DeleteFileA("incl4.vsh");
+ DeleteFileA("include/incl3.vsh");
+ DeleteFileA("include/incl4.vsh");
+ RemoveDirectoryA("include");
+ }
+}
+
START_TEST(asm)
{
assembleshader_test();
+
+ d3dxpreprocess_test();
}
diff --git a/include/d3dx9shader.h b/include/d3dx9shader.h
index 357ace2..b5380a3 100644
--- a/include/d3dx9shader.h
+++ b/include/d3dx9shader.h
@@ -349,6 +349,39 @@ HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module,
LPD3DXCONSTANTTABLE* constant_table);
#define D3DXCompileShaderFromResource WINELIB_NAME_AW(D3DXCompileShaderFromResource)
+HRESULT WINAPI D3DXPreprocessShader(LPCSTR data,
+ UINT data_len,
+ CONST D3DXMACRO* defines,
+ LPD3DXINCLUDE include,
+ LPD3DXBUFFER* shader,
+ LPD3DXBUFFER* error_messages);
+
+HRESULT WINAPI D3DXPreprocessShaderFromFileA(LPCSTR filename,
+ CONST D3DXMACRO* defines,
+ LPD3DXINCLUDE include,
+ LPD3DXBUFFER* shader,
+ LPD3DXBUFFER* error_messages);
+HRESULT WINAPI D3DXPreprocessShaderFromFileW(LPCWSTR filename,
+ CONST D3DXMACRO* defines,
+ LPD3DXINCLUDE include,
+ LPD3DXBUFFER* shader,
+ LPD3DXBUFFER* error_messages);
+#define D3DXPreprocessShaderFromFile WINELIB_NAME_AW(D3DXPreprocessShaderFromFile)
+
+HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module,
+ LPCSTR resource,
+ CONST D3DXMACRO* defines,
+ LPD3DXINCLUDE include,
+ LPD3DXBUFFER* shader,
+ LPD3DXBUFFER* error_messages);
+HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
+ LPCWSTR resource,
+ CONST D3DXMACRO* defines,
+ LPD3DXINCLUDE include,
+ LPD3DXBUFFER* shader,
+ LPD3DXBUFFER* error_messages);
+#define D3DXPreprocessShaderFromResource WINELIB_NAME_AW(D3DXPreprocessShaderFromResource)
+
HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
DWORD flags,
LPD3DXCONSTANTTABLE* constant_table);
--
1.7.2.2
More information about the wine-patches
mailing list