mirror of
https://github.com/ValveSoftware/Proton.git
synced 2024-12-27 23:25:50 +03:00
vrclient: Classify struct compatibility over SDK versions.
CW-Bug-Id: #22729
This commit is contained in:
parent
fb25831f68
commit
cafc3fb8e7
@ -121,6 +121,8 @@ EXEMPT_STRUCTS = {
|
||||
"HmdVector3_t",
|
||||
"HmdVector3d_t",
|
||||
"HmdVector4_t",
|
||||
"IntersectionMaskCircle_t",
|
||||
"IntersectionMaskRectangle_t",
|
||||
}
|
||||
|
||||
# structs for which the size is important, either because of arrays or size parameters
|
||||
@ -213,6 +215,7 @@ all_records = {}
|
||||
all_structs = {}
|
||||
all_sources = {}
|
||||
all_versions = {}
|
||||
unique_structs = []
|
||||
|
||||
|
||||
MANUAL_METHODS = {
|
||||
@ -271,8 +274,24 @@ class BasicType:
|
||||
def __init__(self, type, abi):
|
||||
self._type = type.get_canonical()
|
||||
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):
|
||||
if self._type.kind == TypeKind.POINTER and self._type.get_pointee().kind == TypeKind.FUNCTIONPROTO:
|
||||
return self._abi != other._abi
|
||||
return False
|
||||
|
||||
|
||||
@ -282,6 +301,7 @@ class Struct:
|
||||
self._sdkver = sdkver
|
||||
self._abi = abi
|
||||
self._fields = None
|
||||
self._decl_order = 0
|
||||
self._conv_cache = {}
|
||||
|
||||
self.name = canonical_typename(self._cursor)
|
||||
@ -291,6 +311,19 @@ class Struct:
|
||||
self.align = self.type.get_align()
|
||||
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
|
||||
def padded_fields(self):
|
||||
if self._fields: return self._fields
|
||||
@ -391,6 +424,7 @@ class Class:
|
||||
self._sdkver = sdkver
|
||||
self._abi = abi
|
||||
self._methods = None
|
||||
self._decl_order = 0
|
||||
|
||||
self.name = cursor.spelling
|
||||
self.filename = SDK_CLASSES.get(self.name, None)
|
||||
@ -398,6 +432,7 @@ class Class:
|
||||
self.version = versions.get(self.name, "")
|
||||
|
||||
self.type = self._cursor.type.get_canonical()
|
||||
self.id = f'{abi}_{self.name}_{sdkver}'
|
||||
|
||||
@property
|
||||
def methods(self):
|
||||
@ -425,9 +460,21 @@ class Class:
|
||||
return self.name
|
||||
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):
|
||||
return self._abi[0] != other._abi[0]
|
||||
|
||||
def __eq__(self, other):
|
||||
return self._abi[0] == other._abi[0]
|
||||
|
||||
def write_definition(self, out, prefix):
|
||||
out(f'struct {prefix}{self.full_name}\n')
|
||||
out(u'{\n')
|
||||
@ -543,6 +590,11 @@ def declspec(decl, name, prefix):
|
||||
if decl.kind == TypeKind.ENUM:
|
||||
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 = real_name.removeprefix("const ")
|
||||
real_name = real_name.removeprefix("vr::")
|
||||
@ -1492,6 +1544,43 @@ def load(sdkver):
|
||||
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):
|
||||
print(f'generating SDK version {sdkver}...')
|
||||
for child in structs['u32'].values():
|
||||
@ -1553,6 +1642,31 @@ for i, sdkver in enumerate(reversed(SDK_VERSIONS)):
|
||||
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():
|
||||
with open(f"vrclient_x64/win{klass.name}.c", "w") as file:
|
||||
out = file.write
|
||||
|
Loading…
Reference in New Issue
Block a user