vrclient: Introduce unix-side buffer cache with PE allocate pointers.

There are several steam API calls that currently pass unix pointers
for e.g. strings directly to the PE-side, this allows for caching such
return values and returning a PE-side pointer instead.
This commit is contained in:
Rémi Bernon 2025-01-21 14:20:18 +01:00 committed by Arkadiusz Hiler
parent 6c13702ab3
commit 85151b7dfa
9 changed files with 74 additions and 0 deletions

View File

@ -223,6 +223,7 @@ unique_structs = []
UNIX_FUNCS = [
'vrclient_init',
'vrclient_init_registry',
'vrclient_get_unix_buffer',
'vrclient_HmdSystemFactory',
'vrclient_VRClientCoreFactory',
'vrclient_unload',

View File

@ -30,6 +30,7 @@ extern NTSTATUS vrclient_init_registry( void *args );
extern NTSTATUS vrclient_unload( void *args );
extern NTSTATUS vrclient_HmdSystemFactory( void *args );
extern NTSTATUS vrclient_VRClientCoreFactory( void *args );
extern NTSTATUS vrclient_get_unix_buffer( void *args );
extern char *vrclient_dos_to_unix_path( const char *src );
extern void vrclient_free_path( char *path );

View File

@ -2,7 +2,9 @@
#include <winternl.h>
#include <dlfcn.h>
#include <pthread.h>
#include <stdlib.h>
#include <unordered_map>
#define WINE_VK_HOST
#include <vulkan/vulkan.h>
@ -370,3 +372,35 @@ NTSTATUS IVRTrackedCamera_IVRTrackedCamera_001_GetVideoStreamFrame( void *args )
*(w_CameraVideoStreamFrame_t_0914 *)params->_ret = *iface->GetVideoStreamFrame( params->nDeviceIndex );
return 0;
}
namespace std
{
template<> struct hash< struct u_buffer >
{
using argument_type = struct u_buffer;
using result_type = std::size_t;
result_type operator()( argument_type const& buf ) const { return buf.ptr; }
};
}
static pthread_mutex_t buffer_cache_lock = PTHREAD_MUTEX_INITIALIZER;
static std::unordered_map< struct u_buffer, void * > buffer_cache;
NTSTATUS vrclient_get_unix_buffer( void *args )
{
struct vrclient_get_unix_buffer_params *params = (struct vrclient_get_unix_buffer_params *)args;
struct cache_entry *entry;
struct rb_entry *ptr;
pthread_mutex_lock( &buffer_cache_lock );
auto iter = buffer_cache.find( params->buf );
if (iter != buffer_cache.end()) params->ptr = iter->second;
else
{
memcpy( params->ptr, (char *)params->buf, params->buf.len );
buffer_cache[params->buf] = params->ptr;
}
pthread_mutex_unlock( &buffer_cache_lock );
return 0;
}

View File

@ -73,6 +73,12 @@ struct vrclient_VRClientCoreFactory_params
int *return_code;
};
struct vrclient_get_unix_buffer_params
{
struct u_buffer buf;
void *ptr; /* client-side ptr */
};
#include <poppack.h>
#define VRCLIENT_CALL( code, args ) \

View File

@ -9,6 +9,7 @@ extern "C" const unixlib_entry_t __wine_unix_call_funcs[] =
{
vrclient_init,
vrclient_init_registry,
vrclient_get_unix_buffer,
vrclient_HmdSystemFactory,
vrclient_VRClientCoreFactory,
vrclient_unload,

View File

@ -29223,6 +29223,7 @@ enum unix_funcs
{
unix_vrclient_init,
unix_vrclient_init_registry,
unix_vrclient_get_unix_buffer,
unix_vrclient_HmdSystemFactory,
unix_vrclient_VRClientCoreFactory,
unix_vrclient_unload,

View File

@ -314,6 +314,24 @@ BOOL CDECL vrclient_init_registry(void)
return TRUE;
}
void *get_unix_buffer( struct u_buffer buf )
{
struct vrclient_get_unix_buffer_params params = {.buf = buf};
void *ret;
if ((UINT_PTR)buf.ptr == buf.ptr && (UINT_PTR)(buf.ptr + buf.len) == (buf.ptr + buf.len))
return (void *)(UINT_PTR)buf.ptr;
if (!(params.ptr = ret = HeapAlloc( GetProcessHeap(), 0, buf.len ))) return NULL;
if (VRCLIENT_CALL( vrclient_get_unix_buffer, &params ) || (ret != params.ptr))
{
HeapFree( GetProcessHeap(), 0, ret );
ret = params.ptr;
}
return ret;
}
static int8_t is_hmd_present_reg(void)
{
DWORD type, value, wait_status, size;

View File

@ -104,6 +104,8 @@ extern void init_rtti( char *base );
struct w_iface *create_win_interface( const char *name, struct u_iface u_iface );
void free_compositor_data_d3d12_device(void);
extern void *get_unix_buffer( struct u_buffer buf );
struct generic_interface
{
struct w_iface *object;

View File

@ -134,3 +134,13 @@ struct u_iface
template< typename T > operator T*() const { return (T*)(UINT_PTR)this->handle; }
#endif /* __cplusplus */
};
struct u_buffer
{
UINT64 ptr;
UINT64 len;
#ifdef __cplusplus
struct u_buffer &operator=(const char* value) { this->ptr = (UINT_PTR)value; this->len = value ? strlen( value ) + 1 : 0; return *this; }
operator char*() const { return (char*)(UINT_PTR)this->ptr; }
#endif /* __cplusplus */
};