From 393ed4a070a38f093fc8920affd72cb77eb0942e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Mon, 22 Oct 2007 13:30:14 +0200 Subject: [PATCH] wined3d: Make resource memory 32 byte aligned. --- dlls/d3d9/tests/device.c | 71 ++++++++++++++++++++++++++++++++++ dlls/wined3d/device.c | 11 +++++- dlls/wined3d/surface.c | 5 ++- dlls/wined3d/wined3d_private.h | 2 + 4 files changed, 85 insertions(+), 4 deletions(-) diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 2402a9713ed..4f655b626dc 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -1449,6 +1449,76 @@ static void test_null_stream(void) if(d3d9) IDirect3D9_Release(d3d9); } +static inline const char *debug_d3dpool(D3DPOOL pool) { + switch(pool) { + case D3DPOOL_DEFAULT: return "D3DPOOL_DEFAULT"; + case D3DPOOL_SYSTEMMEM: return "D3DPOOL_SYSTEMMEM"; + case D3DPOOL_SCRATCH: return "D3DPOOL_SCRATCH"; + case D3DPOOL_MANAGED: return "D3DPOOL_MANAGED"; + default: + return "unknown pool"; + } +} + +static void test_vertex_buffer_alignment(void) +{ + IDirect3DVertexBuffer9 *buffer = NULL; + D3DPRESENT_PARAMETERS present_parameters; + IDirect3DDevice9 *device = NULL; + IDirect3D9 *d3d9; + HWND hwnd; + HRESULT hr; + D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED}; + DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577}; + unsigned int i, j; + void *data; + + d3d9 = pDirect3DCreate9( D3D_SDK_VERSION ); + ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n"); + hwnd = CreateWindow( "static", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL ); + ok(hwnd != NULL, "Failed to create window\n"); + if (!d3d9 || !hwnd) goto cleanup; + + ZeroMemory(&present_parameters, sizeof(present_parameters)); + present_parameters.Windowed = TRUE; + present_parameters.hDeviceWindow = hwnd; + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + + hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device ); + ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %s\n", DXGetErrorString9(hr)); + if(!device) + { + skip("Failed to create a d3d device\n"); + goto cleanup; + } + + for(i = 0; i < (sizeof(sizes) / sizeof(sizes[0])); i++) { + for(j = 0; j < (sizeof(pools) / sizeof(pools[0])); j++) { + hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL); + if(pools[j] == D3DPOOL_SCRATCH) { + ok(hr == D3DERR_INVALIDCALL, "Creating a D3DPOOL_SCRATCH buffer returned (0x%08x)\n", hr); + } else { + ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x). Pool = %s, size %d\n", hr, + debug_d3dpool(pools[j]), sizes[i]); + } + if(FAILED(hr)) continue; + + hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, (void **) &data, 0); + ok(SUCCEEDED(hr), "IDirect3DVertexBuffer9_Lock failed (0x%08x)\n", hr); + ok(((DWORD_PTR) data & 31) == 0, "Vertex buffer start address is not 32 byte aligned(size: %d, pool: %s, data: %p)\n", + sizes[i], debug_d3dpool(pools[j]), data); + hr = IDirect3DVertexBuffer9_Unlock(buffer); + ok(SUCCEEDED(hr), "IDirect3DVertexBuffer9_Unlock failed (0x%08x)\n", hr); + + if(buffer) IDirect3DVertexBuffer9_Release(buffer); + } + } + + cleanup: + if(d3d9) IDirect3D9_Release(d3d9); +} + START_TEST(device) { HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" ); @@ -1473,5 +1543,6 @@ START_TEST(device) test_depthstenciltest(); test_draw_indexed(); test_null_stream(); + test_vertex_buffer_alignment(); } } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index db7a4e323b4..dd6bde8c953 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -101,14 +101,14 @@ static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3 } \ WineD3DAdapterChangeGLRam(This, _size); \ } \ - object->resource.heapMemory = (0 == _size ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size + 4)); \ + object->resource.heapMemory = (0 == _size ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size + RESOURCE_ALIGNMENT)); \ if (object->resource.heapMemory == NULL && _size != 0) { \ FIXME("Out of memory!\n"); \ HeapFree(GetProcessHeap(), 0, object); \ *pp##type = NULL; \ return WINED3DERR_OUTOFVIDEOMEMORY; \ } \ - object->resource.allocatedMemory = object->resource.heapMemory; \ + object->resource.allocatedMemory = (BYTE *)(((ULONG_PTR) object->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); \ *pp##type = (IWineD3D##type *) object; \ IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\ TRACE("(%p) : Created resource %p\n", This, object); \ @@ -304,6 +304,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac WARN("Size 0 requested, returning WINED3DERR_INVALIDCALL\n"); *ppVertexBuffer = NULL; return WINED3DERR_INVALIDCALL; + } else if(Pool == WINED3DPOOL_SCRATCH) { + /* The d3d9 testsuit shows that this is not allowed. It doesn't make much sense + * anyway, SCRATCH vertex buffers aren't useable anywhere + */ + WARN("Vertex buffer in D3DPOOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL\n"); + *ppVertexBuffer = NULL; + return WINED3DERR_INVALIDCALL; } D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size) diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 6637539d7f8..5b6e90805eb 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -677,8 +677,9 @@ static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) { /* Whatever surface we have, make sure that there is memory allocated for the downloaded copy, * or a pbo to map */ - This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + 4); - This->resource.allocatedMemory = This->resource.heapMemory; + This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + RESOURCE_ALIGNMENT); + This->resource.allocatedMemory = + (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); if(This->Flags & SFLAG_INSYSMEM) { ERR("Surface without memory or pbo has SFLAG_INSYSMEM set!\n"); } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index fdfd43f2648..cac31a8cb69 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -830,6 +830,8 @@ typedef struct IWineD3DResourceImpl IWineD3DResourceClass resource; } IWineD3DResourceImpl; +/* Tests show that the start address of resources is 32 byte aligned */ +#define RESOURCE_ALIGNMENT 32 /***************************************************************************** * IWineD3DVertexBuffer implementation structure (extends IWineD3DResourceImpl)