Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
716520b4
Commit
716520b4
authored
Dec 28, 2009
by
Stefan Dösinger
Committed by
Alexandre Julliard
Jan 04, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wined3d: Track separate dirty ranges in buffers.
parent
1bd98719
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
158 additions
and
90 deletions
+158
-90
buffer.c
dlls/wined3d/buffer.c
+147
-84
wined3d_private.h
dlls/wined3d/wined3d_private.h
+11
-6
No files found.
dlls/wined3d/buffer.c
View file @
716520b4
...
...
@@ -36,6 +36,61 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d);
#define VB_MAXFULLCONVERSIONS 5
/* Number of full conversions before we stop converting */
#define VB_RESETFULLCONVS 20
/* Reset full conversion counts after that number of draws */
static
inline
BOOL
buffer_add_dirty_area
(
struct
wined3d_buffer
*
This
,
UINT
offset
,
UINT
size
)
{
if
(
!
This
->
buffer_object
)
return
TRUE
;
if
(
This
->
maps_size
<=
This
->
modified_areas
)
{
void
*
new
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
This
->
maps
,
This
->
maps_size
*
2
*
sizeof
(
*
This
->
maps
));
if
(
!
new
)
{
ERR
(
"Out of memory
\n
"
);
return
FALSE
;
}
else
{
This
->
maps
=
new
;
This
->
maps_size
*=
2
;
}
}
if
(
!
offset
&&
!
size
)
{
size
=
This
->
resource
.
size
;
}
This
->
maps
[
This
->
modified_areas
].
offset
=
offset
;
This
->
maps
[
This
->
modified_areas
].
size
=
size
;
This
->
modified_areas
++
;
return
TRUE
;
}
static
inline
void
buffer_clear_dirty_areas
(
struct
wined3d_buffer
*
This
)
{
This
->
modified_areas
=
0
;
}
static
inline
BOOL
buffer_is_dirty
(
struct
wined3d_buffer
*
This
)
{
return
This
->
modified_areas
!=
0
;
}
static
inline
BOOL
buffer_is_fully_dirty
(
struct
wined3d_buffer
*
This
)
{
unsigned
int
i
;
for
(
i
=
0
;
i
<
This
->
modified_areas
;
i
++
)
{
if
(
This
->
maps
[
i
].
offset
==
0
&&
This
->
maps
[
i
].
size
==
This
->
resource
.
size
)
{
return
TRUE
;
}
}
return
FALSE
;
}
/* Context activation is done by the caller. */
static
void
buffer_create_buffer_object
(
struct
wined3d_buffer
*
This
)
{
...
...
@@ -65,6 +120,7 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This)
if
(
!
This
->
buffer_object
||
error
!=
GL_NO_ERROR
)
{
ERR
(
"Failed to create a VBO with error %s (%#x)
\n
"
,
debug_glerror
(
error
),
error
);
LEAVE_GL
();
goto
fail
;
}
...
...
@@ -77,6 +133,7 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This)
if
(
error
!=
GL_NO_ERROR
)
{
ERR
(
"Failed to bind the VBO with error %s (%#x)
\n
"
,
debug_glerror
(
error
),
error
);
LEAVE_GL
();
goto
fail
;
}
...
...
@@ -101,29 +158,29 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This)
*/
GL_EXTCALL
(
glBufferDataARB
(
This
->
buffer_type_hint
,
This
->
resource
.
size
,
This
->
resource
.
allocatedMemory
,
gl_usage
));
error
=
glGetError
();
LEAVE_GL
();
if
(
error
!=
GL_NO_ERROR
)
{
ERR
(
"glBufferDataARB failed with error %s (%#x)
\n
"
,
debug_glerror
(
error
),
error
);
goto
fail
;
}
LEAVE_GL
();
This
->
buffer_object_size
=
This
->
resource
.
size
;
This
->
buffer_object_usage
=
gl_usage
;
This
->
dirty_start
=
0
;
This
->
dirty_end
=
This
->
resource
.
size
;
if
(
This
->
flags
&
WINED3D_BUFFER_DOUBLEBUFFER
)
{
This
->
flags
|=
WINED3D_BUFFER_DIRTY
;
if
(
!
buffer_add_dirty_area
(
This
,
0
,
0
))
{
ERR
(
"buffer_add_dirty_area failed, this is not expected
\n
"
);
goto
fail
;
}
}
else
{
HeapFree
(
GetProcessHeap
(),
0
,
This
->
resource
.
heapMemory
);
This
->
resource
.
allocatedMemory
=
NULL
;
This
->
resource
.
heapMemory
=
NULL
;
This
->
flags
&=
~
WINED3D_BUFFER_DIRTY
;
}
return
;
...
...
@@ -131,9 +188,14 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This)
fail:
/* Clean up all vbo init, but continue because we can work without a vbo :-) */
ERR
(
"Failed to create a vertex buffer object. Continuing, but performance issues may occur
\n
"
);
if
(
This
->
buffer_object
)
GL_EXTCALL
(
glDeleteBuffersARB
(
1
,
&
This
->
buffer_object
));
if
(
This
->
buffer_object
)
{
ENTER_GL
();
GL_EXTCALL
(
glDeleteBuffersARB
(
1
,
&
This
->
buffer_object
));
LEAVE_GL
();
}
This
->
buffer_object
=
0
;
LEAVE_GL
(
);
buffer_clear_dirty_areas
(
This
);
}
static
BOOL
buffer_process_converted_attribute
(
struct
wined3d_buffer
*
This
,
...
...
@@ -620,6 +682,7 @@ static void STDMETHODCALLTYPE buffer_UnLoad(IWineD3DBuffer *iface)
LEAVE_GL
();
This
->
buffer_object
=
0
;
This
->
flags
|=
WINED3D_BUFFER_CREATEBO
;
/* Recreate the buffer object next load */
buffer_clear_dirty_areas
(
This
);
context_release
(
context
);
...
...
@@ -645,6 +708,7 @@ static ULONG STDMETHODCALLTYPE buffer_Release(IWineD3DBuffer *iface)
buffer_UnLoad
(
iface
);
resource_cleanup
((
IWineD3DResource
*
)
iface
);
This
->
resource
.
parent_ops
->
wined3d_object_destroyed
(
This
->
resource
.
parent
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
maps
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
}
...
...
@@ -691,7 +755,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
{
struct
wined3d_buffer
*
This
=
(
struct
wined3d_buffer
*
)
iface
;
IWineD3DDeviceImpl
*
device
=
This
->
resource
.
device
;
UINT
start
=
0
,
end
=
0
,
vertices
;
UINT
start
=
0
,
end
=
0
,
len
=
0
,
vertices
;
struct
wined3d_context
*
context
;
BOOL
decl_changed
=
FALSE
;
unsigned
int
i
,
j
;
...
...
@@ -723,7 +787,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
This
->
flags
|=
WINED3D_BUFFER_HASDESC
;
}
if
(
!
decl_changed
&&
!
(
This
->
flags
&
WINED3D_BUFFER_HASDESC
&&
This
->
flags
&
WINED3D_BUFFER_DIRTY
))
if
(
!
decl_changed
&&
!
(
This
->
flags
&
WINED3D_BUFFER_HASDESC
&&
buffer_is_dirty
(
This
)
))
{
context_release
(
context
);
++
This
->
draw_count
;
...
...
@@ -764,7 +828,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
* changes it every minute drop the VBO after VB_MAX_DECL_CHANGES minutes. So count draws without
* decl changes and reset the decl change count after a specific number of them
*/
if
(
This
->
dirty_start
==
0
&&
This
->
dirty_end
==
This
->
resource
.
size
)
if
(
buffer_is_fully_dirty
(
This
)
)
{
++
This
->
full_conversion_count
;
if
(
This
->
full_conversion_count
>
VB_MAXFULLCONVERSIONS
)
...
...
@@ -788,28 +852,14 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
{
/* The declaration changed, reload the whole buffer */
WARN
(
"Reloading buffer because of decl change
\n
"
);
start
=
0
;
end
=
This
->
resource
.
size
;
}
else
{
/* No decl change, but dirty data, reload the changed stuff */
if
(
This
->
conversion_shift
)
buffer_clear_dirty_areas
(
This
);
if
(
!
buffer_add_dirty_area
(
This
,
0
,
0
))
{
if
(
This
->
dirty_start
!=
0
||
This
->
dirty_end
!=
0
)
{
FIXME
(
"Implement partial buffer loading with shifted conversion
\n
"
);
}
ERR
(
"buffer_add_dirty_area failed, this is not expected
\n
"
);
return
;
}
start
=
This
->
dirty_start
;
end
=
This
->
dirty_end
;
}
/* Mark the buffer clean */
This
->
flags
&=
~
WINED3D_BUFFER_DIRTY
;
This
->
dirty_start
=
0
;
This
->
dirty_end
=
0
;
if
(
This
->
buffer_type_hint
==
GL_ELEMENT_ARRAY_BUFFER_ARB
)
{
IWineD3DDeviceImpl_MarkStateDirty
(
This
->
resource
.
device
,
STATE_INDEXBUFFER
);
...
...
@@ -833,8 +883,14 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
ENTER_GL
();
GL_EXTCALL
(
glBindBufferARB
(
This
->
buffer_type_hint
,
This
->
buffer_object
));
checkGLcall
(
"glBindBufferARB"
);
GL_EXTCALL
(
glBufferSubDataARB
(
This
->
buffer_type_hint
,
start
,
end
-
start
,
This
->
resource
.
allocatedMemory
+
start
));
checkGLcall
(
"glBufferSubDataARB"
);
while
(
This
->
modified_areas
)
{
This
->
modified_areas
--
;
start
=
This
->
maps
[
This
->
modified_areas
].
offset
;
len
=
This
->
maps
[
This
->
modified_areas
].
size
;
GL_EXTCALL
(
glBufferSubDataARB
(
This
->
buffer_type_hint
,
start
,
len
,
This
->
resource
.
allocatedMemory
+
start
));
checkGLcall
(
"glBufferSubDataARB"
);
}
LEAVE_GL
();
context_release
(
context
);
...
...
@@ -854,6 +910,15 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
TRACE
(
"Shifted conversion
\n
"
);
data
=
HeapAlloc
(
GetProcessHeap
(),
0
,
vertices
*
This
->
conversion_stride
);
start
=
0
;
len
=
This
->
resource
.
size
;
end
=
start
+
len
;
if
(
This
->
maps
[
0
].
offset
||
This
->
maps
[
0
].
size
!=
This
->
resource
.
size
)
{
FIXME
(
"Implement partial buffer load with shifted conversion
\n
"
);
}
for
(
i
=
start
/
This
->
stride
;
i
<
min
((
end
/
This
->
stride
)
+
1
,
vertices
);
++
i
)
{
for
(
j
=
0
;
j
<
This
->
stride
;
++
j
)
...
...
@@ -893,41 +958,50 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
else
{
data
=
HeapAlloc
(
GetProcessHeap
(),
0
,
This
->
resource
.
size
);
memcpy
(
data
+
start
,
This
->
resource
.
allocatedMemory
+
start
,
end
-
start
);
for
(
i
=
start
/
This
->
stride
;
i
<
min
((
end
/
This
->
stride
)
+
1
,
vertices
);
++
i
)
while
(
This
->
modified_areas
)
{
for
(
j
=
0
;
j
<
This
->
stride
;
++
j
)
This
->
modified_areas
--
;
start
=
This
->
maps
[
This
->
modified_areas
].
offset
;
len
=
This
->
maps
[
This
->
modified_areas
].
size
;
end
=
start
+
len
;
memcpy
(
data
+
start
,
This
->
resource
.
allocatedMemory
+
start
,
end
-
start
);
for
(
i
=
start
/
This
->
stride
;
i
<
min
((
end
/
This
->
stride
)
+
1
,
vertices
);
++
i
)
{
switch
(
This
->
conversion_map
[
j
]
)
for
(
j
=
0
;
j
<
This
->
stride
;
++
j
)
{
case
CONV_NONE
:
/* Done already */
j
+=
3
;
break
;
case
CONV_D3DCOLOR
:
fixup_d3dcolor
((
DWORD
*
)
(
data
+
i
*
This
->
stride
+
j
));
j
+=
3
;
break
;
case
CONV_POSITIONT
:
fixup_transformed_pos
((
float
*
)
(
data
+
i
*
This
->
stride
+
j
));
j
+=
15
;
break
;
case
CONV_FLOAT16_2
:
ERR
(
"Did not expect FLOAT16 conversion in unshifted conversion
\n
"
);
default:
FIXME
(
"Unimplemented conversion %d in shifted conversion
\n
"
,
This
->
conversion_map
[
j
]);
switch
(
This
->
conversion_map
[
j
])
{
case
CONV_NONE
:
/* Done already */
j
+=
3
;
break
;
case
CONV_D3DCOLOR
:
fixup_d3dcolor
((
DWORD
*
)
(
data
+
i
*
This
->
stride
+
j
));
j
+=
3
;
break
;
case
CONV_POSITIONT
:
fixup_transformed_pos
((
float
*
)
(
data
+
i
*
This
->
stride
+
j
));
j
+=
15
;
break
;
case
CONV_FLOAT16_2
:
ERR
(
"Did not expect FLOAT16 conversion in unshifted conversion
\n
"
);
default:
FIXME
(
"Unimplemented conversion %d in shifted conversion
\n
"
,
This
->
conversion_map
[
j
]);
}
}
}
}
ENTER_GL
();
GL_EXTCALL
(
glBindBufferARB
(
This
->
buffer_type_hint
,
This
->
buffer_object
));
checkGLcall
(
"glBindBufferARB"
);
GL_EXTCALL
(
glBufferSubDataARB
(
This
->
buffer_type_hint
,
start
,
end
-
start
,
data
+
start
));
checkGLcall
(
"glBufferSubDataARB"
);
LEAVE_GL
();
ENTER_GL
();
GL_EXTCALL
(
glBindBufferARB
(
This
->
buffer_type_hint
,
This
->
buffer_object
));
checkGLcall
(
"glBindBufferARB"
);
GL_EXTCALL
(
glBufferSubDataARB
(
This
->
buffer_type_hint
,
start
,
len
,
data
+
start
));
checkGLcall
(
"glBufferSubDataARB"
);
LEAVE_GL
();
}
}
HeapFree
(
GetProcessHeap
(),
0
,
data
);
...
...
@@ -950,27 +1024,9 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset,
TRACE
(
"iface %p, offset %u, size %u, data %p, flags %#x
\n
"
,
iface
,
offset
,
size
,
data
,
flags
);
count
=
InterlockedIncrement
(
&
This
->
lock_count
);
if
(
This
->
flags
&
WINED3D_BUFFER_DIRTY
)
{
if
(
This
->
dirty_start
>
offset
)
This
->
dirty_start
=
offset
;
if
(
!
buffer_add_dirty_area
(
This
,
offset
,
size
))
return
E_OUTOFMEMORY
;
if
(
size
)
{
if
(
This
->
dirty_end
<
offset
+
size
)
This
->
dirty_end
=
offset
+
size
;
}
else
{
This
->
dirty_end
=
This
->
resource
.
size
;
}
}
else
{
This
->
dirty_start
=
offset
;
if
(
size
)
This
->
dirty_end
=
offset
+
size
;
else
This
->
dirty_end
=
This
->
resource
.
size
;
}
count
=
InterlockedIncrement
(
&
This
->
lock_count
);
if
(
!
(
This
->
flags
&
WINED3D_BUFFER_DOUBLEBUFFER
)
&&
This
->
buffer_object
)
{
...
...
@@ -992,10 +1048,6 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset,
context_release
(
context
);
}
}
else
{
This
->
flags
|=
WINED3D_BUFFER_DIRTY
;
}
*
data
=
This
->
resource
.
allocatedMemory
+
offset
;
...
...
@@ -1046,6 +1098,7 @@ static HRESULT STDMETHODCALLTYPE buffer_Unmap(IWineD3DBuffer *iface)
context_release
(
context
);
This
->
resource
.
allocatedMemory
=
NULL
;
buffer_clear_dirty_areas
(
This
);
}
else
if
(
This
->
flags
&
WINED3D_BUFFER_HASDESC
)
{
...
...
@@ -1169,5 +1222,15 @@ HRESULT buffer_init(struct wined3d_buffer *buffer, IWineD3DDeviceImpl *device,
}
}
buffer
->
maps
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
buffer
->
maps
));
if
(
!
buffer
->
maps
)
{
ERR
(
"Out of memory
\n
"
);
buffer_UnLoad
((
IWineD3DBuffer
*
)
buffer
);
resource_cleanup
((
IWineD3DResource
*
)
buffer
);
return
E_OUTOFMEMORY
;
}
buffer
->
maps_size
=
1
;
return
WINED3D_OK
;
}
dlls/wined3d/wined3d_private.h
View file @
716520b4
...
...
@@ -2358,11 +2358,16 @@ enum wined3d_buffer_conversion_type
CONV_FLOAT16_2
,
/* Also handles FLOAT16_4 */
};
struct
wined3d_map_range
{
UINT
offset
;
UINT
size
;
};
#define WINED3D_BUFFER_OPTIMIZED 0x01
/* Optimize has been called for the buffer */
#define WINED3D_BUFFER_DIRTY 0x02
/* Buffer data has been modified */
#define WINED3D_BUFFER_HASDESC 0x04
/* A vertex description has been found */
#define WINED3D_BUFFER_CREATEBO 0x08
/* Attempt to create a buffer object next PreLoad */
#define WINED3D_BUFFER_DOUBLEBUFFER 0x10
/* Use a vbo and local allocated memory */
#define WINED3D_BUFFER_HASDESC 0x02
/* A vertex description has been found */
#define WINED3D_BUFFER_CREATEBO 0x04
/* Attempt to create a buffer object next PreLoad */
#define WINED3D_BUFFER_DOUBLEBUFFER 0x08
/* Use a vbo and local allocated memory */
struct
wined3d_buffer
{
...
...
@@ -2378,9 +2383,9 @@ struct wined3d_buffer
LONG
bind_count
;
DWORD
flags
;
UINT
dirty_start
;
UINT
dirty_end
;
LONG
lock_count
;
struct
wined3d_map_range
*
maps
;
ULONG
maps_size
,
modified_areas
;
/* conversion stuff */
UINT
decl_change_count
,
full_conversion_count
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment