wined3d: Make resource memory 32 byte aligned.
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index 2402a97..4f655b6 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -1449,6 +1449,76 @@
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 @@
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 db7a4e3..dd6bde8 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -101,14 +101,14 @@
} \
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 @@
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 6637539..5b6e908 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -677,8 +677,9 @@
/* 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 fdfd43f..cac31a8 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -830,6 +830,8 @@
IWineD3DResourceClass resource;
} IWineD3DResourceImpl;
+/* Tests show that the start address of resources is 32 byte aligned */
+#define RESOURCE_ALIGNMENT 32
/*****************************************************************************
* IWineD3DVertexBuffer implementation structure (extends IWineD3DResourceImpl)