Implement pinned memory for ATI where buffer regions are slow

Stanislaw Halik sthalik at misaki.pl
Sun Feb 17 00:17:29 CST 2013


This one should be better. Sorry about indentation. Much, much FPS, and 
supposedly no loss of functionality.

Where to go from here?

-sh
-------------- next part --------------
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index e9a07a5..606e5be 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -666,38 +666,46 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined
 
     /* This potentially invalidates the element array buffer binding, but the
      * caller always takes care of this. */
-    GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
-    checkGLcall("glBindBufferARB");
-    if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
-    {
-        GLbitfield mapflags;
-        mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
-        if (flags & WINED3D_BUFFER_DISCARD)
-            mapflags |= GL_MAP_INVALIDATE_BUFFER_BIT;
-        if (flags & WINED3D_BUFFER_NOSYNC)
-            mapflags |= GL_MAP_UNSYNCHRONIZED_BIT;
-        map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
-                    This->resource.size, mapflags));
-        checkGLcall("glMapBufferRange");
-    }
-    else
-    {
-        if (This->flags & WINED3D_BUFFER_APPLESYNC)
-        {
-            DWORD syncflags = 0;
-            if (flags & WINED3D_BUFFER_DISCARD)
-                syncflags |= WINED3D_MAP_DISCARD;
-            if (flags & WINED3D_BUFFER_NOSYNC)
-                syncflags |= WINED3D_MAP_NOOVERWRITE;
-            buffer_sync_apple(This, syncflags, gl_info);
-        }
-        map = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_WRITE_ONLY_ARB));
-        checkGLcall("glMapBufferARB");
-    }
+    
+    if (gl_info->supported[ATI_PINNED_MEMORY])
+    {
+    	map = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->resource.size + RESOURCE_ALIGNMENT);
+	GL_EXTCALL(glBindBufferARB(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, This->buffer_object));
+	GL_EXTCALL(glBufferDataARB(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, This->resource.size, map, GL_STREAM_COPY));
+    } else {
+    	GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
+    	checkGLcall("glBindBufferARB");
+	    if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+	    {
+		GLbitfield mapflags;
+		mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
+		if (flags & WINED3D_BUFFER_DISCARD)
+		    mapflags |= GL_MAP_INVALIDATE_BUFFER_BIT;
+		if (flags & WINED3D_BUFFER_NOSYNC)
+		    mapflags |= GL_MAP_UNSYNCHRONIZED_BIT;
+		map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
+			    This->resource.size, mapflags));
+		checkGLcall("glMapBufferRange");
+	    }
+	    else
+	    {
+		if (This->flags & WINED3D_BUFFER_APPLESYNC)
+		{
+		    DWORD syncflags = 0;
+		    if (flags & WINED3D_BUFFER_DISCARD)
+			syncflags |= WINED3D_MAP_DISCARD;
+		    if (flags & WINED3D_BUFFER_NOSYNC)
+			syncflags |= WINED3D_MAP_NOOVERWRITE;
+		    buffer_sync_apple(This, syncflags, gl_info);
+		}
+		map = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_WRITE_ONLY_ARB));
+		checkGLcall("glMapBufferARB");
+	    }
+	}
     if (!map)
     {
-        ERR("Failed to map opengl buffer\n");
-        return;
+	ERR("Failed to map opengl buffer\n");
+	return;
     }
 
     while (This->modified_areas)
@@ -705,22 +713,33 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined
         This->modified_areas--;
         start = This->maps[This->modified_areas].offset;
         len = This->maps[This->modified_areas].size;
-
-        memcpy(map + start, This->resource.allocatedMemory + start, len);
-
-        if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
-        {
-            GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len));
-            checkGLcall("glFlushMappedBufferRange");
-        }
-        else if (This->flags & WINED3D_BUFFER_FLUSH)
-        {
-            GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len));
-            checkGLcall("glFlushMappedBufferRangeAPPLE");
-        }
+	
+	    memcpy(map + start, This->resource.allocatedMemory + start, len);
+
+  	    if (!gl_info->supported[ATI_PINNED_MEMORY])
+	    {
+		    if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+		    {
+			GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len));
+			checkGLcall("glFlushMappedBufferRange");
+		    }
+		    else if (This->flags & WINED3D_BUFFER_FLUSH)
+		    {
+			GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len));
+			checkGLcall("glFlushMappedBufferRangeAPPLE");
+		    }
+	    }
+    }
+    if (gl_info->supported[ATI_PINNED_MEMORY])
+    {
+	GL_EXTCALL(glBindBufferARB(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0));
+	HeapFree(GetProcessHeap(), 0, map);
+    }
+    else
+    {
+	    GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint));
+	    checkGLcall("glUnmapBufferARB");
     }
-    GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint));
-    checkGLcall("glUnmapBufferARB");
 }
 
 /* Do not call while under the GL lock. */
@@ -1030,7 +1049,13 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN
                     context_invalidate_state(context, STATE_INDEXBUFFER);
                 GL_EXTCALL(glBindBufferARB(buffer->buffer_type_hint, buffer->buffer_object));
 
-                if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+		if (gl_info->supported[ATI_PINNED_MEMORY])
+		{
+			GL_EXTCALL(glBindBufferARB(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, buffer->buffer_object));
+    			buffer->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer->resource.size + RESOURCE_ALIGNMENT);
+			GL_EXTCALL(glBufferDataARB(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, buffer->resource.size, buffer->resource.allocatedMemory, GL_STREAM_COPY));
+		}
+                else if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
                 {
                     GLbitfield mapflags = buffer_gl_map_flags(flags);
                     buffer->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(buffer->buffer_type_hint,
@@ -1141,26 +1166,33 @@ void CDECL wined3d_buffer_unmap(struct wined3d_buffer *buffer)
             context_invalidate_state(context, STATE_INDEXBUFFER);
         GL_EXTCALL(glBindBufferARB(buffer->buffer_type_hint, buffer->buffer_object));
 
-        if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
-        {
-            for (i = 0; i < buffer->modified_areas; ++i)
-            {
-                GL_EXTCALL(glFlushMappedBufferRange(buffer->buffer_type_hint,
-                        buffer->maps[i].offset, buffer->maps[i].size));
-                checkGLcall("glFlushMappedBufferRange");
-            }
-        }
-        else if (buffer->flags & WINED3D_BUFFER_FLUSH)
-        {
-            for (i = 0; i < buffer->modified_areas; ++i)
-            {
-                GL_EXTCALL(glFlushMappedBufferRangeAPPLE(buffer->buffer_type_hint,
-                        buffer->maps[i].offset, buffer->maps[i].size));
-                checkGLcall("glFlushMappedBufferRangeAPPLE");
-            }
-        }
-
-        GL_EXTCALL(glUnmapBufferARB(buffer->buffer_type_hint));
+	if (gl_info->supported[ATI_PINNED_MEMORY])
+	{
+		GL_EXTCALL(glBindBufferARB(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0));
+		HeapFree(GetProcessHeap(), 0, buffer->resource.allocatedMemory);
+	}
+	else {
+		if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+		{
+		    for (i = 0; i < buffer->modified_areas; ++i)
+		    {
+			GL_EXTCALL(glFlushMappedBufferRange(buffer->buffer_type_hint,
+				buffer->maps[i].offset, buffer->maps[i].size));
+			checkGLcall("glFlushMappedBufferRange");
+		    }
+		}
+		else if (buffer->flags & WINED3D_BUFFER_FLUSH)
+		{
+		    for (i = 0; i < buffer->modified_areas; ++i)
+		    {
+			GL_EXTCALL(glFlushMappedBufferRangeAPPLE(buffer->buffer_type_hint,
+				buffer->maps[i].offset, buffer->maps[i].size));
+			checkGLcall("glFlushMappedBufferRangeAPPLE");
+		    }
+		}
+
+        	GL_EXTCALL(glUnmapBufferARB(buffer->buffer_type_hint));
+	}
         if (wined3d_settings.strict_draw_ordering)
             gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
         context_release(context);
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index acdcc57..21a7aa8 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -145,6 +145,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ATI_texture_compression_3dc",      ATI_TEXTURE_COMPRESSION_3DC   },
     {"GL_ATI_texture_env_combine3",         ATI_TEXTURE_ENV_COMBINE3      },
     {"GL_ATI_texture_mirror_once",          ATI_TEXTURE_MIRROR_ONCE       },
+    {"GL_AMD_pinned_memory",                ATI_PINNED_MEMORY             },
 
     /* EXT */
     {"GL_EXT_blend_color",                  EXT_BLEND_COLOR               },
diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h
index 06b5274..84747a2 100644
--- a/dlls/wined3d/wined3d_gl.h
+++ b/dlls/wined3d/wined3d_gl.h
@@ -27,6 +27,7 @@
 #include "wine/wgl.h"
 
 #define GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837  /* not in the gl spec */
+#define EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD              0x9160
 
 void (WINE_GLAPI *glDisableWINE)(GLenum cap) DECLSPEC_HIDDEN;
 void (WINE_GLAPI *glEnableWINE)(GLenum cap) DECLSPEC_HIDDEN;
@@ -96,6 +97,7 @@ enum wined3d_gl_extension
     ATI_TEXTURE_COMPRESSION_3DC,
     ATI_TEXTURE_ENV_COMBINE3,
     ATI_TEXTURE_MIRROR_ONCE,
+    ATI_PINNED_MEMORY,
     /* EXT */
     EXT_BLEND_COLOR,
     EXT_BLEND_EQUATION_SEPARATE,


More information about the wine-patches mailing list