From: Jacek Caban jacek@codeweavers.com
--- dlls/opengl32/unix_wgl.c | 497 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 461 insertions(+), 36 deletions(-)
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index df7159df732..7019acbbe37 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -42,6 +42,7 @@
#include "wine/debug.h" #include "wine/rbtree.h" +#include "wine/vulkan_driver.h"
WINE_DEFAULT_DEBUG_CHANNEL(opengl);
@@ -124,6 +125,7 @@ struct buffers { unsigned int ref; struct rb_tree map; + struct vk_device *vk_device; };
struct context @@ -169,6 +171,27 @@ struct buffer size_t copy_length; void *vm_ptr; SIZE_T vm_size; + + /* members of Vulkan-backed buffer storages */ + struct vk_device *vk_device; + VkDeviceMemory vk_memory; + GLuint gl_memory; + GLbitfield flags; +}; + +struct vk_device +{ + struct rb_entry entry; + VkDevice vk_device; + GLubyte uuid[GL_UUID_SIZE_EXT]; + VkPhysicalDeviceMemoryProperties memory_properties; + + PFN_vkAllocateMemory p_vkAllocateMemory; + PFN_vkFlushMappedMemoryRanges p_vkFlushMappedMemoryRanges; + PFN_vkFreeMemory p_vkFreeMemory; + PFN_vkGetMemoryFdKHR p_vkGetMemoryFdKHR; + PFN_vkMapMemory2KHR p_vkMapMemory2KHR; + PFN_vkUnmapMemory2KHR p_vkUnmapMemory2KHR; };
struct wgl_handle @@ -191,6 +214,17 @@ static unsigned int handle_count;
static ULONG_PTR zero_bits;
+static const struct vulkan_funcs *vk_funcs; +static VkInstance vk_instance; + +static int vk_device_cmp( const void *key, const struct rb_entry *entry ) +{ + struct vk_device *vk_device = RB_ENTRY_VALUE( entry, struct vk_device, entry ); + return memcmp( key, &vk_device->uuid, sizeof(vk_device->uuid) ); +} + +struct rb_tree vk_devices = { vk_device_cmp }; + static struct context *context_from_wgl_context( struct wgl_context *context ) { return CONTAINING_RECORD( context, struct context, base ); @@ -342,26 +376,46 @@ static BOOL copy_context_attributes( TEB *teb, const struct opengl_funcs *funcs, return dst->used != -1 && src->used != -1; }
+static void unmap_vk_buffer( struct buffer *buffer ) +{ + VkMemoryUnmapInfoKHR unmap_info = + { + .sType = VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR, + .memory = buffer->vk_memory, + .flags = VK_MEMORY_UNMAP_RESERVE_BIT_EXT, + }; + VkResult vr; + + vr = buffer->vk_device->p_vkUnmapMemory2KHR( buffer->vk_device->vk_device, &unmap_info ); + if (vr) ERR( "VkMemoryUnmapInfoKHR failed: %x\n", vr); +} + static int compare_buffer_name( const void *key, const struct rb_entry *entry ) { struct buffer *buffer = RB_ENTRY_VALUE( entry, struct buffer, entry ); return memcmp( key, &buffer->name, sizeof(buffer->name) ); }
-static void free_buffer( struct buffer *buffer ) +static void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ) { + if (buffer->vk_memory) + { + if (buffer->map_ptr) unmap_vk_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->vm_ptr) NtFreeVirtualMemory( GetCurrentProcess(), &buffer->vm_ptr, &buffer->vm_size, MEM_RELEASE ); free( buffer ); }
-static void release_buffers( struct buffers *buffers ) +static void release_buffers( const struct opengl_funcs *funcs, struct buffers *buffers ) { struct buffer *buffer, *next;
if (--buffers->ref) return;
RB_FOR_EACH_ENTRY_DESTRUCTOR( buffer, next, &buffers->map, struct buffer, entry ) - free_buffer( buffer ); + free_buffer( funcs, buffer ); free( buffers ); }
@@ -384,7 +438,7 @@ static void update_handle_context( TEB *teb, HGLRC handle, struct wgl_handle *pt } if (shared && shared->buffers) { - release_buffers( ctx->buffers ); + release_buffers( funcs, ctx->buffers ); ctx->buffers = shared->buffers; ctx->buffers->ref++; } @@ -947,6 +1001,175 @@ BOOL wrap_wglCopyContext( TEB *teb, HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ) return ret; }
+static BOOL initialize_vk_device( TEB *teb, struct context *ctx ) +{ + struct opengl_funcs *funcs = teb->glTable; + VkPhysicalDevice *vk_physical_devices = NULL; + struct vk_device *vk_device = NULL; + GLint uuid_count = 0, i, j; + VkResult vr; + + static PFN_vkCreateDevice p_vkCreateDevice; + static PFN_vkEnumeratePhysicalDevices p_vkEnumeratePhysicalDevices; + static PFN_vkGetPhysicalDeviceMemoryProperties p_vkGetPhysicalDeviceMemoryProperties; + static PFN_vkGetPhysicalDeviceProperties2 p_vkGetPhysicalDeviceProperties2; + + if (ctx->buffers->vk_device) return TRUE; + if (!is_extension_supported( ctx, "GL_EXT_memory_object_fd" )) + { + TRACE( "GL_EXT_memory_object_fd is not supported\n" ); + return FALSE; + } + + if (!vk_funcs) + { + PFN_vkCreateInstance p_vkCreateInstance; + static const char *instance_extensions[] = + { + "VK_KHR_get_physical_device_properties2", + }; + VkApplicationInfo app_info = + { + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pEngineName = "Wine WGL", + .engineVersion = 1, + }; + VkInstanceCreateInfo create_info = + { + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pApplicationInfo = &app_info, + .ppEnabledExtensionNames = instance_extensions, + .enabledExtensionCount = ARRAYSIZE(instance_extensions), + }; + + if (!(vk_funcs = __wine_get_vulkan_driver( WINE_VULKAN_DRIVER_VERSION ))) return FALSE; + if (!vk_funcs->p_vkGetInstanceProcAddr + || !(p_vkCreateInstance = (void *)vk_funcs->p_vkGetInstanceProcAddr( NULL, "vkCreateInstance" ))) + return FALSE; + if ((vr = p_vkCreateInstance( &create_info, NULL, &vk_instance ))) + { + WARN( "Failed to create a Vulkan instance, vr %d.\n", vr ); + return FALSE; + } +#define GET_VK_FUNC(name) p_##name = (void *)vk_funcs->p_vkGetInstanceProcAddr( vk_instance, #name ) + GET_VK_FUNC( vkCreateDevice ); + GET_VK_FUNC( vkEnumeratePhysicalDevices ); + GET_VK_FUNC( vkGetPhysicalDeviceMemoryProperties ); + GET_VK_FUNC( vkGetPhysicalDeviceProperties2 ); +#undef GET_VK_FUNC + } + if (!vk_instance) return FALSE; + +#define GET_GL_FUNC(name) if (!funcs->p_##name) funcs->p_##name = (void *)funcs->p_wglGetProcAddress( #name ) + GET_GL_FUNC( glBufferStorageMemEXT ); + GET_GL_FUNC( glCreateMemoryObjectsEXT ); + GET_GL_FUNC( glDeleteMemoryObjectsEXT ); + GET_GL_FUNC( glGetUnsignedBytei_vEXT ); + GET_GL_FUNC( glImportMemoryFdEXT ); + GET_GL_FUNC( glNamedBufferStorageMemEXT ); +#undef GET_GL_FUNC + + funcs->p_glGetIntegerv( GL_NUM_DEVICE_UUIDS_EXT, &uuid_count ); + for (i = 0; i < uuid_count; i++) + { + GLubyte uuid[GL_UUID_SIZE_EXT]; + struct rb_entry *entry; + uint32_t count; + + funcs->p_glGetUnsignedBytei_vEXT( GL_DEVICE_UUID_EXT, i, uuid ); + if ((entry = rb_get( &vk_devices, uuid ))) + { + vk_device = RB_ENTRY_VALUE( entry, struct vk_device, entry ); + if (!vk_device->vk_device) continue; /* known incompatible device */ + TRACE( "Found existing device %p for uuid %s\n", vk_device, debugstr_guid( (const GUID *)uuid ) ); + ctx->buffers->vk_device = vk_device; + free( vk_physical_devices ); + return TRUE; + } + + if (!(vk_device = calloc( 1, sizeof(*vk_device) ))) return FALSE; + memcpy( vk_device->uuid, uuid, sizeof(uuid) ); + rb_put( &vk_devices, uuid, &vk_device->entry ); + + if (!vk_physical_devices) + { + vr = p_vkEnumeratePhysicalDevices( vk_instance, &count, NULL ); + if (!vr && count) + { + vk_physical_devices = calloc( count, sizeof(*vk_physical_devices) ); + vr = p_vkEnumeratePhysicalDevices( vk_instance, &count, vk_physical_devices ); + } + if (vr || !count) + { + WARN( "Could not get vulkan physical devices: %d\n", vr ); + continue; + } + } + + for (j = 0; j < count; j++) + { + static const char *device_extensions[] = + { + "VK_KHR_external_memory", + "VK_KHR_external_memory_fd", + "VK_EXT_map_memory_placed", + "VK_KHR_map_memory2", + }; + VkPhysicalDeviceIDProperties id_props = + { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES, + }; + VkPhysicalDeviceProperties2 props = + { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &id_props, + }; + float priority = 0.0f; + VkDeviceQueueCreateInfo queue_info = + { + .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, + .queueCount = 1, + .pQueuePriorities = &priority, + }; + VkDeviceCreateInfo device_info = + { + .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, + .queueCreateInfoCount = 1, + .pQueueCreateInfos = &queue_info, + .enabledExtensionCount = ARRAYSIZE(device_extensions), + .ppEnabledExtensionNames = device_extensions, + }; + + p_vkGetPhysicalDeviceProperties2( vk_physical_devices[j], &props ); + if (memcmp( id_props.deviceUUID, uuid, sizeof(uuid) )) continue; + + p_vkGetPhysicalDeviceMemoryProperties( vk_physical_devices[j], &vk_device->memory_properties ); + vr = p_vkCreateDevice( vk_physical_devices[j], &device_info, NULL, &vk_device->vk_device ); + if (vr) + { + WARN( "Could not create vulkan device: %d\n", vr ); + continue; + } + +#define GET_VK_FUNC(name) vk_device->p_##name = (void *)vk_funcs->p_vkGetDeviceProcAddr( vk_device->vk_device, #name ) + GET_VK_FUNC( vkAllocateMemory ); + GET_VK_FUNC( vkFreeMemory ); + GET_VK_FUNC( vkGetMemoryFdKHR ); + GET_VK_FUNC( vkMapMemory2KHR ); + GET_VK_FUNC( vkUnmapMemory2KHR ); + GET_VK_FUNC( vkFlushMappedMemoryRanges ); +#undef GET_VK_FUNC + TRACE( "Created %p device for uuid %s\n", vk_device, debugstr_guid((const GUID *)uuid) ); + free( vk_physical_devices ); + return TRUE; + } + } + + free( vk_physical_devices ); + WARN( "Could not find compatible Vulkan device\n" ); + return FALSE; +} + static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HDC draw_hdc, HDC read_hdc, HGLRC hglrc, struct context *ctx ) { @@ -1030,8 +1253,14 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD
for (i = 0; legacy_extensions[i]; i++) extensions[count++] = legacy_extensions[i]; qsort( extensions, count, sizeof(*extensions), string_array_cmp ); + ctx->extension_array = extensions; + ctx->extension_count = count;
- if (is_win64 && is_wow64()) + if (is_win64 && is_wow64() + && (ctx->major_version > 4 || (ctx->major_version == 4 && ctx->minor_version > 3) + || is_extension_supported( ctx, "GL_ARB_buffer_storage" ) + || is_extension_supported( ctx, "GL_EXT_buffer_storage" )) + && !initialize_vk_device( teb, ctx )) { if (ctx->major_version > 4 || (ctx->major_version == 4 && ctx->minor_version > 3)) { @@ -1050,11 +1279,9 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD } extensions[j++] = ext; } - count = j; + ctx->extension_count = j; }
- ctx->extension_array = extensions; - ctx->extension_count = count; if (TRACE_ON(opengl)) for (i = 0; i < count; i++) TRACE( "++ %s\n", extensions[i] ); }
@@ -1317,6 +1544,7 @@ HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC share, const int else { context->buffers->ref = 1; + context->buffers->vk_device = NULL; rb_init( &context->buffers->map, compare_buffer_name ); } } @@ -2058,7 +2286,7 @@ void invalidate_buffer_name( TEB *teb, GLuint name )
if (!buffer || !(ctx = get_current_context( teb, NULL, NULL ))) return; rb_remove( &ctx->buffers->map, &buffer->entry ); - free_buffer( buffer ); + free_buffer( teb->glTable, buffer ); }
void invalidate_buffer_target( TEB *teb, GLenum target ) @@ -2093,10 +2321,166 @@ static BOOL buffer_vm_alloc( TEB *teb, struct buffer *buffer, SIZE_T size ) return TRUE; }
-static PTR32 wow64_map_buffer( TEB *teb, GLenum target, GLuint name, GLintptr offset, +static void flush_buffer( TEB *teb, struct buffer *buffer, size_t offset, size_t length ) +{ + VkMappedMemoryRange memory_range = + { + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = buffer->vk_memory, + .offset = (char *)buffer->map_ptr - (char *)buffer->host_ptr + offset, + .size = length, + }; + VkResult vr; + + if (!buffer->vk_memory) return; + + vr = buffer->vk_device->p_vkFlushMappedMemoryRanges( buffer->vk_device->vk_device, 1, &memory_range ); + if (vr) ERR( "vkFlushMappedMemoryRanges failed: %x\n", vr ); +} + +static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint name, size_t size, const void *data, GLbitfield flags ) +{ + VkExportMemoryAllocateInfo export_alloc = + { + .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, + }; + VkMemoryAllocateInfo alloc_info = + { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = &export_alloc, + .allocationSize = size, + }; + VkMemoryGetFdInfoKHR fd_info = + { + .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, + }; + struct opengl_funcs *funcs = teb->glTable; + GLuint buffer_name = name ? name : get_target_name( teb, target ); + struct context *ctx = get_current_context( teb, NULL, NULL ); + struct vk_device *vk_device; + struct buffer *buffer; + uint32_t i; + int fd; + VkResult vr; + + if (!(vk_device = ctx->buffers->vk_device) || !vk_device->vk_device) return NULL; + + /* FIXME: For now, just use any host-visible coherent memory type. We can do better and take into account GL flags. */ + for (i = 0; i < vk_device->memory_properties.memoryTypeCount; i++) + { + static const uint32_t mask = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + if ((vk_device->memory_properties.memoryTypes[i].propertyFlags & mask) == mask) break; + } + if (i == vk_device->memory_properties.memoryTypeCount) + { + WARN( "Could not find memory type\n" ); + return NULL; + } + alloc_info.memoryTypeIndex = i; + + 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) + { + ERR( "vkAllocateMemory failed: %d\n", vr ); + free_buffer( funcs, buffer ); + return NULL; + } + + if (data) + { + VkMemoryMapInfoKHR map_info = + { + .sType = VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR, + .memory = buffer->vk_memory, + .size = VK_WHOLE_SIZE, + }; + VkMemoryUnmapInfoKHR unmap_info = + { + .sType = VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR, + .memory = buffer->vk_memory, + }; + void *ptr; + + vr = vk_device->p_vkMapMemory2KHR( vk_device->vk_device, &map_info, &ptr ); + if (vr) + { + ERR( "vkMapMemory2KHR failed: %d\n", vr ); + free_buffer( funcs, buffer ); + return NULL; + } + + memcpy( ptr, data, size ); + vk_device->p_vkUnmapMemory2KHR( vk_device->vk_device, &unmap_info ); + } + + fd_info.memory = buffer->vk_memory; + vr = vk_device->p_vkGetMemoryFdKHR( vk_device->vk_device, &fd_info, &fd ); + if (vr) + { + ERR( "vkGetMemoryFdKHR failed: %d\n", vr ); + free_buffer( funcs, buffer ); + return NULL; + } + + funcs->p_glCreateMemoryObjectsEXT( 1, &buffer->gl_memory ); + funcs->p_glImportMemoryFdEXT( buffer->gl_memory, size, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd ); + if (name) + funcs->p_glNamedBufferStorageMemEXT( buffer->name, size, buffer->gl_memory, 0 ); + else + funcs->p_glBufferStorageMemEXT( target, size, buffer->gl_memory, 0 ); + rb_put( &ctx->buffers->map, &buffer->name, &buffer->entry ); + TRACE( "created buffer_storage %p\n", buffer ); + return buffer; +} + +static PTR32 wow64_map_buffer( TEB *teb, struct buffer *buffer, GLenum target, GLuint name, GLintptr offset, size_t length, GLbitfield access, void *ptr ) { - struct buffer *buffer = get_target_buffer( teb, target ); + if (buffer && buffer->map_ptr) + { + set_gl_error( teb, GL_INVALID_OPERATION ); + return 0; + } + + if (buffer && buffer->vk_memory) + { + VkMemoryMapPlacedInfoEXT placed_info = + { + .sType = VK_STRUCTURE_TYPE_MEMORY_MAP_PLACED_INFO_EXT, + }; + VkMemoryMapInfoKHR map_info = + { + .sType = VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR, + .flags = VK_MEMORY_MAP_PLACED_BIT_EXT, + .pNext = &placed_info, + .memory = buffer->vk_memory, + .size = VK_WHOLE_SIZE, + }; + VkResult vr; + struct context *ctx = get_current_context( teb, NULL, NULL ); + struct vk_device *vk_device = ctx->buffers->vk_device; + + if (!buffer_vm_alloc( teb, buffer, buffer->size )) return 0; + placed_info.pPlacedAddress = buffer->vm_ptr; + vr = vk_device->p_vkMapMemory2KHR( vk_device->vk_device, &map_info, &buffer->host_ptr ); + if (vr) + { + ERR( "vkMapMemory2KHR failed: %d\n", vr ); + return 0; + } + assert( buffer->host_ptr == buffer->vm_ptr ); + buffer->map_ptr = (char *)buffer->vm_ptr + offset; + TRACE( "returning vk mapping %p\n", buffer->map_ptr ); + return PtrToUlong( buffer->map_ptr ); + }
if (!ptr) return 0;
@@ -2179,22 +2563,34 @@ void wow64_glDeleteBuffers( TEB *teb, GLsizei n, const GLuint *buffers ) void wow64_glBufferStorage( TEB *teb, GLenum target, GLsizeiptr size, const void *data, GLbitfield flags ) { const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer = NULL;
- funcs->p_glBufferStorage( target, size, data, flags ); + if (flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) + buffer = create_buffer_storage( teb, target, 0, size, data, flags ); + + if (!buffer) funcs->p_glBufferStorage( target, size, data, flags ); }
void wow64_glNamedBufferStorage( TEB *teb, GLuint name, GLsizeiptr size, const void *data, GLbitfield flags ) { const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer = NULL; + + if (flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) + buffer = create_buffer_storage( teb, 0, name, size, data, flags );
- funcs->p_glNamedBufferStorage( name, size, data, flags ); + if (!buffer) funcs->p_glNamedBufferStorage( name, size, data, flags ); }
void wow64_glNamedBufferStorageEXT( TEB *teb, GLuint name, GLsizeiptr size, const void *data, GLbitfield flags ) { const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer = NULL;
- funcs->p_glNamedBufferStorageEXT( name, size, data, flags ); + if (flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) + buffer = create_buffer_storage( teb, 0, name, size, data, flags ); + + if (!buffer) funcs->p_glNamedBufferStorageEXT( name, size, data, flags ); }
static BOOL wow64_gl_get_buffer_pointer_v( TEB *teb, GLenum target, GLuint name, GLenum pname, PTR32 *wow_ptr ) @@ -2254,12 +2650,14 @@ void wow64_glGetNamedBufferPointervEXT( TEB *teb, GLuint buffer, GLenum pname, P static PTR32 wow64_gl_map_buffer( TEB *teb, GLenum target, GLenum access, PFN_glMapBuffer gl_map_buffer64 ) { GLbitfield range_access = map_range_flags_from_map_flags( access ); - void *ptr; - PTR32 ret; + struct buffer *buffer; + void *ptr = NULL; + PTR32 ret ;
pthread_mutex_lock( &wgl_lock ); - ptr = gl_map_buffer64( target, access ); - ret = wow64_map_buffer( teb, target, 0, 0, 0, range_access, ptr ); + buffer = get_target_buffer( teb, target ); + if (!buffer || !buffer->vk_memory) ptr = gl_map_buffer64( target, access ); + ret = wow64_map_buffer( teb, buffer, target, 0, 0, 0, range_access, ptr ); pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2279,12 +2677,14 @@ PTR32 wow64_glMapBufferARB( TEB *teb, GLenum target, GLenum access ) PTR32 wow64_glMapBufferRange( TEB *teb, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access ) { const struct opengl_funcs *funcs = teb->glTable; - void *ptr; + struct buffer *buffer; + void *ptr = NULL; PTR32 ret;
pthread_mutex_lock( &wgl_lock ); - ptr = funcs->p_glMapBufferRange( target, offset, length, access ); - ret = wow64_map_buffer( teb, target, 0, offset, length, access, ptr ); + buffer = get_target_buffer( teb, target ); + if (!buffer || !buffer->vk_memory) ptr = funcs->p_glMapBufferRange( target, offset, length, access ); + ret = wow64_map_buffer( teb, buffer, target, 0, offset, length, access, ptr ); pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2292,12 +2692,14 @@ PTR32 wow64_glMapBufferRange( TEB *teb, GLenum target, GLintptr offset, GLsizeip static PTR32 wow64_gl_map_named_buffer( TEB *teb, GLuint name, GLenum access, PFN_glMapNamedBuffer gl_map_named_buffer64 ) { GLbitfield range_access = map_range_flags_from_map_flags( access ); - void *ptr; + struct buffer *buffer; + void *ptr = NULL; PTR32 ret;
pthread_mutex_lock( &wgl_lock ); - ptr = gl_map_named_buffer64( name, access ); - ret = wow64_map_buffer( teb, 0, name, 0, 0, range_access, ptr ); + buffer = get_named_buffer( teb, name ); + if (!buffer || !buffer->vk_memory) ptr = gl_map_named_buffer64( name, access ); + ret = wow64_map_buffer( teb, buffer, 0, name, 0, 0, range_access, ptr ); pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2317,12 +2719,14 @@ PTR32 wow64_glMapNamedBufferEXT( TEB *teb, GLuint buffer, GLenum access ) static NTSTATUS wow64_gl_map_named_buffer_range( TEB *teb, GLuint name, GLintptr offset, GLsizeiptr length, GLbitfield access, PFN_glMapNamedBufferRange gl_map_named_buffer_range64 ) { - void *ptr; + struct buffer *buffer; + void *ptr = NULL; PTR32 ret;
pthread_mutex_lock( &wgl_lock ); - ptr = gl_map_named_buffer_range64( name, offset, length, access ); - ret = wow64_map_buffer( teb, 0, name, offset, length, access, ptr ); + buffer = get_named_buffer( teb, name ); + if (!buffer || !buffer->vk_memory) ptr = gl_map_named_buffer_range64( name, offset, length, access ); + ret = wow64_map_buffer( teb, buffer, 0, name, offset, length, access, ptr ); pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2339,9 +2743,17 @@ PTR32 wow64_glMapNamedBufferRangeEXT( TEB *teb, GLuint buffer, GLintptr offset, return wow64_gl_map_named_buffer_range( teb, buffer, offset, length, access, funcs->p_glMapNamedBufferRangeEXT ); }
-static void wow64_unmap_buffer( struct buffer *buffer ) +static BOOL wow64_unmap_buffer( TEB *teb, struct buffer *buffer ) { - if (!buffer->host_ptr) return; + if (buffer->vk_memory) + { + if (!buffer->map_ptr) + { + set_gl_error( teb, GL_INVALID_OPERATION ); + return FALSE; + } + unmap_vk_buffer( buffer ); + }
if (buffer->host_ptr != buffer->map_ptr) { @@ -2354,6 +2766,7 @@ static void wow64_unmap_buffer( struct buffer *buffer ) }
buffer->host_ptr = buffer->map_ptr = NULL; + return TRUE; }
static GLboolean wow64_unmap_target_buffer( TEB *teb, GLenum target, PFN_glUnmapBuffer gl_unmap ) @@ -2362,8 +2775,8 @@ static GLboolean wow64_unmap_target_buffer( TEB *teb, GLenum target, PFN_glUnmap GLboolean ret;
pthread_mutex_lock( &wgl_lock ); - if ((buffer = get_target_buffer( teb, target ))) wow64_unmap_buffer( buffer ); - ret = gl_unmap( target ); + if ((buffer = get_target_buffer( teb, target ))) ret = wow64_unmap_buffer( teb, buffer ); + if (!buffer || !buffer->vk_memory) ret = gl_unmap( target ); pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2386,8 +2799,8 @@ static GLboolean wow64_gl_unmap_named_buffer( TEB *teb, GLuint name, PFN_glUnmap GLboolean ret;
pthread_mutex_lock( &wgl_lock ); - if ((buffer = get_named_buffer( teb, name ))) wow64_unmap_buffer( buffer ); - ret = gl_unmap( name ); + if ((buffer = get_named_buffer( teb, name ))) ret = wow64_unmap_buffer( teb, buffer ); + if (!buffer || !buffer->vk_memory) ret = gl_unmap( name ); pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2407,22 +2820,34 @@ GLboolean wow64_glUnmapNamedBufferEXT( TEB *teb, GLuint buffer ) void wow64_glFlushMappedBufferRange( TEB *teb, GLenum target, GLintptr offset, GLsizeiptr length ) { const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer;
- funcs->p_glFlushMappedBufferRange( target, offset, length ); + 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 ); + pthread_mutex_unlock( &wgl_lock ); }
void wow64_glFlushMappedNamedBufferRange( TEB *teb, GLuint name, GLintptr offset, GLsizeiptr length ) { const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer;
- funcs->p_glFlushMappedNamedBufferRange( name, offset, length ); + 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 ); + pthread_mutex_unlock( &wgl_lock ); }
void wow64_glFlushMappedNamedBufferRangeEXT( TEB *teb, GLuint name, GLintptr offset, GLsizeiptr length ) { const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer;
- funcs->p_glFlushMappedNamedBufferRangeEXT( name, offset, length ); + 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 ); + pthread_mutex_unlock( &wgl_lock ); }
NTSTATUS wow64_thread_attach( void *args )