From 128cf64371a385eb75642af6b6ef6342bec9ceba Mon Sep 17 00:00:00 2001 From: Christian Costa Date: Fri, 10 Sep 2010 18:42:45 +0200 Subject: [PATCH] d3dx9: Constant table parsing foundations. --- dlls/d3dx9_36/shader.c | 139 ++++++++++++++++++++++++++++++++--- dlls/d3dx9_36/tests/shader.c | 105 ++++++++++++++++++++++++++ 2 files changed, 233 insertions(+), 11 deletions(-) diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c index 8c4580a244..e2efe53dbd 100644 --- a/dlls/d3dx9_36/shader.c +++ b/dlls/d3dx9_36/shader.c @@ -609,14 +609,20 @@ HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module, } +typedef struct ctab_constant { + D3DXCONSTANT_DESC desc; + struct ctab_constant *members; +} ctab_constant; + static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl; typedef struct ID3DXConstantTableImpl { const ID3DXConstantTableVtbl *lpVtbl; LONG ref; - LPVOID ctab; + char *ctab; DWORD size; D3DXCONSTANTTABLE_DESC desc; + ctab_constant *constants; } ID3DXConstantTableImpl; /*** IUnknown methods ***/ @@ -658,6 +664,7 @@ static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable* iface) if (!ref) { + HeapFree(GetProcessHeap(), 0, This->constants); HeapFree(GetProcessHeap(), 0, This->ctab); HeapFree(GetProcessHeap(), 0, This); } @@ -703,10 +710,31 @@ static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable* D3DXCONSTANT_DESC *desc, UINT *count) { ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface; + ctab_constant *constant_info; - FIXME("(%p)->(%p, %p, %p): stub\n", This, constant, desc, count); + TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count); - return E_NOTIMPL; + if (!constant) + return D3DERR_INVALIDCALL; + + /* Applications can pass the name of the constant in place of the handle */ + if (!((UINT_PTR)constant >> 16)) + constant_info = &This->constants[(UINT_PTR)constant - 1]; + else + { + D3DXHANDLE c = ID3DXConstantTable_GetConstantByName(iface, NULL, constant); + if (!c) + return D3DERR_INVALIDCALL; + + constant_info = &This->constants[(UINT_PTR)c - 1]; + } + + if (desc) + *desc = constant_info->desc; + if (count) + *count = 1; + + return D3D_OK; } static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(LPD3DXCONSTANTTABLE iface, D3DXHANDLE constant) @@ -722,16 +750,39 @@ static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable* { ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface; - FIXME("(%p)->(%p, %d): stub\n", This, constant, index); + TRACE("(%p)->(%p, %d)\n", This, constant, index); - return NULL; + if (constant) + { + FIXME("Only top level constants supported\n"); + return NULL; + } + + if (index >= This->desc.Constants) + return NULL; + + return (D3DXHANDLE)(DWORD_PTR)(index + 1); } static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable* iface, D3DXHANDLE constant, LPCSTR name) { ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface; + UINT i; + + TRACE("(%p)->(%p, %s)\n", This, constant, name); - FIXME("(%p)->(%p, %s): stub\n", This, constant, name); + if (!name) + return NULL; + + if (constant) + { + FIXME("Only top level constants supported\n"); + return NULL; + } + + for (i = 0; i < This->desc.Constants; i++) + if (!strcmp(This->constants[i].desc.Name, name)) + return (D3DXHANDLE)(DWORD_PTR)(i + 1); return NULL; } @@ -937,6 +988,27 @@ static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl = ID3DXConstantTableImpl_SetMatrixTransposePointerArray }; +static HRESULT parse_ctab_constant_type(const D3DXSHADER_TYPEINFO *type, ctab_constant *constant) +{ + constant->desc.Class = type->Class; + constant->desc.Type = type->Type; + constant->desc.Rows = type->Rows; + constant->desc.Columns = type->Columns; + constant->desc.StructMembers = type->StructMembers; + + TRACE("class = %d, type = %d, rows = %d, columns = %d, struct_members = %d\n", + constant->desc.Class, constant->desc.Type, + constant->desc.Rows, constant->desc.Columns, constant->desc.StructMembers); + + if ((constant->desc.Class == D3DXPC_STRUCT) && constant->desc.StructMembers) + { + FIXME("Struct not supported yet\n"); + return E_NOTIMPL; + } + + return D3D_OK; +} + HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code, DWORD flags, LPD3DXCONSTANTTABLE* constant_table) @@ -946,8 +1018,10 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code, LPCVOID data; UINT size; const D3DXSHADER_CONSTANTTABLE* ctab_header; + D3DXSHADER_CONSTANTINFO* constant_info; + DWORD i; - FIXME("(%p, %x, %p): semi-stub\n", byte_code, flags, constant_table); + TRACE("(%p, %x, %p)\n", byte_code, flags, constant_table); if (!byte_code || !constant_table) return D3DERR_INVALIDCALL; @@ -967,24 +1041,66 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code, object->ref = 1; if (size < sizeof(D3DXSHADER_CONSTANTTABLE)) + { + hr = D3DXERR_INVALIDDATA; goto error; + } object->ctab = HeapAlloc(GetProcessHeap(), 0, size); if (!object->ctab) { - HeapFree(GetProcessHeap(), 0, object); ERR("Out of memory\n"); - return E_OUTOFMEMORY; + hr = E_OUTOFMEMORY; + goto error; } object->size = size; memcpy(object->ctab, data, object->size); ctab_header = (const D3DXSHADER_CONSTANTTABLE*)data; if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE)) + { + hr = D3DXERR_INVALIDDATA; goto error; - object->desc.Creator = ctab_header->Creator ? (LPCSTR)object->ctab + ctab_header->Creator : NULL; + } + object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL; object->desc.Version = ctab_header->Version; object->desc.Constants = ctab_header->Constants; + if (object->desc.Creator) + TRACE("Creator = %s\n", object->desc.Creator); + TRACE("Version = %x\n", object->desc.Version); + TRACE("Constants = %d\n", ctab_header->Constants); + if (ctab_header->Target) + TRACE("Target = %s\n", object->ctab + ctab_header->Target); + + if (object->desc.Constants > 65535) + { + FIXME("Too many constants (%u)\n", object->desc.Constants); + hr = E_NOTIMPL; + goto error; + } + + object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(*object->constants) * object->desc.Constants); + if (!object->constants) + { + ERR("Out of memory\n"); + hr = E_OUTOFMEMORY; + goto error; + } + + constant_info = (LPD3DXSHADER_CONSTANTINFO)(object->ctab + ctab_header->ConstantInfo); + for (i = 0; i < ctab_header->Constants; i++) + { + TRACE("name = %s\n", object->ctab + constant_info[i].Name); + object->constants[i].desc.Name = object->ctab + constant_info[i].Name; + object->constants[i].desc.RegisterSet = constant_info[i].RegisterSet; + object->constants[i].desc.RegisterIndex = constant_info[i].RegisterIndex; + object->constants[i].desc.RegisterCount = 0; + hr = parse_ctab_constant_type((LPD3DXSHADER_TYPEINFO)(object->ctab + constant_info[i].TypeInfo), + &object->constants[i]); + if (hr != D3D_OK) + goto error; + } *constant_table = (LPD3DXCONSTANTTABLE)object; @@ -992,10 +1108,11 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code, error: + HeapFree(GetProcessHeap(), 0, object->constants); HeapFree(GetProcessHeap(), 0, object->ctab); HeapFree(GetProcessHeap(), 0, object); - return D3DXERR_INVALIDDATA; + return hr; } HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code, diff --git a/dlls/d3dx9_36/tests/shader.c b/dlls/d3dx9_36/tests/shader.c index 3615279193..ae505d12f9 100644 --- a/dlls/d3dx9_36/tests/shader.c +++ b/dlls/d3dx9_36/tests/shader.c @@ -55,6 +55,23 @@ static const DWORD shader_with_invalid_ctab[] = { 0x00000000, 0x00000000, 0x0000ffff}; /* END */ +static const DWORD shader_with_ctab_constants[] = { + 0xfffe0300, /* vs_3_0 */ + 0x002efffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x000000a4, 0xfffe0300, 0x00000003, 0x0000001c, 0x20008100, /* Header */ + 0x0000009c, + 0x00000058, 0x00070002, 0x00000001, 0x00000064, 0x00000000, /* Constant 1 desc */ + 0x00000074, 0x00000002, 0x00000004, 0x00000080, 0x00000000, /* Constant 2 desc */ + 0x00000090, 0x00040002, 0x00000003, 0x00000080, 0x00000000, /* Constant 3 desc */ + 0x736e6f43, 0x746e6174, 0xabab0031, /* Constant 1 name string */ + 0x00030001, 0x00040001, 0x00000001, 0x00000000, /* Constant 1 type desc */ + 0x736e6f43, 0x746e6174, 0xabab0032, /* Constant 2 name string */ + 0x00030003, 0x00040004, 0x00000001, 0x00000000, /* Constant 2 & 3 type desc */ + 0x736e6f43, 0x746e6174, 0xabab0033, /* Constant 3 name string */ + 0x335f7376, 0xab00305f, /* Target name string */ + 0x656e6957, 0x6f727020, 0x7463656a, 0xababab00, /* Creator name string */ + 0x0000ffff}; /* END */ + static void test_get_shader_size(void) { UINT shader_size, expected; @@ -157,6 +174,94 @@ static void test_get_shader_constant_table_ex(void) ID3DXConstantTable_Release(constant_table); } + + hr = D3DXGetShaderConstantTableEx(shader_with_ctab_constants, 0, &constant_table); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + if (SUCCEEDED(hr)) + { + D3DXHANDLE constant; + D3DXCONSTANT_DESC constant_desc; + D3DXCONSTANT_DESC constant_desc_save; + UINT nb; + + /* Test GetDesc */ + hr = ID3DXConstantTable_GetDesc(constant_table, &desc); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!strcmp(desc.Creator, "Wine project"), "Got result '%s', expected 'Wine project'\n", desc.Creator); + ok(desc.Version == D3DVS_VERSION(3, 0), "Got result %x, expected %x\n", desc.Version, D3DVS_VERSION(3, 0)); + ok(desc.Constants == 3, "Got result %x, expected 3\n", desc.Constants); + + /* Test GetConstant */ + constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 0); + ok(constant != NULL, "No constant found\n"); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!strcmp(constant_desc.Name, "Constant1"), "Got result '%s', expected 'Constant1'\n", + constant_desc.Name); + ok(constant_desc.Class == D3DXPC_VECTOR, "Got result %x, expected %u (D3DXPC_VECTOR)\n", + constant_desc.Class, D3DXPC_VECTOR); + ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n", + constant_desc.Type, D3DXPT_FLOAT); + ok(constant_desc.Rows == 1, "Got result %x, expected 1\n", constant_desc.Rows); + ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns); + + constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 1); + ok(constant != NULL, "No constant found\n"); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!strcmp(constant_desc.Name, "Constant2"), "Got result '%s', expected 'Constant2'\n", + constant_desc.Name); + ok(constant_desc.Class == D3DXPC_MATRIX_COLUMNS, "Got result %x, expected %u (D3DXPC_MATRIX_COLUMNS)\n", + constant_desc.Class, D3DXPC_MATRIX_COLUMNS); + ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n", + constant_desc.Type, D3DXPT_FLOAT); + ok(constant_desc.Rows == 4, "Got result %x, expected 1\n", constant_desc.Rows); + ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns); + + constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 2); + ok(constant != NULL, "No constant found\n"); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!strcmp(constant_desc.Name, "Constant3"), "Got result '%s', expected 'Constant3'\n", + constant_desc.Name); + ok(constant_desc.Class == D3DXPC_MATRIX_COLUMNS, "Got result %x, expected %u (D3DXPC_MATRIX_COLUMNS)\n", + constant_desc.Class, D3DXPC_MATRIX_COLUMNS); + ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n", + constant_desc.Type, D3DXPT_FLOAT); + ok(constant_desc.Rows == 4, "Got result %x, expected 1\n", constant_desc.Rows); + ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns); + constant_desc_save = constant_desc; /* For GetConstantDesc test */ + + constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 3); + ok(constant == NULL, "Got result %p, expected NULL\n", constant); + + /* Test GetConstantByName */ + constant = ID3DXConstantTable_GetConstantByName(constant_table, NULL, "Constant unknown"); + ok(constant == NULL, "Got result %p, expected NULL\n", constant); + constant = ID3DXConstantTable_GetConstantByName(constant_table, NULL, "Constant3"); + ok(constant != NULL, "No constant found\n"); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!memcmp(&constant_desc, &constant_desc_save, sizeof(D3DXCONSTANT_DESC)), "Got different constant data\n"); + + /* Test GetConstantDesc */ + constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 0); + ok(constant != NULL, "No constant found\n"); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, NULL, &constant_desc, &nb); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, NULL, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, "Constant unknow", &constant_desc, &nb); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, "Constant3", &constant_desc, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!memcmp(&constant_desc, &constant_desc_save, sizeof(D3DXCONSTANT_DESC)), "Got different constant data\n"); + + ID3DXConstantTable_Release(constant_table); + } } START_TEST(shader) -- 2.32.0.93.g670b81a890