Merge branch 'wow64_placed_alloc' into 'master'

Draft: Placed-allocation-callback solution for wow64 GL memory mappings

See merge request wine/wine!6663
This commit is contained in:
Derek Lesho 2024-11-19 19:47:44 +00:00
commit 028957963d
10 changed files with 54025 additions and 14 deletions

File diff suppressed because it is too large Load diff

View file

@ -97,6 +97,8 @@ my %arg_types =
"GLint64EXT" => [ "int64", "wine_dbgstr_longlong(%s)" ],
"GLintptr" => [ "long", "%Id" ],
"GLintptrARB" => [ "long", "%Id" ],
"GLplacedMapMESA" => [ "ptr", "%p" ],
"GLplacedUnmapMESA" => [ "ptr", "%p" ],
"GLshort" => [ "long", "%d" ],
"GLsizei" => [ "long", "%d" ],
"GLsizeiptr" => [ "long", "%Id" ],
@ -1072,6 +1074,7 @@ print OUT " unix_process_attach,\n";
print OUT " unix_thread_attach,\n";
print OUT " unix_process_detach,\n";
print OUT " unix_get_pixel_formats,\n";
print OUT " unix_mapping_thread,\n";
foreach (sort keys %wgl_functions)
{
next if defined $manual_win_functions{$_};
@ -1197,6 +1200,7 @@ print OUT "extern NTSTATUS process_attach( void *args );\n";
print OUT "extern NTSTATUS thread_attach( void *args );\n";
print OUT "extern NTSTATUS process_detach( void *args );\n";
print OUT "extern NTSTATUS get_pixel_formats( void *args );\n";
print OUT "extern NTSTATUS mapping_thread( void *args );\n";
foreach (sort keys %wgl_functions)
{
next if defined $manual_win_functions{$_};
@ -1245,6 +1249,7 @@ print OUT " process_attach,\n";
print OUT " thread_attach,\n";
print OUT " process_detach,\n";
print OUT " get_pixel_formats,\n";
print OUT " mapping_thread,\n";
foreach (sort keys %wgl_functions)
{
next if defined $manual_win_functions{$_};
@ -1313,6 +1318,7 @@ print OUT " process_attach,\n";
print OUT " wow64_thread_attach,\n";
print OUT " wow64_process_detach,\n";
print OUT " wow64_get_pixel_formats,\n";
print OUT " mapping_thread,\n";
foreach (sort keys %wgl_functions)
{
next if defined $manual_win_functions{$_};

View file

@ -17938,6 +17938,14 @@ static void WINAPI glSetMultisamplefvAMD( GLenum pname, GLuint index, const GLfl
if ((status = UNIX_CALL( glSetMultisamplefvAMD, &args ))) WARN( "glSetMultisamplefvAMD returned %#lx\n", status );
}
static void WINAPI glSetPlacedAllocatorMESA( GLplacedMapMESA placedMap, GLplacedUnmapMESA placedUnmap )
{
struct glSetPlacedAllocatorMESA_params args = { .teb = NtCurrentTeb(), .placedMap = placedMap, .placedUnmap = placedUnmap };
NTSTATUS status;
TRACE( "placedMap %p, placedUnmap %p\n", placedMap, placedUnmap );
if ((status = UNIX_CALL( glSetPlacedAllocatorMESA, &args ))) WARN( "glSetPlacedAllocatorMESA returned %#lx\n", status );
}
static void WINAPI glShaderBinary( GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length )
{
struct glShaderBinary_params args = { .teb = NtCurrentTeb(), .count = count, .shaders = shaders, .binaryformat = binaryformat, .binary = binary, .length = length };
@ -26210,6 +26218,7 @@ const void *extension_procs[] =
glSetInvariantEXT,
glSetLocalConstantEXT,
glSetMultisamplefvAMD,
glSetPlacedAllocatorMESA,
glShaderBinary,
glShaderOp1EXT,
glShaderOp2EXT,

View file

@ -26,6 +26,7 @@ extern NTSTATUS process_attach( void *args );
extern NTSTATUS thread_attach( void *args );
extern NTSTATUS process_detach( void *args );
extern NTSTATUS get_pixel_formats( void *args );
extern NTSTATUS mapping_thread( void *args );
extern NTSTATUS wgl_wglCopyContext( void *args );
extern NTSTATUS wgl_wglCreateContext( void *args );
extern NTSTATUS wgl_wglDeleteContext( void *args );
@ -17836,6 +17837,14 @@ static NTSTATUS ext_glSetMultisamplefvAMD( void *args )
return STATUS_SUCCESS;
}
static NTSTATUS ext_glSetPlacedAllocatorMESA( void *args )
{
struct glSetPlacedAllocatorMESA_params *params = args;
const struct opengl_funcs *funcs = params->teb->glTable;
funcs->ext.p_glSetPlacedAllocatorMESA( params->placedMap, params->placedUnmap );
return STATUS_SUCCESS;
}
static NTSTATUS ext_glShaderBinary( void *args )
{
struct glShaderBinary_params *params = args;
@ -24201,6 +24210,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
thread_attach,
process_detach,
get_pixel_formats,
mapping_thread,
wgl_wglCopyContext,
wgl_wglCreateContext,
wgl_wglDeleteContext,
@ -26436,6 +26446,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
ext_glSetInvariantEXT,
ext_glSetLocalConstantEXT,
ext_glSetMultisamplefvAMD,
ext_glSetPlacedAllocatorMESA,
ext_glShaderBinary,
ext_glShaderOp1EXT,
ext_glShaderOp2EXT,
@ -75173,6 +75184,25 @@ static NTSTATUS wow64_ext_glSetMultisamplefvAMD( void *args )
return status;
}
static NTSTATUS wow64_ext_glSetPlacedAllocatorMESA( void *args )
{
struct
{
PTR32 teb;
PTR32 placedMap;
PTR32 placedUnmap;
} *params32 = args;
struct glSetPlacedAllocatorMESA_params params =
{
.teb = get_teb64(params32->teb),
.placedMap = ULongToPtr(params32->placedMap),
.placedUnmap = ULongToPtr(params32->placedUnmap),
};
NTSTATUS status;
status = ext_glSetPlacedAllocatorMESA( &params );
return status;
}
static NTSTATUS wow64_ext_glShaderBinary( void *args )
{
struct
@ -92300,6 +92330,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
wow64_thread_attach,
wow64_process_detach,
wow64_get_pixel_formats,
mapping_thread,
wow64_wgl_wglCopyContext,
wow64_wgl_wglCreateContext,
wow64_wgl_wglDeleteContext,
@ -94535,6 +94566,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
wow64_ext_glSetInvariantEXT,
wow64_ext_glSetLocalConstantEXT,
wow64_ext_glSetMultisamplefvAMD,
wow64_ext_glSetPlacedAllocatorMESA,
wow64_ext_glShaderBinary,
wow64_ext_glShaderOp1EXT,
wow64_ext_glShaderOp2EXT,
@ -97580,6 +97612,7 @@ static void null_glSetFragmentShaderConstantATI( GLuint dst, const GLfloat *valu
static void null_glSetInvariantEXT( GLuint id, GLenum type, const void *addr ) { }
static void null_glSetLocalConstantEXT( GLuint id, GLenum type, const void *addr ) { }
static void null_glSetMultisamplefvAMD( GLenum pname, GLuint index, const GLfloat *val ) { }
static void null_glSetPlacedAllocatorMESA( GLplacedMapMESA placedMap, GLplacedUnmapMESA placedUnmap ) { }
static void null_glShaderBinary( GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length ) { }
static void null_glShaderOp1EXT( GLenum op, GLuint res, GLuint arg1 ) { }
static void null_glShaderOp2EXT( GLenum op, GLuint res, GLuint arg1, GLuint arg2 ) { }
@ -100627,6 +100660,7 @@ struct opengl_funcs null_opengl_funcs =
null_glSetInvariantEXT,
null_glSetLocalConstantEXT,
null_glSetMultisamplefvAMD,
null_glSetPlacedAllocatorMESA,
null_glShaderBinary,
null_glShaderOp1EXT,
null_glShaderOp2EXT,
@ -101434,8 +101468,8 @@ struct opengl_funcs null_opengl_funcs =
},
};
const int extension_registry_size = 2694;
const struct registry_entry extension_registry[2694] =
const int extension_registry_size = 2695;
const struct registry_entry extension_registry[2695] =
{
{ "glAccumxOES", "GL_OES_fixed_point" },
{ "glAcquireKeyedMutexWin32EXT", "GL_EXT_win32_keyed_mutex" },
@ -103327,6 +103361,7 @@ const struct registry_entry extension_registry[2694] =
{ "glSetInvariantEXT", "GL_EXT_vertex_shader" },
{ "glSetLocalConstantEXT", "GL_EXT_vertex_shader" },
{ "glSetMultisamplefvAMD", "GL_AMD_sample_positions" },
{ "glSetPlacedAllocatorMESA", "GL_MESA_placed_allocation" },
{ "glShaderBinary", "GL_ARB_ES2_compatibility GL_VERSION_4_1" },
{ "glShaderOp1EXT", "GL_EXT_vertex_shader" },
{ "glShaderOp2EXT", "GL_EXT_vertex_shader" },

View file

@ -159,7 +159,14 @@ static BOOL has_extension( const char *list, const char *ext, size_t len )
return FALSE;
}
static GLubyte *filter_extensions_list( const char *extensions, const char *disabled )
static BOOL wow64_has_placed( const struct opengl_funcs *funcs )
{
const char *extensions = (const char *) funcs->gl.p_glGetString( GL_EXTENSIONS );
return !!strstr(extensions, "GL_MESA_placed_allocation");
}
static GLubyte *filter_extensions_list( TEB *teb, const char *extensions, const char *disabled )
{
const char *end;
char *p, *str;
@ -179,8 +186,8 @@ static GLubyte *filter_extensions_list( const char *extensions, const char *disa
p[end - extensions] = 0;
/* We do not support GL_MAP_PERSISTENT_BIT, and hence
* ARB_buffer_storage, on wow64. */
if (is_win64 && is_wow64() && (!strcmp( p, "GL_ARB_buffer_storage" ) || !strcmp( p, "GL_EXT_buffer_storage" )))
* ARB_buffer_storage, on wow64 without GL_MESA_placed_allocation */
if (is_win64 && is_wow64() && !wow64_has_placed(teb->glTable) && (!strcmp( p, "GL_ARB_buffer_storage" ) || !strcmp( p, "GL_EXT_buffer_storage" )))
{
TRACE( "-- %s (disabled due to wow64)\n", p );
}
@ -250,8 +257,8 @@ static GLuint *filter_extensions_index( TEB *teb, const char *disabled )
ext = (const char *)funcs->ext.p_glGetStringi( GL_EXTENSIONS, j );
/* We do not support GL_MAP_PERSISTENT_BIT, and hence
* ARB_buffer_storage, on wow64. */
if (is_win64 && is_wow64() && (!strcmp( ext, "GL_ARB_buffer_storage" ) || !strcmp( ext, "GL_EXT_buffer_storage" )))
* ARB_buffer_storage, on wow64 without GL_MESA_placed_allocation. */
if (is_win64 && is_wow64() && !wow64_has_placed(funcs) && (!strcmp( ext, "GL_ARB_buffer_storage" ) || !strcmp( ext, "GL_EXT_buffer_storage" )))
{
TRACE( "-- %s (disabled due to wow64)\n", ext );
disabled_index[i++] = j;
@ -377,7 +384,7 @@ static BOOL filter_extensions( TEB * teb, const char *extensions, GLubyte **exts
else disabled = "";
}
if (extensions && !*exts_list) *exts_list = filter_extensions_list( extensions, disabled );
if (extensions && !*exts_list) *exts_list = filter_extensions_list( teb, extensions, disabled );
if (!*disabled_exts) *disabled_exts = filter_extensions_index( teb, disabled );
return (exts_list && *exts_list) || *disabled_exts;
}
@ -449,9 +456,9 @@ static void wrap_glGetIntegerv( TEB *teb, GLenum pname, GLint *data )
if (pname == GL_NUM_EXTENSIONS && (disabled = disabled_extensions_index( teb )))
while (*disabled++ != ~0u) (*data)--;
if (is_win64 && is_wow64())
if (is_win64 && is_wow64() && !wow64_has_placed(funcs))
{
/* 4.4 depends on ARB_buffer_storage, which we don't support on wow64. */
/* 4.4 depends on ARB_buffer_storage, which we don't support on wow64 without GL_MESA_placed_allocation. */
if (pname == GL_MAJOR_VERSION && *data > 4)
*data = 4;
else if (pname == GL_MINOR_VERSION)
@ -479,7 +486,7 @@ static const GLubyte *wrap_glGetString( TEB *teb, GLenum name )
GLuint **disabled = &ptr->u.context->disabled_exts;
if (*extensions || filter_extensions( teb, (const char *)ret, extensions, disabled )) return *extensions;
}
else if (name == GL_VERSION && is_win64 && is_wow64())
else if (name == GL_VERSION && is_win64 && is_wow64() && !wow64_has_placed(funcs))
{
struct wgl_handle *ptr = get_current_context_ptr( teb );
int major, minor;
@ -650,6 +657,11 @@ static BOOL wrap_wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask )
return ret;
}
static void wow64_setup_placed(const struct opengl_funcs *funcs);
static void * WINE_GLAPI wow64_placed_map(GLuint size);
static void WINE_GLAPI wow64_placed_unmap(void *addr, GLuint size);
static ULONG_PTR zero_bits = 0;
static HGLRC wrap_wglCreateContext( HDC hdc )
{
HGLRC ret = 0;
@ -688,6 +700,8 @@ static BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc )
teb->glReserved1[1] = hdc;
teb->glCurrentRC = hglrc;
teb->glTable = (void *)ptr->funcs;
wow64_setup_placed(ptr->funcs);
}
}
else
@ -851,6 +865,8 @@ static BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc,
teb->glReserved1[1] = read_hdc;
teb->glCurrentRC = hglrc;
teb->glTable = (void *)ptr->funcs;
wow64_setup_placed(ptr->funcs);
}
}
else
@ -1896,9 +1912,9 @@ static NTSTATUS wow64_map_buffer( TEB *teb, GLint buffer, GLenum target, void *p
}
if (ULongToPtr(*ret = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
if (access & GL_MAP_PERSISTENT_BIT)
if (access & GL_MAP_PERSISTENT_BIT && !wow64_has_placed(teb->glTable))
{
FIXME( "GL_MAP_PERSISTENT_BIT not supported!\n" );
FIXME( "GL_MAP_PERSISTENT_BIT not supported! ptr=%p\n", ptr );
return STATUS_NOT_SUPPORTED;
}
@ -2243,6 +2259,154 @@ NTSTATUS wow64_ext_glUnmapNamedBufferEXT( void *args )
return wow64_gl_unmap_named_buffer( args, ext_glUnmapNamedBufferEXT );
}
static void wow64_setup_placed(const struct opengl_funcs *funcs)
{
SYSTEM_BASIC_INFORMATION info;
typeof(*funcs->ext.p_glSetPlacedAllocatorMESA) *p_set_placed_allocator;
NtQuerySystemInformation(SystemEmulationBasicInformation, &info, sizeof(info), NULL);
zero_bits = (ULONG_PTR)info.HighestUserAddress | 0x7fffffff;
if (!(p_set_placed_allocator = funcs->ext.p_glSetPlacedAllocatorMESA))
p_set_placed_allocator = (void *)funcs->wgl.p_wglGetProcAddress( "glSetPlacedAllocatorMESA" );
if (p_set_placed_allocator)
p_set_placed_allocator( wow64_placed_map, wow64_placed_unmap );
}
static int mapping_thread_stop;
static pthread_mutex_t mapping_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t mapping_cond = PTHREAD_COND_INITIALIZER;
static struct
{
enum
{
MAPPING_CMD_NONE = 0,
MAPPING_CMD_MAP,
MAPPING_CMD_UNMAP,
} cmd;
BOOL done;
union
{
struct
{
/* in */
unsigned int size;
/* out */
void *mapping;
} map;
struct
{
/* in */
void *mapping;
GLuint size;
} unmap;
};
} map_request;
static void * WINE_GLAPI wow64_placed_map(GLuint size)
{
void *mapping = NULL;
SIZE_T alloc_size = size;
if (!NtCurrentTeb())
{
/* offload to mapping_thread */
pthread_mutex_lock( &mapping_lock );
while (map_request.cmd != MAPPING_CMD_NONE)
pthread_cond_wait( &mapping_cond, &mapping_lock );
map_request.cmd = MAPPING_CMD_MAP;
map_request.map.size = size;
pthread_cond_broadcast( &mapping_cond );
while (!map_request.done)
pthread_cond_wait( &mapping_cond, &mapping_lock );
mapping = map_request.map.mapping;
map_request.cmd = MAPPING_CMD_NONE;
map_request.done = FALSE;
pthread_mutex_unlock( &mapping_lock );
pthread_cond_broadcast( &mapping_cond );
return mapping;
}
if (NtAllocateVirtualMemory(GetCurrentProcess(), &mapping, zero_bits, &alloc_size,
MEM_COMMIT, PAGE_READWRITE))
{
ERR("NtAllocateVirtualMemory failed\n");
return NULL;
}
TRACE("returning placed mapping %p size %x.\n", mapping, size);
return mapping;
}
static void WINE_GLAPI wow64_placed_unmap(void *addr, GLuint size)
{
SIZE_T alloc_size = 0;
if(!NtCurrentTeb())
{
/* offload to mapping_thread */
pthread_mutex_lock( &mapping_lock );
while (map_request.cmd != MAPPING_CMD_NONE)
pthread_cond_wait( &mapping_cond, &mapping_lock );
map_request.cmd = MAPPING_CMD_UNMAP;
map_request.unmap.mapping = addr;
map_request.unmap.size = size;
pthread_mutex_unlock( &mapping_lock );
pthread_cond_broadcast( &mapping_cond );
return;
}
TRACE("unmapping %p.\n", addr);
NtFreeVirtualMemory(GetCurrentProcess(), &addr, &alloc_size, MEM_RELEASE);
}
NTSTATUS mapping_thread (void *args )
{
if (!is_wow64())
return STATUS_SUCCESS;
while (!mapping_thread_stop)
{
pthread_mutex_lock( &mapping_lock );
while (map_request.cmd == MAPPING_CMD_NONE || map_request.done)
pthread_cond_wait( &mapping_cond, &mapping_lock );
if (map_request.cmd == MAPPING_CMD_MAP)
{
map_request.map.mapping = wow64_placed_map(map_request.map.size);
map_request.done = TRUE;
}
else if (map_request.cmd == MAPPING_CMD_UNMAP)
{
wow64_placed_unmap(map_request.unmap.mapping, map_request.unmap.size);
map_request.cmd = MAPPING_CMD_NONE;
}
pthread_cond_broadcast( &mapping_cond );
pthread_mutex_unlock( &mapping_lock );
}
return STATUS_SUCCESS;
}
NTSTATUS wow64_thread_attach( void *args )
{
return thread_attach( get_teb64( (ULONG_PTR)args ));
@ -2252,6 +2416,8 @@ NTSTATUS wow64_process_detach( void *args )
{
NTSTATUS status;
mapping_thread_stop = 1;
if ((status = process_detach( NULL ))) return status;
free( wow64_strings );

View file

@ -18658,6 +18658,13 @@ struct glSetMultisamplefvAMD_params
const GLfloat *val;
};
struct glSetPlacedAllocatorMESA_params
{
TEB *teb;
GLplacedMapMESA placedMap;
GLplacedUnmapMESA placedUnmap;
};
struct glShaderBinary_params
{
TEB *teb;
@ -25343,6 +25350,7 @@ enum unix_funcs
unix_thread_attach,
unix_process_detach,
unix_get_pixel_formats,
unix_mapping_thread,
unix_wglCopyContext,
unix_wglCreateContext,
unix_wglDeleteContext,
@ -27578,6 +27586,7 @@ enum unix_funcs
unix_glSetInvariantEXT,
unix_glSetLocalConstantEXT,
unix_glSetMultisamplefvAMD,
unix_glSetPlacedAllocatorMESA,
unix_glShaderBinary,
unix_glShaderOp1EXT,
unix_glShaderOp2EXT,

File diff suppressed because it is too large Load diff

View file

@ -1888,6 +1888,12 @@ static NTSTATUS WINAPI call_gl_debug_message_callback( void *args, ULONG size )
return STATUS_SUCCESS;
}
static DWORD WINAPI mapping_thread(LPVOID param)
{
UNIX_CALL( mapping_thread, NULL );
return 0;
}
/***********************************************************************
* OpenGL initialisation routine
*/
@ -1909,6 +1915,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
return FALSE;
}
if (NtCurrentTeb()->WowTebOffset)
CreateThread(NULL, 0, mapping_thread, NULL, 0, NULL);
/* fallthrough */
case DLL_THREAD_ATTACH:
if ((status = UNIX_CALL( thread_attach, NtCurrentTeb() )))

2
include/wine/wgl.h generated
View file

@ -48,6 +48,8 @@ typedef void *GLDEBUGPROCAMD;
typedef unsigned short GLhalfNV;
typedef GLintptr GLvdpauSurfaceNV;
typedef void *GLVULKANPROCNV;
typedef void *( *GLplacedMapMESA)(GLuint size);
typedef void ( *GLplacedUnmapMESA)(void *mapping, GLuint size);
struct _GPU_DEVICE {
DWORD cb;
CHAR DeviceName[32];

View file

@ -7,7 +7,7 @@
#define WINE_GLAPI
#endif
#define WINE_WGL_DRIVER_VERSION 28
#define WINE_WGL_DRIVER_VERSION 29
struct wgl_context;
struct wgl_pbuffer;
@ -2290,6 +2290,7 @@ struct opengl_funcs
void (WINE_GLAPI *p_glSetInvariantEXT)( GLuint id, GLenum type, const void *addr );
void (WINE_GLAPI *p_glSetLocalConstantEXT)( GLuint id, GLenum type, const void *addr );
void (WINE_GLAPI *p_glSetMultisamplefvAMD)( GLenum pname, GLuint index, const GLfloat *val );
void (WINE_GLAPI *p_glSetPlacedAllocatorMESA)( GLplacedMapMESA placedMap, GLplacedUnmapMESA placedUnmap );
void (WINE_GLAPI *p_glShaderBinary)( GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length );
void (WINE_GLAPI *p_glShaderOp1EXT)( GLenum op, GLuint res, GLuint arg1 );
void (WINE_GLAPI *p_glShaderOp2EXT)( GLenum op, GLuint res, GLuint arg1, GLuint arg2 );