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