This provides a less performant alternative to the Vulkan-based persistent memory mapping used on wow64, so use it as a fallback on older drivers when available.
From: Jacek Caban jacek@codeweavers.com
--- dlls/opengl32/make_opengl | 10 +++++-- dlls/opengl32/unix_private.h | 5 ++-- dlls/opengl32/unix_thunks.c | 55 +++++++++++++++++++++++++++--------- dlls/opengl32/unix_wgl.c | 25 +++++++++------- 4 files changed, 67 insertions(+), 28 deletions(-)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 011b3d21878..61eafbec33e 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -443,6 +443,7 @@ sub generate_unix_thunk($$$$) my $manual_wow64_wrapper = $is_wow64 && defined $manual_wow64_wrappers{$name}; my $need_wrap = $manual_wow64_wrapper || needs_wrapper( $name, $func ); my $need_lock = $func_ret =~ /HGLRC|HPBUFFERARB/; + my $need_funcs = !$need_wrap; my $teb = $is_wow64 ? "teb" : "params->teb"; my $ret_stat = "return STATUS_SUCCESS;"; my $invalidation = ""; @@ -544,9 +545,12 @@ sub generate_unix_thunk($$$$) if (defined $wow64_invalidate_buffer{$name}) { $need_lock = 1; + $need_funcs = 1; + $input_conv .= " struct buffer *buffer;\n"; $invalidation .= $name =~ /NamedBuffer/ - ? " invalidate_buffer_name( $teb, params->buffer );\n" - : " invalidate_buffer_target( $teb, params->target );\n"; + ? " buffer = invalidate_buffer_name( $teb, params->buffer );\n" + : " buffer = invalidate_buffer_target( $teb, params->target );\n"; + $output_conv .= " if (buffer) free_buffer( funcs, buffer );\n"; } $ret .= " TEB *teb = get_teb64( params->teb );\n" if $need_wrap || !$use_dc; } @@ -575,7 +579,7 @@ sub generate_unix_thunk($$$$) $ret .= " const struct opengl_funcs *funcs = get_dc_funcs( $param );\n"; $ret .= " if (!funcs || !funcs->p_$name) return STATUS_NOT_IMPLEMENTED;\n"; } - elsif (!$need_wrap) + elsif ($need_funcs) { $ret .= " const struct opengl_funcs *funcs = $teb->glTable;\n"; } diff --git a/dlls/opengl32/unix_private.h b/dlls/opengl32/unix_private.h index 9ced126e3ab..138578210f8 100644 --- a/dlls/opengl32/unix_private.h +++ b/dlls/opengl32/unix_private.h @@ -71,8 +71,9 @@ static inline TEB *get_teb64( ULONG teb32 ) return (TEB *)((char *)teb32_ptr + teb32_ptr->WowTebOffset); }
-extern void invalidate_buffer_name( TEB *teb, GLuint name ); -extern void invalidate_buffer_target( TEB *teb, GLenum target ); +extern struct buffer *invalidate_buffer_name( TEB *teb, GLuint name ); +extern struct buffer *invalidate_buffer_target( TEB *teb, GLenum target ); +extern void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ); extern NTSTATUS return_wow64_string( const void *str, PTR32 *wow64_str );
#endif diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 19596967d23..7d4c00edbe9 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -37981,12 +37981,14 @@ static NTSTATUS wow64_ext_glBufferAttachMemoryNV( void *args ) GLuint64 offset; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_target( teb, params->target ); + buffer = invalidate_buffer_target( teb, params->target ); funcs->p_glBufferAttachMemoryNV( params->target, params->memory, params->offset ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -38001,12 +38003,14 @@ static NTSTATUS wow64_ext_glBufferData( void *args ) GLenum usage; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_target( teb, params->target ); + buffer = invalidate_buffer_target( teb, params->target ); funcs->p_glBufferData( params->target, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->usage ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -38021,12 +38025,14 @@ static NTSTATUS wow64_ext_glBufferDataARB( void *args ) GLenum usage; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_target( teb, params->target ); + buffer = invalidate_buffer_target( teb, params->target ); funcs->p_glBufferDataARB( params->target, (GLsizeiptrARB)ULongToPtr(params->size), ULongToPtr(params->data), params->usage ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -38107,11 +38113,14 @@ static NTSTATUS wow64_ext_glBufferStorage( void *args ) GLbitfield flags; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; + const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_target( teb, params->target ); + buffer = invalidate_buffer_target( teb, params->target ); wow64_glBufferStorage( teb, params->target, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->flags ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -38127,12 +38136,14 @@ static NTSTATUS wow64_ext_glBufferStorageExternalEXT( void *args ) GLbitfield flags; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_target( teb, params->target ); + buffer = invalidate_buffer_target( teb, params->target ); funcs->p_glBufferStorageExternalEXT( params->target, (GLintptr)ULongToPtr(params->offset), (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->clientBuffer), params->flags ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -38147,12 +38158,14 @@ static NTSTATUS wow64_ext_glBufferStorageMemEXT( void *args ) GLuint64 offset; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_target( teb, params->target ); + buffer = invalidate_buffer_target( teb, params->target ); funcs->p_glBufferStorageMemEXT( params->target, (GLsizeiptr)ULongToPtr(params->size), params->memory, params->offset ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -59295,12 +59308,14 @@ static NTSTATUS wow64_ext_glNamedBufferAttachMemoryNV( void *args ) GLuint64 offset; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_name( teb, params->buffer ); + buffer = invalidate_buffer_name( teb, params->buffer ); funcs->p_glNamedBufferAttachMemoryNV( params->buffer, params->memory, params->offset ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -59315,12 +59330,14 @@ static NTSTATUS wow64_ext_glNamedBufferData( void *args ) GLenum usage; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_name( teb, params->buffer ); + buffer = invalidate_buffer_name( teb, params->buffer ); funcs->p_glNamedBufferData( params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->usage ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -59335,12 +59352,14 @@ static NTSTATUS wow64_ext_glNamedBufferDataEXT( void *args ) GLenum usage; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_name( teb, params->buffer ); + buffer = invalidate_buffer_name( teb, params->buffer ); funcs->p_glNamedBufferDataEXT( params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->usage ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -59408,11 +59427,14 @@ static NTSTATUS wow64_ext_glNamedBufferStorage( void *args ) GLbitfield flags; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; + const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_name( teb, params->buffer ); + buffer = invalidate_buffer_name( teb, params->buffer ); wow64_glNamedBufferStorage( teb, params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->flags ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -59427,11 +59449,14 @@ static NTSTATUS wow64_ext_glNamedBufferStorageEXT( void *args ) GLbitfield flags; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; + const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_name( teb, params->buffer ); + buffer = invalidate_buffer_name( teb, params->buffer ); wow64_glNamedBufferStorageEXT( teb, params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->flags ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -59447,12 +59472,14 @@ static NTSTATUS wow64_ext_glNamedBufferStorageExternalEXT( void *args ) GLbitfield flags; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_name( teb, params->buffer ); + buffer = invalidate_buffer_name( teb, params->buffer ); funcs->p_glNamedBufferStorageExternalEXT( params->buffer, (GLintptr)ULongToPtr(params->offset), (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->clientBuffer), params->flags ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
@@ -59467,12 +59494,14 @@ static NTSTATUS wow64_ext_glNamedBufferStorageMemEXT( void *args ) GLuint64 offset; } *params = args; TEB *teb = get_teb64( params->teb ); + struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; pthread_mutex_lock( &wgl_lock ); - invalidate_buffer_name( teb, params->buffer ); + buffer = invalidate_buffer_name( teb, params->buffer ); funcs->p_glNamedBufferStorageMemEXT( params->buffer, (GLsizeiptr)ULongToPtr(params->size), params->memory, params->offset ); pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); + if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; }
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 1d9e1573a7e..2ab0cdfb10c 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -398,7 +398,7 @@ static int compare_buffer_name( const void *key, const struct rb_entry *entry ) return memcmp( key, &buffer->name, sizeof(buffer->name) ); }
-static void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ) +void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ) { if (buffer->vk_memory) { @@ -2323,20 +2323,21 @@ static struct buffer *get_named_buffer( TEB *teb, GLuint name ) return NULL; }
-void invalidate_buffer_name( TEB *teb, GLuint name ) +struct buffer *invalidate_buffer_name( TEB *teb, GLuint name ) { struct buffer *buffer = get_named_buffer( teb, name ); - struct context *ctx; - - if (!buffer || !(ctx = get_current_context( teb, NULL, NULL ))) return; - rb_remove( &ctx->buffers->map, &buffer->entry ); - free_buffer( teb->glTable, buffer ); + if (buffer) + { + struct context *ctx = get_current_context( teb, NULL, NULL ); + rb_remove( &ctx->buffers->map, &buffer->entry ); + } + return buffer; }
-void invalidate_buffer_target( TEB *teb, GLenum target ) +struct buffer *invalidate_buffer_target( TEB *teb, GLenum target ) { GLuint name = get_target_name( teb, target ); - if (name) invalidate_buffer_name( teb, name ); + return name ? invalidate_buffer_name( teb, name ) : NULL; }
static struct buffer *get_target_buffer( TEB *teb, GLenum target ) @@ -2605,12 +2606,16 @@ static GLbitfield map_range_flags_from_map_flags( GLenum flags ) void wow64_glDeleteBuffers( TEB *teb, GLsizei n, const GLuint *buffers ) { const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer; GLsizei i;
pthread_mutex_lock( &wgl_lock );
funcs->p_glDeleteBuffers( n, buffers ); - for (i = 0; i < n; i++) invalidate_buffer_name( teb, buffers[i] ); + for (i = 0; i < n; i++) + { + if ((buffer = invalidate_buffer_name( teb, buffers[i] ))) free_buffer( funcs, buffer ); + }
pthread_mutex_unlock( &wgl_lock ); }
From: Jacek Caban jacek@codeweavers.com
--- dlls/opengl32/unix_wgl.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 2ab0cdfb10c..edcf846994e 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -2346,6 +2346,11 @@ static struct buffer *get_target_buffer( TEB *teb, GLenum target ) return name ? get_named_buffer( teb, name ) : NULL; }
+static BOOL use_driver_buffer_map( struct buffer *buffer ) +{ + return !buffer || !buffer->vk_memory; +} + static BOOL buffer_vm_alloc( TEB *teb, struct buffer *buffer, SIZE_T size ) { if (buffer->vm_size >= size) return TRUE; @@ -2715,7 +2720,7 @@ static void *wow64_gl_map_buffer( TEB *teb, GLenum target, GLenum access, PFN_gl
pthread_mutex_lock( &wgl_lock ); buffer = get_target_buffer( teb, target ); - if (!buffer || !buffer->vk_memory) ptr = gl_map_buffer64( target, access ); + if (use_driver_buffer_map( buffer )) ptr = gl_map_buffer64( target, access ); ptr = wow64_map_buffer( teb, buffer, target, 0, 0, 0, range_access, ptr ); pthread_mutex_unlock( &wgl_lock ); return ptr; @@ -2741,7 +2746,7 @@ void *wow64_glMapBufferRange( TEB *teb, GLenum target, GLintptr offset, GLsizeip
pthread_mutex_lock( &wgl_lock ); buffer = get_target_buffer( teb, target ); - if (!buffer || !buffer->vk_memory) ptr = funcs->p_glMapBufferRange( target, offset, length, access ); + if (use_driver_buffer_map( buffer )) ptr = funcs->p_glMapBufferRange( target, offset, length, access ); ptr = wow64_map_buffer( teb, buffer, target, 0, offset, length, access, ptr ); pthread_mutex_unlock( &wgl_lock ); return ptr; @@ -2755,7 +2760,7 @@ static void *wow64_gl_map_named_buffer( TEB *teb, GLuint name, GLenum access, PF
pthread_mutex_lock( &wgl_lock ); buffer = get_named_buffer( teb, name ); - if (!buffer || !buffer->vk_memory) ptr = gl_map_named_buffer64( name, access ); + if (use_driver_buffer_map( buffer )) ptr = gl_map_named_buffer64( name, access ); ptr = wow64_map_buffer( teb, buffer, 0, name, 0, 0, range_access, ptr ); pthread_mutex_unlock( &wgl_lock ); return ptr; @@ -2781,7 +2786,7 @@ static void *wow64_gl_map_named_buffer_range( TEB *teb, GLuint name, GLintptr of
pthread_mutex_lock( &wgl_lock ); buffer = get_named_buffer( teb, name ); - if (!buffer || !buffer->vk_memory) ptr = gl_map_named_buffer_range64( name, offset, length, access ); + if (use_driver_buffer_map( buffer )) ptr = gl_map_named_buffer_range64( name, offset, length, access ); ptr = wow64_map_buffer( teb, buffer, 0, name, offset, length, access, ptr ); pthread_mutex_unlock( &wgl_lock ); return ptr; @@ -2832,7 +2837,7 @@ static GLboolean wow64_unmap_target_buffer( TEB *teb, GLenum target, PFN_glUnmap
pthread_mutex_lock( &wgl_lock ); if ((buffer = get_target_buffer( teb, target ))) ret = wow64_unmap_buffer( teb, buffer ); - if (!buffer || !buffer->vk_memory) ret = gl_unmap( target ); + if (use_driver_buffer_map( buffer )) ret = gl_unmap( target ); pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2856,7 +2861,7 @@ static GLboolean wow64_gl_unmap_named_buffer( TEB *teb, GLuint name, PFN_glUnmap
pthread_mutex_lock( &wgl_lock ); if ((buffer = get_named_buffer( teb, name ))) ret = wow64_unmap_buffer( teb, buffer ); - if (!buffer || !buffer->vk_memory) ret = gl_unmap( name ); + if (use_driver_buffer_map( buffer )) ret = gl_unmap( name ); pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2880,7 +2885,7 @@ void wow64_glFlushMappedBufferRange( TEB *teb, GLenum target, GLintptr offset, G
pthread_mutex_lock( &wgl_lock ); if ((buffer = get_target_buffer( teb, target ))) flush_buffer( teb, buffer, offset, length ); - if (!buffer || !buffer->vk_memory) funcs->p_glFlushMappedBufferRange( target, offset, length ); + if (use_driver_buffer_map( buffer )) funcs->p_glFlushMappedBufferRange( target, offset, length ); pthread_mutex_unlock( &wgl_lock ); }
@@ -2891,7 +2896,7 @@ void wow64_glFlushMappedNamedBufferRange( TEB *teb, GLuint name, GLintptr offset
pthread_mutex_lock( &wgl_lock ); if ((buffer = get_named_buffer( teb, name ))) flush_buffer( teb, buffer, offset, length ); - if (!buffer || !buffer->vk_memory) funcs->p_glFlushMappedNamedBufferRange( name, offset, length ); + if (use_driver_buffer_map( buffer )) funcs->p_glFlushMappedNamedBufferRange( name, offset, length ); pthread_mutex_unlock( &wgl_lock ); }
@@ -2902,7 +2907,7 @@ void wow64_glFlushMappedNamedBufferRangeEXT( TEB *teb, GLuint name, GLintptr off
pthread_mutex_lock( &wgl_lock ); if ((buffer = get_named_buffer( teb, name ))) flush_buffer( teb, buffer, offset, length ); - if (!buffer || !buffer->vk_memory) funcs->p_glFlushMappedNamedBufferRangeEXT( name, offset, length ); + if (use_driver_buffer_map( buffer )) funcs->p_glFlushMappedNamedBufferRangeEXT( name, offset, length ); pthread_mutex_unlock( &wgl_lock ); }
From: Jacek Caban jacek@codeweavers.com
This provides a less performant alternative to the Vulkan-based persistent memory mapping used on wow64, so use it as a fallback on older drivers when available. --- dlls/opengl32/unix_wgl.c | 49 ++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-)
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index edcf846994e..63109e4ee2b 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -146,6 +146,7 @@ struct context GLenum gl_error; /* wrapped GL error */ const char **extension_array; /* array of supported extensions */ size_t extension_count; /* size of supported extensions */ + BOOL use_pinned_memory; /* use GL_AMD_pinned_memory to emulate persistent maps */
/* semi-stub state tracker for wglCopyContext */ GLbitfield used; /* context state used bits */ @@ -171,6 +172,7 @@ struct buffer size_t copy_length; void *vm_ptr; SIZE_T vm_size; + void *pinned_ptr;
/* members of Vulkan-backed buffer storages */ struct vk_device *vk_device; @@ -406,6 +408,7 @@ void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ) buffer->vk_device->p_vkFreeMemory( buffer->vk_device->vk_device, buffer->vk_memory, NULL ); } if (buffer->gl_memory) funcs->p_glDeleteMemoryObjectsEXT( 1, &buffer->gl_memory ); + if (buffer->pinned_ptr) NtFreeVirtualMemory( GetCurrentProcess(), &buffer->pinned_ptr, &buffer->size, MEM_RELEASE ); if (buffer->vm_ptr) NtFreeVirtualMemory( GetCurrentProcess(), &buffer->vm_ptr, &buffer->vm_size, MEM_RELEASE ); free( buffer ); } @@ -1290,7 +1293,8 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD ctx->extension_array = extensions; ctx->extension_count = count;
- if (is_win64 && ctx->buffers && !initialize_vk_device( teb, ctx )) + if (is_win64 && ctx->buffers && !initialize_vk_device( teb, ctx ) + && !(ctx->use_pinned_memory = is_extension_supported( ctx, "GL_AMD_pinned_memory" ))) { if (ctx->major_version > 4 || (ctx->major_version == 4 && ctx->minor_version > 3)) { @@ -2348,7 +2352,7 @@ static struct buffer *get_target_buffer( TEB *teb, GLenum target )
static BOOL use_driver_buffer_map( struct buffer *buffer ) { - return !buffer || !buffer->vk_memory; + return !buffer || (!buffer->vk_memory && !buffer->pinned_ptr); }
static BOOL buffer_vm_alloc( TEB *teb, struct buffer *buffer, SIZE_T size ) @@ -2428,7 +2432,32 @@ static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint nam VkResult vr;
if (!(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) return NULL; - if (!(vk_device = ctx->buffers->vk_device) || !vk_device->vk_device) return NULL; + if ((!(vk_device = ctx->buffers->vk_device) || !vk_device->vk_device) && !ctx->use_pinned_memory) return NULL; + + if (!(buffer = calloc( 1, sizeof(*buffer) ))) return NULL; + buffer->name = buffer_name; + buffer->flags = flags; + buffer->size = size; + buffer->vk_device = vk_device; + + if (ctx->use_pinned_memory) + { + if (!buffer_vm_alloc( teb, buffer, size )) return NULL; + buffer->pinned_ptr = buffer->vm_ptr; + buffer->vm_ptr = NULL; + buffer->vm_size = 0; + if (data) memcpy( buffer->pinned_ptr, data, size ); + + /* FIXME: we may interfere with GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD if the + * application uses it as well. Unlike other targets, there’s no way to query + * the currently bound target, so we’d need to track it ourselves if we want + * to support it. */ + funcs->p_glBindBuffer( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, buffer_name ); + funcs->p_glBufferData( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, size, buffer->pinned_ptr, GL_DYNAMIC_COPY ); + rb_put( &ctx->buffers->map, &buffer->name, &buffer->entry ); + TRACE( "created buffer %p with pinned memory %p\n", buffer, buffer->pinned_ptr ); + return buffer; + }
if (flags & GL_CLIENT_STORAGE_BIT) desired_type &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; memory_type = find_vk_memory_type( vk_device, desired_type, type_mask ); @@ -2437,16 +2466,11 @@ static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint nam if (memory_type == -1) { WARN( "Could not find memory type\n" ); + free_buffer( funcs, buffer ); return NULL; } alloc_info.memoryTypeIndex = memory_type;
- if (!(buffer = calloc( 1, sizeof(*buffer) ))) return NULL; - buffer->name = buffer_name; - buffer->flags = flags; - buffer->size = size; - buffer->vk_device = vk_device; - vr = vk_device->p_vkAllocateMemory( vk_device->vk_device, &alloc_info, NULL, &buffer->vk_memory ); if (vr) { @@ -2543,6 +2567,13 @@ static void *wow64_map_buffer( TEB *teb, struct buffer *buffer, GLenum target, G return buffer->map_ptr; }
+ if (buffer && buffer->pinned_ptr) + { + buffer->map_ptr = (char *)buffer->pinned_ptr + offset; + TRACE( "returning pinned ptr %p\n", buffer->map_ptr ); + return buffer->map_ptr; + } + if (!ptr) return NULL;
if (!buffer)
From: Jacek Caban jacek@codeweavers.com
--- dlls/opengl32/unix_wgl.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 63109e4ee2b..0e63f0415b4 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -2847,14 +2847,11 @@ static BOOL wow64_unmap_buffer( TEB *teb, struct buffer *buffer ) unmap_vk_buffer( buffer ); }
- if (buffer->host_ptr != buffer->map_ptr) + if (buffer->map_ptr && buffer->copy_length) { - if (buffer->copy_length) - { - TRACE( "Copying %#zx from wow64 buffer %p to buffer %p\n", buffer->copy_length, - buffer->map_ptr, buffer->host_ptr ); - memcpy( buffer->host_ptr, buffer->map_ptr, buffer->copy_length ); - } + TRACE( "Copying %#zx from wow64 buffer %p to buffer %p\n", buffer->copy_length, + buffer->map_ptr, buffer->host_ptr ); + memcpy( buffer->host_ptr, buffer->map_ptr, buffer->copy_length ); }
buffer->host_ptr = buffer->map_ptr = NULL;
Rémi Bernon (@rbernon) commented about dlls/opengl32/unix_wgl.c:
size_t copy_length; void *vm_ptr; SIZE_T vm_size;
- void *pinned_ptr;
Why do we need a different pointer from vm_ptr?
Rémi Bernon (@rbernon) commented about dlls/opengl32/unix_wgl.c:
unmap_vk_buffer( buffer ); }
- if (buffer->host_ptr != buffer->map_ptr)
- {
if (buffer->copy_length)
- if (buffer->map_ptr && buffer->copy_length)
This could even be `if (buffer->copy_length)` don't you think?
On Thu Nov 27 13:48:32 2025 +0000, Rémi Bernon wrote:
Why do we need a different pointer from vm_ptr?
With this implementation, we don’t need a separate pointer, but we do need a flag.
We could potentially do a bit better for cases where a buffer storage created with the persistent flag is then used with old-style maps. Technically, that would be more correct, but handling it would require working around issues such as `glMapBufferRange` not being supported on pinned memory. For now, I used the same code path that we use for Vulkan, but this representation would allow implementing that in the future.