mirror of
https://github.com/ValveSoftware/Proton.git
synced 2025-02-11 22:28:59 +03:00
vrclient: Classify struct compatibility over SDK versions.
CW-Bug-Id: #22729
This commit is contained in:
parent
79495ea28b
commit
a0116531ad
@ -121,6 +121,8 @@ EXEMPT_STRUCTS = {
|
|||||||
"HmdVector3_t",
|
"HmdVector3_t",
|
||||||
"HmdVector3d_t",
|
"HmdVector3d_t",
|
||||||
"HmdVector4_t",
|
"HmdVector4_t",
|
||||||
|
"IntersectionMaskCircle_t",
|
||||||
|
"IntersectionMaskRectangle_t",
|
||||||
}
|
}
|
||||||
|
|
||||||
# structs for which the size is important, either because of arrays or size parameters
|
# structs for which the size is important, either because of arrays or size parameters
|
||||||
@ -213,6 +215,7 @@ all_records = {}
|
|||||||
all_structs = {}
|
all_structs = {}
|
||||||
all_sources = {}
|
all_sources = {}
|
||||||
all_versions = {}
|
all_versions = {}
|
||||||
|
unique_structs = []
|
||||||
|
|
||||||
|
|
||||||
MANUAL_METHODS = {
|
MANUAL_METHODS = {
|
||||||
@ -271,8 +274,24 @@ class BasicType:
|
|||||||
def __init__(self, type, abi):
|
def __init__(self, type, abi):
|
||||||
self._type = type.get_canonical()
|
self._type = type.get_canonical()
|
||||||
self._abi = abi
|
self._abi = abi
|
||||||
|
self._decl_order = 0
|
||||||
|
self._conv_cache = {}
|
||||||
|
|
||||||
|
self.size = self._type.get_size()
|
||||||
|
self.id = self._type.spelling
|
||||||
|
|
||||||
|
@property
|
||||||
|
def order(self):
|
||||||
|
return self._decl_order
|
||||||
|
|
||||||
|
def set_used(self, order=-1):
|
||||||
|
if self._decl_order <= order:
|
||||||
|
return
|
||||||
|
self._decl_order = order
|
||||||
|
|
||||||
def needs_conversion(self, other):
|
def needs_conversion(self, other):
|
||||||
|
if self._type.kind == TypeKind.POINTER and self._type.get_pointee().kind == TypeKind.FUNCTIONPROTO:
|
||||||
|
return self._abi != other._abi
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -282,6 +301,7 @@ class Struct:
|
|||||||
self._sdkver = sdkver
|
self._sdkver = sdkver
|
||||||
self._abi = abi
|
self._abi = abi
|
||||||
self._fields = None
|
self._fields = None
|
||||||
|
self._decl_order = 0
|
||||||
self._conv_cache = {}
|
self._conv_cache = {}
|
||||||
|
|
||||||
self.name = canonical_typename(self._cursor)
|
self.name = canonical_typename(self._cursor)
|
||||||
@ -291,6 +311,19 @@ class Struct:
|
|||||||
self.align = self.type.get_align()
|
self.align = self.type.get_align()
|
||||||
self.id = f'{abi}_{self.name}_{sdkver}'
|
self.id = f'{abi}_{self.name}_{sdkver}'
|
||||||
|
|
||||||
|
if self._cursor.spelling in EXEMPT_STRUCTS:
|
||||||
|
self._fields = [Padding(0, self.size)]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def order(self):
|
||||||
|
return self._decl_order
|
||||||
|
|
||||||
|
def set_used(self, order=-1):
|
||||||
|
if self._decl_order <= order:
|
||||||
|
return
|
||||||
|
self._decl_order = order
|
||||||
|
[f._type.set_used(order - 1) for f in self.fields]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def padded_fields(self):
|
def padded_fields(self):
|
||||||
if self._fields: return self._fields
|
if self._fields: return self._fields
|
||||||
@ -391,6 +424,7 @@ class Class:
|
|||||||
self._sdkver = sdkver
|
self._sdkver = sdkver
|
||||||
self._abi = abi
|
self._abi = abi
|
||||||
self._methods = None
|
self._methods = None
|
||||||
|
self._decl_order = 0
|
||||||
|
|
||||||
self.name = cursor.spelling
|
self.name = cursor.spelling
|
||||||
self.filename = SDK_CLASSES.get(self.name, None)
|
self.filename = SDK_CLASSES.get(self.name, None)
|
||||||
@ -398,6 +432,7 @@ class Class:
|
|||||||
self.version = versions.get(self.name, "")
|
self.version = versions.get(self.name, "")
|
||||||
|
|
||||||
self.type = self._cursor.type.get_canonical()
|
self.type = self._cursor.type.get_canonical()
|
||||||
|
self.id = f'{abi}_{self.name}_{sdkver}'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def methods(self):
|
def methods(self):
|
||||||
@ -425,9 +460,21 @@ class Class:
|
|||||||
return self.name
|
return self.name
|
||||||
return f'{self.name}_{self.version}'
|
return f'{self.name}_{self.version}'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def order(self):
|
||||||
|
return self._decl_order
|
||||||
|
|
||||||
|
def set_used(self, order=-1):
|
||||||
|
if self._decl_order <= order:
|
||||||
|
return
|
||||||
|
self._decl_order = order
|
||||||
|
|
||||||
def needs_conversion(self, other):
|
def needs_conversion(self, other):
|
||||||
return self._abi[0] != other._abi[0]
|
return self._abi[0] != other._abi[0]
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self._abi[0] == other._abi[0]
|
||||||
|
|
||||||
def write_definition(self, out, prefix):
|
def write_definition(self, out, prefix):
|
||||||
out(f'struct {prefix}{self.full_name}\n')
|
out(f'struct {prefix}{self.full_name}\n')
|
||||||
out(u'{\n')
|
out(u'{\n')
|
||||||
@ -543,6 +590,11 @@ def declspec(decl, name, prefix):
|
|||||||
if decl.kind == TypeKind.ENUM:
|
if decl.kind == TypeKind.ENUM:
|
||||||
return f'uint{decl.get_size() * 8}_t{name}'
|
return f'uint{decl.get_size() * 8}_t{name}'
|
||||||
|
|
||||||
|
type_name = decl.spelling.removeprefix("const ")
|
||||||
|
type_name = decl.spelling.removeprefix("vr::")
|
||||||
|
if type_name.startswith(('IVR', 'ID3D')):
|
||||||
|
return f'{const}void /*{type_name}*/{name}'
|
||||||
|
|
||||||
real_name = canonical_typename(decl)
|
real_name = canonical_typename(decl)
|
||||||
real_name = real_name.removeprefix("const ")
|
real_name = real_name.removeprefix("const ")
|
||||||
real_name = real_name.removeprefix("vr::")
|
real_name = real_name.removeprefix("vr::")
|
||||||
@ -1492,6 +1544,43 @@ def load(sdkver):
|
|||||||
return versions, sources
|
return versions, sources
|
||||||
|
|
||||||
|
|
||||||
|
def classify_struct(name):
|
||||||
|
if name in EXEMPT_STRUCTS:
|
||||||
|
return None
|
||||||
|
structs = all_structs[name]
|
||||||
|
|
||||||
|
prev = []
|
||||||
|
versions = {}
|
||||||
|
unique = True
|
||||||
|
|
||||||
|
for sdkver in filter(lambda v: v in structs, reversed(SDK_VERSIONS)):
|
||||||
|
abis = [structs[sdkver][a] for a in ABIS]
|
||||||
|
|
||||||
|
if any(abis[0].needs_conversion(a) for a in abis[1:]):
|
||||||
|
unique = False
|
||||||
|
|
||||||
|
def is_always_compatible(other):
|
||||||
|
for a, b in zip(abis, other):
|
||||||
|
if a.needs_conversion(b):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
compat = next((k for k, v in prev if is_always_compatible(v)), None)
|
||||||
|
if compat:
|
||||||
|
versions[sdkver] = versions[compat]
|
||||||
|
else:
|
||||||
|
[abi.set_used() for abi in abis] # make sure order is computed
|
||||||
|
versions[sdkver] = f"{name}_{display_sdkver(sdkver)}"
|
||||||
|
prev += [(sdkver, abis)]
|
||||||
|
|
||||||
|
if unique:
|
||||||
|
unique_structs.append(name)
|
||||||
|
|
||||||
|
if len(set(versions.values())) == 1:
|
||||||
|
versions = {sdkver: name for sdkver in versions.keys()}
|
||||||
|
return versions
|
||||||
|
|
||||||
|
|
||||||
def generate(sdkver, structs):
|
def generate(sdkver, structs):
|
||||||
print(f'generating SDK version {sdkver}...')
|
print(f'generating SDK version {sdkver}...')
|
||||||
for child in structs['u32'].values():
|
for child in structs['u32'].values():
|
||||||
@ -1553,6 +1642,31 @@ for i, sdkver in enumerate(reversed(SDK_VERSIONS)):
|
|||||||
print('parsing SDKs... 100%')
|
print('parsing SDKs... 100%')
|
||||||
|
|
||||||
|
|
||||||
|
tmp_structs = {}
|
||||||
|
|
||||||
|
for i, name in enumerate(all_structs.keys()):
|
||||||
|
print(f'classifying structs... {i * 100 // len(all_structs.keys())}%', end='\r')
|
||||||
|
versions = classify_struct(name)
|
||||||
|
for sdkver in SDK_VERSIONS:
|
||||||
|
if not versions or sdkver not in versions: continue
|
||||||
|
all_versions[sdkver][name] = versions[sdkver]
|
||||||
|
|
||||||
|
def struct_order(tuple):
|
||||||
|
name, structs = tuple
|
||||||
|
order = (struct.order for abis in structs.values()
|
||||||
|
for struct in abis.values())
|
||||||
|
return (min(order), name)
|
||||||
|
|
||||||
|
for name, structs in sorted(all_structs.items(), key=struct_order):
|
||||||
|
tmp_structs[name] = {}
|
||||||
|
for sdkver in filter(lambda v: v in structs, SDK_VERSIONS):
|
||||||
|
tmp_structs[name][sdkver] = {a: structs[sdkver][a] for a in ABIS}
|
||||||
|
|
||||||
|
all_structs = tmp_structs
|
||||||
|
|
||||||
|
print('classifying structs... 100%')
|
||||||
|
|
||||||
|
|
||||||
for klass in all_classes.values():
|
for klass in all_classes.values():
|
||||||
with open(f"vrclient_x64/win{klass.name}.c", "w") as file:
|
with open(f"vrclient_x64/win{klass.name}.c", "w") as file:
|
||||||
out = file.write
|
out = file.write
|
||||||
|
Loading…
x
Reference in New Issue
Block a user