Commit 128cf643 authored by Christian Costa's avatar Christian Costa Committed by Alexandre Julliard

d3dx9: Constant table parsing foundations.

parent b4736bd7
......@@ -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,
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment