wined3d: Do not release the local vertex buffer copy.

This commit is contained in:
Stefan Dösinger 2007-02-14 17:51:21 +01:00 committed by Alexandre Julliard
parent 40c85a60b7
commit e6fedfca7a
2 changed files with 28 additions and 102 deletions

View File

@ -355,25 +355,20 @@ static void CreateVBO(IWineD3DVertexBufferImpl *object) {
} }
/* Don't use static, because dx apps tend to update the buffer /* Don't use static, because dx apps tend to update the buffer
* quite often even if they specify 0 usage * quite often even if they specify 0 usage. Because we always keep the local copy
* we never read from the vbo and can create a write only opengl buffer.
*/ */
switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) { switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC: case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
case D3DUSAGE_DYNAMIC:
TRACE("Gl usage = GL_STREAM_DRAW\n"); TRACE("Gl usage = GL_STREAM_DRAW\n");
glUsage = GL_STREAM_DRAW_ARB; glUsage = GL_STREAM_DRAW_ARB;
break; break;
case D3DUSAGE_WRITEONLY: case D3DUSAGE_WRITEONLY:
default:
TRACE("Gl usage = GL_DYNAMIC_DRAW\n"); TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
glUsage = GL_DYNAMIC_DRAW_ARB; glUsage = GL_DYNAMIC_DRAW_ARB;
break; break;
case D3DUSAGE_DYNAMIC:
TRACE("Gl usage = GL_STREAM_COPY\n");
glUsage = GL_STREAM_COPY_ARB;
break;
default:
TRACE("Gl usage = GL_DYNAMIC_COPY\n");
glUsage = GL_DYNAMIC_COPY_ARB;
break;
} }
/* Reserve memory for the buffer. The amount of data won't change /* Reserve memory for the buffer. The amount of data won't change
@ -444,13 +439,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac
if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
(dxVersion > 7 || !conv) ) { (dxVersion > 7 || !conv) ) {
CreateVBO(object); CreateVBO(object);
/* DX7 buffers can be locked directly into the VBO (no conversion, see above */
if(dxVersion == 7 && object->vbo) {
HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
object->resource.allocatedMemory = NULL;
}
} }
return WINED3D_OK; return WINED3D_OK;
} }

View File

@ -289,7 +289,6 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if
This->draws = 0; This->draws = 0;
if(This->declChanges > VB_MAXDECLCHANGES) { if(This->declChanges > VB_MAXDECLCHANGES) {
if(This->resource.allocatedMemory) {
FIXME("Too much declaration changes, stopping converting\n"); FIXME("Too much declaration changes, stopping converting\n");
ENTER_GL(); ENTER_GL();
GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo)); GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo));
@ -306,11 +305,6 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if
return; return;
} }
/* Otherwise do not bother to release the VBO. If we're doing direct locking now,
* and the declarations changed the code below will fetch the VBO's contents, convert
* and on the next decl change the data will be in sysmem too and we can just release the VBO
*/
}
} else { } else {
/* However, it is perfectly fine to change the declaration every now and then. We don't want a game that /* However, it is perfectly fine to change the declaration every now and then. We don't want a game that
* changes it every minute drop the VBO after VB_MAX_DECL_CHANGES minutes. So count draws without * changes it every minute drop the VBO after VB_MAX_DECL_CHANGES minutes. So count draws without
@ -339,46 +333,20 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if
This->dirtystart = 0; This->dirtystart = 0;
This->dirtyend = 0; This->dirtyend = 0;
/* If there was no conversion done before, then resource.allocatedMemory does not exist
* because locking was done directly into the VBO. In this case get the data out
*/
if(declChanged && !This->resource.allocatedMemory) {
This->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, This->resource.size);
if(!This->resource.allocatedMemory) {
ERR("Out of memory when allocating memory for a vertex buffer\n");
return;
}
ERR("Was locking directly into the VBO, reading data back because conv is needed\n");
ENTER_GL();
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo));
checkGLcall("glBindBufferARB");
data = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB));
if(!data) {
ERR("glMapBuffer failed!\n");
LEAVE_GL();
return;
}
memcpy(This->resource.allocatedMemory, data, This->resource.size);
GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
checkGLcall("glUnmapBufferARB");
LEAVE_GL();
}
if (This->strided.u.s.position.dwStride) stride = This->strided.u.s.position.dwStride; if (This->strided.u.s.position.dwStride) stride = This->strided.u.s.position.dwStride;
else if(This->strided.u.s.specular.dwStride) stride = This->strided.u.s.specular.dwStride; else if(This->strided.u.s.specular.dwStride) stride = This->strided.u.s.specular.dwStride;
else if(This->strided.u.s.diffuse.dwStride) stride = This->strided.u.s.diffuse.dwStride; else if(This->strided.u.s.diffuse.dwStride) stride = This->strided.u.s.diffuse.dwStride;
else { else {
/* That means that there is nothing to fixup. Upload everything into the VBO and /* That means that there is nothing to fixup. Just upload from This->resource.allocatedMemory
* free This->resource.allocatedMemory * directly into the vbo. Do not free the system memory copy because drawPrimitive may need it if
* the stride is 0, for instancing emulation, vertex blending emulation or shader emulation.
*/ */
TRACE("No conversion needed, locking directly into the VBO in future\n"); TRACE("No conversion needed, locking directly into the VBO in future\n");
ENTER_GL(); ENTER_GL();
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo));
checkGLcall("glBindBufferARB"); checkGLcall("glBindBufferARB");
GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, This->resource.size, This->resource.allocatedMemory)); GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, start, end-start, This->resource.allocatedMemory + start));
checkGLcall("glBufferSubDataARB"); checkGLcall("glBufferSubDataARB");
LEAVE_GL(); LEAVE_GL();
return; return;
@ -448,31 +416,8 @@ static HRESULT WINAPI IWineD3DVertexBufferImpl_Lock(IWineD3DVertexBuffer *iface
This->dirtyend = This->resource.size; This->dirtyend = This->resource.size;
} }
if(This->resource.allocatedMemory) {
data = This->resource.allocatedMemory; data = This->resource.allocatedMemory;
This->Flags |= VBFLAG_DIRTY; This->Flags |= VBFLAG_DIRTY;
} else {
GLenum mode = GL_READ_WRITE_ARB;
/* Return data to the VBO */
TRACE("Locking directly into the buffer\n");
if((This->resource.usage & WINED3DUSAGE_WRITEONLY) || ( Flags & WINED3DLOCK_DISCARD) ) {
mode = GL_WRITE_ONLY_ARB;
} else if( Flags & (WINED3DLOCK_READONLY | WINED3DLOCK_NO_DIRTY_UPDATE) ) {
mode = GL_READ_ONLY_ARB;
}
ENTER_GL();
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo));
checkGLcall("glBindBufferARB");
data = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, mode));
LEAVE_GL();
if(!data) {
ERR("glMapBuffer failed\n");
return WINED3DERR_INVALIDCALL;
}
}
*ppbData = data + OffsetToLock; *ppbData = data + OffsetToLock;
TRACE("(%p) : returning memory of %p (base:%p,offset:%u)\n", This, data + OffsetToLock, data, OffsetToLock); TRACE("(%p) : returning memory of %p (base:%p,offset:%u)\n", This, data + OffsetToLock, data, OffsetToLock);
@ -491,14 +436,7 @@ HRESULT WINAPI IWineD3DVertexBufferImpl_Unlock(IWineD3DVertexBuffer *iface) {
return D3D_OK; return D3D_OK;
} }
if(!This->resource.allocatedMemory) { if(This->Flags & VBFLAG_HASDESC) {
ENTER_GL();
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo));
checkGLcall("glBindBufferARB");
GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
checkGLcall("glUnmapBufferARB");
LEAVE_GL();
} else if(This->Flags & VBFLAG_HASDESC){
IWineD3DVertexBufferImpl_PreLoad(iface); IWineD3DVertexBufferImpl_PreLoad(iface);
} }
return WINED3D_OK; return WINED3D_OK;