d3dx9: Parse structs and sub constants in ID3DXConstantTable.

This commit is contained in:
Rico Schüller 2012-08-23 21:36:50 +02:00 committed by Alexandre Julliard
parent 8f83681723
commit b565e8fb4f
1 changed files with 129 additions and 21 deletions

View File

@ -618,7 +618,7 @@ HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
struct ctab_constant {
D3DXCONSTANT_DESC desc;
struct ctab_constant *members;
struct ctab_constant *constants;
};
static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
@ -632,9 +632,32 @@ struct ID3DXConstantTableImpl {
struct ctab_constant *constants;
};
static void free_constant(struct ctab_constant *constant)
{
if (constant->constants)
{
UINT i, count = constant->desc.Elements > 1 ? constant->desc.Elements : constant->desc.StructMembers;
for (i = 0; i < count; ++i)
{
free_constant(&constant->constants[i]);
}
HeapFree(GetProcessHeap(), 0, constant->constants);
}
}
static void free_constant_table(struct ID3DXConstantTableImpl *table)
{
HeapFree(GetProcessHeap(), 0, table->constants);
if (table->constants)
{
UINT i;
for (i = 0; i < table->desc.Constants; ++i)
{
free_constant(&table->constants[i]);
}
HeapFree(GetProcessHeap(), 0, table->constants);
}
HeapFree(GetProcessHeap(), 0, table->ctab);
}
@ -1426,27 +1449,117 @@ static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
ID3DXConstantTableImpl_SetMatrixTransposePointerArray
};
static HRESULT parse_ctab_constant_type(const D3DXSHADER_TYPEINFO *type, struct ctab_constant *constant)
static HRESULT parse_ctab_constant_type(const char *ctab, DWORD typeoffset, struct ctab_constant *constant,
BOOL is_element, WORD index, WORD max, DWORD *offset, DWORD nameoffset, UINT regset)
{
const D3DXSHADER_TYPEINFO *type = (LPD3DXSHADER_TYPEINFO)(ctab + typeoffset);
const D3DXSHADER_STRUCTMEMBERINFO *memberinfo = NULL;
HRESULT hr = D3D_OK;
UINT i, count = 0;
WORD size = 0;
constant->desc.DefaultValue = offset ? ctab + *offset : NULL;
constant->desc.Class = type->Class;
constant->desc.Type = type->Type;
constant->desc.Rows = type->Rows;
constant->desc.Columns = type->Columns;
constant->desc.Elements = type->Elements;
constant->desc.Elements = is_element ? 1 : type->Elements;
constant->desc.StructMembers = type->StructMembers;
constant->desc.Bytes = calc_bytes(&constant->desc);
constant->desc.Name = ctab + nameoffset;
constant->desc.RegisterSet = regset;
constant->desc.RegisterIndex = index;
TRACE("class = %d, type = %d, rows = %d, columns = %d, elements = %d, struct_members = %d\n",
constant->desc.Class, constant->desc.Type, constant->desc.Rows,
constant->desc.Columns, constant->desc.Elements, constant->desc.StructMembers);
TRACE("name %s, elements %u, index %u, defaultvalue %p\n", constant->desc.Name,
constant->desc.Elements, index, constant->desc.DefaultValue);
TRACE("class %d, type %d, rows %d, columns %d, elements %d, struct_members %d\n",
type->Class, type->Type, type->Rows, type->Columns, type->Elements, type->StructMembers);
if ((constant->desc.Class == D3DXPC_STRUCT) && constant->desc.StructMembers)
if (type->Elements > 1 && !is_element)
{
FIXME("Struct not supported yet\n");
return E_NOTIMPL;
count = type->Elements;
}
else if ((type->Class == D3DXPC_STRUCT) && type->StructMembers)
{
memberinfo = (D3DXSHADER_STRUCTMEMBERINFO*)(ctab + type->StructMemberInfo);
count = type->StructMembers;
}
if (count)
{
WORD size_element = 0;
constant->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*constant->constants) * count);
if (!constant->constants)
{
ERR("Out of memory\n");
hr = E_OUTOFMEMORY;
goto error;
}
for (i = 0; i < count; ++i)
{
hr = parse_ctab_constant_type(ctab, memberinfo ? memberinfo[i].TypeInfo : typeoffset,
&constant->constants[i], memberinfo == NULL, index + size, max, offset,
memberinfo ? memberinfo[i].Name : nameoffset, regset);
if (hr != D3D_OK)
goto error;
if (i == 0) size_element = constant->constants[i].desc.RegisterCount;
size += size_element;
}
}
else
{
WORD offsetdiff = 0;
switch (type->Class)
{
case D3DXPC_SCALAR:
case D3DXPC_VECTOR:
offsetdiff = 1;
size = 1;
break;
case D3DXPC_MATRIX_ROWS:
size = is_element ? type->Rows : max(type->Rows, type->Columns);
offsetdiff = type->Rows;
break;
case D3DXPC_MATRIX_COLUMNS:
size = type->Columns;
offsetdiff = type->Columns;
break;
case D3DXPC_OBJECT:
size = 1;
break;
default:
FIXME("Unhandled type class %u\n", type->Class);
break;
}
/* offset in bytes => offsetdiff * components(4) * sizeof(DWORD) */
if (offset) *offset += offsetdiff * 4 * 4;
}
constant->desc.RegisterCount = max(0, min(max - index, size));
constant->desc.Bytes = calc_bytes(&constant->desc);
return D3D_OK;
error:
if (constant->constants)
{
for (i = 0; i < count; ++i)
{
free_constant(&constant->constants[i]);
}
HeapFree(GetProcessHeap(), 0, constant->constants);
constant->constants = NULL;
}
return hr;
}
HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD *byte_code,
@ -1537,16 +1650,12 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD *byte_code,
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 = constant_info[i].RegisterCount;
object->constants[i].desc.DefaultValue = constant_info[i].DefaultValue
? object->ctab + constant_info[i].DefaultValue : NULL;
DWORD offset = constant_info[i].DefaultValue;
hr = parse_ctab_constant_type((LPD3DXSHADER_TYPEINFO)(object->ctab + constant_info[i].TypeInfo),
&object->constants[i]);
hr = parse_ctab_constant_type(object->ctab, constant_info[i].TypeInfo,
&object->constants[i], FALSE, constant_info[i].RegisterIndex,
constant_info[i].RegisterIndex + constant_info[i].RegisterCount,
offset ? &offset : NULL, constant_info[i].Name, constant_info[i].RegisterSet);
if (hr != D3D_OK)
goto error;
}
@ -1556,7 +1665,6 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD *byte_code,
return D3D_OK;
error:
free_constant_table(object);
HeapFree(GetProcessHeap(), 0, object);