My hardware is Ryzen 7 4700u with the integrated graphics
Flatout (Direct3D 9): 3 fps to 40 fps (renders correctly) Unigine Heaven (OpenGL): ~17 fps (renders correctly) Unigine Heaven (Direct3D 9): 20-30 fps (renders correctly) Unigine Heaven (Direct3D 11): 20-30 fps as well (renders correctly) Elder Scrolls IV (Direct3D 9): 20 fps (broken intro videos, ingame rendering looks correct, old mapping code works just fine in the intro videos)
These numbers are from my memory, I will update them with the more accurate numbers when I get home.
From: Etaash Mathamsetty 45927311+Etaash-mathamsetty@users.noreply.github.com
--- dlls/opengl32/unix_wgl.c | 113 +++++++++++++++++++++++++++++---------- dlls/opengl32/wgl.c | 2 +- 2 files changed, 85 insertions(+), 30 deletions(-)
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 453a9824046..e60a772fd93 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -1852,8 +1852,40 @@ static void unmap_named_buffer( TEB *teb, GLint buffer ) if (func) func( buffer ); }
-static NTSTATUS wow64_map_buffer( TEB *teb, GLint buffer, GLenum target, void *ptr, SIZE_T size, - GLbitfield access, PTR32 *ret ) +static void gl_buffer_sub_data( TEB *teb, GLenum target, GLintptr offset, GLsizeiptr size, const void *data ) +{ + const struct opengl_funcs *funcs = teb->glTable; + typeof(*funcs->ext.p_glBufferSubData) *func; + if (!(func = funcs->ext.p_glBufferSubData)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glBufferSubData" ); + if (func) func( target, offset, size, data ); +} + +static void gl_named_buffer_sub_data( TEB *teb, GLint buffer, GLintptr offset, GLsizeiptr size, const void *data ) +{ + const struct opengl_funcs *funcs = teb->glTable; + typeof(*funcs->ext.p_glNamedBufferSubData) *func; + if (!(func = funcs->ext.p_glNamedBufferSubData)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glNamedBufferSubData" ); + if (func) func( buffer, offset, size, data ); +} + +static void gl_get_buffer_sub_data( TEB *teb, GLenum target, GLintptr offset, GLsizeiptr size, void *data ) +{ + const struct opengl_funcs *funcs = teb->glTable; + typeof(*funcs->ext.p_glBufferSubData) *func; + if (!(func = funcs->ext.p_glBufferSubData)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetBufferSubData" ); + if (func) func( target, offset, size, data ); +} + +static void gl_get_named_buffer_sub_data( TEB *teb, GLint buffer, GLintptr offset, GLsizeiptr size, void *data ) +{ + const struct opengl_funcs *funcs = teb->glTable; + typeof(*funcs->ext.p_glGetNamedBufferSubData) *func; + if (!(func = funcs->ext.p_glGetNamedBufferSubData)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetNamedBufferSubData" ); + if (func) func( buffer, offset, size, data ); +} + +static NTSTATUS wow64_map_buffer( TEB *teb, GLint buffer, GLenum target, void **ptr, GLintptr offset, SIZE_T size, + GLbitfield access, PTR32 *ret, NTSTATUS (*gl_map_buffer64)(void *), void *params ) { static unsigned int once;
@@ -1865,15 +1897,20 @@ static NTSTATUS wow64_map_buffer( TEB *teb, GLint buffer, GLenum target, void *p FIXME( "Doing a copy of a mapped buffer (expect performance issues)\n" );
TRACE( "Copying %#zx from buffer at %p to wow64 buffer %p\n", size, ptr, UlongToPtr(*ret) ); - memcpy( UlongToPtr(*ret), ptr, size ); + if(buffer) + gl_get_named_buffer_sub_data( teb, buffer, offset, size, UlongToPtr(*ret) ); + else + gl_get_buffer_sub_data( teb, target, offset, size, UlongToPtr(*ret) ); }
+ gl_map_buffer64(params); + /* save the wow64 pointer in the buffer data, we'll overwrite it on unmap */ - *(PTR32 *)ptr = (UINT_PTR)*ret; + memcpy(UlongToPtr(*ret + size), *ptr, sizeof(PTR32)); + memcpy(*ptr, ret, sizeof(PTR32)); return STATUS_SUCCESS; }
- if (ULongToPtr(*ret = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */ if (access & GL_MAP_PERSISTENT_BIT) { FIXME( "GL_MAP_PERSISTENT_BIT not supported!\n" ); @@ -1881,13 +1918,18 @@ static NTSTATUS wow64_map_buffer( TEB *teb, GLint buffer, GLenum target, void *p }
if (!size) size = buffer ? get_named_buffer_param( teb, buffer, GL_BUFFER_SIZE ) : get_buffer_param( teb, target, GL_BUFFER_SIZE ); - if ((PTR32)size != size) return STATUS_NO_MEMORY; /* overflow */ + if (size < sizeof(PTR32)) { FIXME( "Buffer too small for metadata!\n" ); return STATUS_BUFFER_TOO_SMALL; }
+ /* store extra 4 bytes to store original data at ret[size] */ + size += sizeof(PTR32); + + if ((PTR32)size != size) return STATUS_NO_MEMORY; /* overflow */ + *ret = size; return STATUS_INVALID_ADDRESS; } @@ -1905,17 +1947,23 @@ static GLbitfield map_range_flags_from_map_flags( GLenum flags ) } }
-static NTSTATUS wow64_unmap_buffer( void *ptr, SIZE_T size, GLbitfield access ) +static NTSTATUS wow64_unmap_buffer( TEB *teb, void *ptr, GLenum target, GLint buffer, GLintptr offset, + SIZE_T size, GLbitfield access, NTSTATUS (*gl_unmap_buffer64)(void *), void *params) { - void *wow_ptr; + void *wow_ptr = UlongToPtr(*(PTR32 *)ptr); + + /* overwrite the stored pointer with the correct data */ + memcpy(ptr, (char*)wow_ptr + size, sizeof(PTR32));
- if (ULongToPtr(PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */ + gl_unmap_buffer64( params );
- wow_ptr = UlongToPtr(*(PTR32 *)ptr); if (access & GL_MAP_WRITE_BIT) { TRACE( "Copying %#zx from wow64 buffer %p to buffer %p\n", size, wow_ptr, ptr ); - memcpy( ptr, wow_ptr, size ); + if(buffer) + gl_named_buffer_sub_data( teb, buffer, offset, size, wow_ptr ); + else + gl_buffer_sub_data( teb, target, offset, size, wow_ptr ); }
return STATUS_INVALID_ADDRESS; @@ -1943,7 +1991,7 @@ static NTSTATUS wow64_gl_get_buffer_pointer_v( void *args, NTSTATUS (*get_buffer
if ((status = get_buffer_pointer_v64( ¶ms ))) return status; if (params.pname != GL_BUFFER_MAP_POINTER) return STATUS_NOT_IMPLEMENTED; - if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */ + *wow_ptr = ptr[0]; return STATUS_SUCCESS; } @@ -1980,7 +2028,7 @@ static NTSTATUS wow64_gl_get_named_buffer_pointer_v( void *args, NTSTATUS (*gl_g
if ((status = gl_get_named_buffer_pointer_v64( ¶ms ))) return status; if (params.pname != GL_BUFFER_MAP_POINTER) return STATUS_NOT_IMPLEMENTED; - if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */ + *wow_ptr = ptr[0]; return STATUS_SUCCESS; } @@ -2014,10 +2062,10 @@ static NTSTATUS wow64_gl_map_buffer( void *args, NTSTATUS (*gl_map_buffer64)(voi
/* already mapped, we're being called again with a wow64 pointer */ if (params32->ret) params.ret = get_buffer_pointer( params.teb, params.target ); - else if ((status = gl_map_buffer64( ¶ms ))) return status;
- status = wow64_map_buffer( params.teb, 0, params.target, params.ret, 0, - map_range_flags_from_map_flags( params.access ), ¶ms32->ret ); + status = wow64_map_buffer( params.teb, 0, params.target, ¶ms.ret, 0, 0, + map_range_flags_from_map_flags( params.access ), ¶ms32->ret, + gl_map_buffer64, ¶ms ); if (!status || status == STATUS_INVALID_ADDRESS) return status;
unmap_buffer( params.teb, params.target ); @@ -2057,9 +2105,10 @@ NTSTATUS wow64_ext_glMapBufferRange( void *args )
/* already mapped, we're being called again with a wow64 pointer */ if (params32->ret) params.ret = (char *)get_buffer_pointer( params.teb, params.target ); - else if ((status = ext_glMapBufferRange( ¶ms ))) return status;
- status = wow64_map_buffer( params.teb, 0, params.target, params.ret, params.length, params.access, ¶ms32->ret ); + status = wow64_map_buffer( params.teb, 0, params.target, ¶ms.ret, params.offset, + params.length, params.access, ¶ms32->ret, + ext_glMapBufferRange, ¶ms ); if (!status || status == STATUS_INVALID_ADDRESS) return status;
unmap_buffer( params.teb, params.target ); @@ -2085,10 +2134,10 @@ static NTSTATUS wow64_gl_map_named_buffer( void *args, NTSTATUS (*gl_map_named_b
/* already mapped, we're being called again with a wow64 pointer */ if (params32->ret) params.ret = get_named_buffer_pointer( params.teb, params.buffer ); - else if ((status = gl_map_named_buffer64( ¶ms ))) return status;
- status = wow64_map_buffer( params.teb, params.buffer, 0, params.ret, 0, - map_range_flags_from_map_flags( params.access ), ¶ms32->ret ); + status = wow64_map_buffer( params.teb, params.buffer, 0, ¶ms.ret, 0, 0, + map_range_flags_from_map_flags( params.access ), ¶ms32->ret, + gl_map_named_buffer64, ¶ms ); if (!status || status == STATUS_INVALID_ADDRESS) return status;
unmap_named_buffer( params.teb, params.buffer ); @@ -2128,9 +2177,10 @@ static NTSTATUS wow64_gl_map_named_buffer_range( void *args, NTSTATUS (*gl_map_n
/* already mapped, we're being called again with a wow64 pointer */ if (params32->ret) params.ret = get_named_buffer_pointer( params.teb, params.buffer ); - else if ((status = gl_map_named_buffer_range64( ¶ms ))) return status;
- status = wow64_map_buffer( params.teb, params.buffer, 0, params.ret, params.length, params.access, ¶ms32->ret ); + status = wow64_map_buffer( params.teb, params.buffer, 0, ¶ms.ret, params.offset, + params.length, params.access, ¶ms32->ret, + gl_map_named_buffer_range64, ¶ms ); if (!status || status == STATUS_INVALID_ADDRESS) return status;
unmap_named_buffer( params.teb, params.buffer ); @@ -2166,9 +2216,12 @@ static NTSTATUS wow64_gl_unmap_buffer( void *args, NTSTATUS (*gl_unmap_buffer64)
if (!(ptr = get_buffer_pointer( params.teb, params.target ))) return STATUS_SUCCESS;
- status = wow64_unmap_buffer( ptr, get_buffer_param( params.teb, params.target, GL_BUFFER_MAP_LENGTH ), - get_buffer_param( params.teb, params.target, GL_BUFFER_ACCESS_FLAGS ) ); - gl_unmap_buffer64( ¶ms ); + status = wow64_unmap_buffer( params.teb, ptr, params.target, 0, + get_buffer_param( params.teb, params.target, GL_BUFFER_MAP_OFFSET ), + get_buffer_param( params.teb, params.target, GL_BUFFER_MAP_LENGTH ), + get_buffer_param( params.teb, params.target, GL_BUFFER_ACCESS_FLAGS ), + gl_unmap_buffer64, ¶ms ); + params32->ret = params.ret;
return status; @@ -2203,9 +2256,11 @@ static NTSTATUS wow64_gl_unmap_named_buffer( void *args, NTSTATUS (*gl_unmap_nam
if (!(ptr = get_named_buffer_pointer( params.teb, params.buffer ))) return STATUS_SUCCESS;
- status = wow64_unmap_buffer( ptr, get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_MAP_LENGTH ), - get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_ACCESS_FLAGS ) ); - gl_unmap_named_buffer64( ¶ms ); + status = wow64_unmap_buffer( params.teb, ptr, 0, params.buffer, + get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_MAP_OFFSET ), + get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_MAP_LENGTH ), + get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_ACCESS_FLAGS ), + gl_unmap_named_buffer64, ¶ms ); params32->ret = params.ret;
return status; diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index c02436f1675..fc1ab7bdffc 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -1128,7 +1128,7 @@ void * WINAPI glMapBufferRange( GLenum target, GLintptr offset, GLsizeiptr lengt if (status == STATUS_INVALID_ADDRESS) { TRACE( "Unable to map wow64 buffer directly, using copy buffer!\n" ); - if (!(args.ret = _aligned_malloc( length, 16 ))) status = STATUS_NO_MEMORY; + if (!(args.ret = _aligned_malloc( (SIZE_T)args.ret, 16 ))) status = STATUS_NO_MEMORY; else if (!(status = UNIX_CALL( glMapBufferRange, &args ))) return args.ret; _aligned_free( args.ret ); }
heaven running on it:
![image](/uploads/e1919fb362fe197cb4d8f2d8d3dfb73c/image.png)