/* * Copyright 2008 Henri Verbeet for CodeWeavers * Copyright 2015 Józef Kucia for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #define COBJMACROS #include "initguid.h" #include "d3d11_4.h" #include "wine/heap.h" #include "wine/test.h" #define BITS_NNAN 0xffc00000 #define BITS_NAN 0x7fc00000 #define BITS_NINF 0xff800000 #define BITS_INF 0x7f800000 #define BITS_N1_0 0xbf800000 #define BITS_1_0 0x3f800000 #define SWAPCHAIN_FLAG_SHADER_INPUT 0x1 static unsigned int use_adapter_idx; static BOOL enable_debug_layer; static BOOL use_warp_adapter; static BOOL use_mt = TRUE; static struct test_entry { union { void (*test)(void); void (*test_fl)(D3D_FEATURE_LEVEL fl); } u; D3D_FEATURE_LEVEL fl; } *mt_tests; size_t mt_tests_size, mt_test_count; struct format_support { DXGI_FORMAT format; D3D_FEATURE_LEVEL fl_required; D3D_FEATURE_LEVEL fl_optional; }; static const struct format_support display_format_support[] = { {DXGI_FORMAT_R8G8B8A8_UNORM, D3D_FEATURE_LEVEL_9_1}, {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, D3D_FEATURE_LEVEL_9_1}, {DXGI_FORMAT_B8G8R8A8_UNORM, D3D_FEATURE_LEVEL_9_1}, {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, D3D_FEATURE_LEVEL_9_1}, {DXGI_FORMAT_R16G16B16A16_FLOAT, D3D_FEATURE_LEVEL_10_0}, {DXGI_FORMAT_R10G10B10A2_UNORM, D3D_FEATURE_LEVEL_10_0}, {DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0}, }; struct vec2 { float x, y; }; struct vec3 { float x, y, z; }; struct vec4 { float x, y, z, w; }; struct ivec4 { int x, y, z, w; }; struct uvec4 { unsigned int x, y, z, w; }; struct device_desc { const D3D_FEATURE_LEVEL *feature_level; UINT flags; }; struct swapchain_desc { BOOL windowed; unsigned buffer_count; unsigned int width, height; DXGI_SWAP_EFFECT swap_effect; DWORD flags; }; static void queue_test_entry(const struct test_entry *t) { if (mt_test_count >= mt_tests_size) { mt_tests_size = max(16, mt_tests_size * 2); mt_tests = heap_realloc(mt_tests, mt_tests_size * sizeof(*t)); } mt_tests[mt_test_count++] = *t; } static void queue_test_fl(void (*test)(const D3D_FEATURE_LEVEL fl), D3D_FEATURE_LEVEL fl) { struct test_entry t; t.u.test_fl = test; t.fl = fl; queue_test_entry(&t); } static void queue_test(void (*test)(void)) { struct test_entry t; t.u.test = test; t.fl = 0; queue_test_entry(&t); } static void run_mt_test(const struct test_entry *t) { if (t->fl) t->u.test_fl(t->fl); else t->u.test(); } static DWORD WINAPI thread_func(void *ctx) { LONG *i = ctx, j; while (*i < mt_test_count) { j = *i; if (InterlockedCompareExchange(i, j + 1, j) == j) run_mt_test(&mt_tests[j]); } return 0; } static void run_queued_tests(void) { unsigned int thread_count, i; HANDLE *threads; SYSTEM_INFO si; LONG test_idx; if (!use_mt) { for (i = 0; i < mt_test_count; ++i) { run_mt_test(&mt_tests[i]); } return; } GetSystemInfo(&si); thread_count = si.dwNumberOfProcessors; threads = heap_calloc(thread_count, sizeof(*threads)); for (i = 0, test_idx = 0; i < thread_count; ++i) { threads[i] = CreateThread(NULL, 0, thread_func, &test_idx, 0, NULL); ok(!!threads[i], "Failed to create thread %u.\n", i); } WaitForMultipleObjects(thread_count, threads, TRUE, INFINITE); for (i = 0; i < thread_count; ++i) { CloseHandle(threads[i]); } heap_free(threads); } static void set_box(D3D11_BOX *box, UINT left, UINT top, UINT front, UINT right, UINT bottom, UINT back) { box->left = left; box->top = top; box->front = front; box->right = right; box->bottom = bottom; box->back = back; } static ULONG get_refcount(void *iface) { IUnknown *unknown = iface; IUnknown_AddRef(unknown); return IUnknown_Release(unknown); } #define check_interface(a, b, c, d) check_interface_(__LINE__, a, b, c, d) static HRESULT check_interface_(unsigned int line, void *iface, REFIID riid, BOOL supported, BOOL is_broken) { HRESULT hr, expected_hr, broken_hr; IUnknown *unknown = iface, *out; if (supported) { expected_hr = S_OK; broken_hr = E_NOINTERFACE; } else { expected_hr = E_NOINTERFACE; broken_hr = S_OK; } hr = IUnknown_QueryInterface(unknown, riid, (void **)&out); ok_(__FILE__, line)(hr == expected_hr || broken(is_broken && hr == broken_hr), "Got hr %#x, expected %#x.\n", hr, expected_hr); if (SUCCEEDED(hr)) IUnknown_Release(out); return hr; } static BOOL compare_float(float f, float g, unsigned int ulps) { int x = *(int *)&f; int y = *(int *)&g; if (x < 0) x = INT_MIN - x; if (y < 0) y = INT_MIN - y; if (abs(x - y) > ulps) return FALSE; return TRUE; } static BOOL compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned int ulps) { return compare_float(v1->x, v2->x, ulps) && compare_float(v1->y, v2->y, ulps) && compare_float(v1->z, v2->z, ulps) && compare_float(v1->w, v2->w, ulps); } static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) { unsigned int diff = x > y ? x - y : y - x; return diff <= max_diff; } static BOOL compare_uvec4(const struct uvec4* v1, const struct uvec4 *v2) { return v1->x == v2->x && v1->y == v2->y && v1->z == v2->z && v1->w == v2->w; } static BOOL compare_color(DWORD c1, DWORD c2, BYTE max_diff) { return compare_uint(c1 & 0xff, c2 & 0xff, max_diff) && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff) && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff) && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff); } struct srv_desc { DXGI_FORMAT format; D3D11_SRV_DIMENSION dimension; unsigned int miplevel_idx; unsigned int miplevel_count; unsigned int layer_idx; unsigned int layer_count; }; static void get_srv_desc(D3D11_SHADER_RESOURCE_VIEW_DESC *d3d11_desc, const struct srv_desc *desc) { d3d11_desc->Format = desc->format; d3d11_desc->ViewDimension = desc->dimension; if (desc->dimension == D3D11_SRV_DIMENSION_TEXTURE1D) { U(*d3d11_desc).Texture1D.MostDetailedMip = desc->miplevel_idx; U(*d3d11_desc).Texture1D.MipLevels = desc->miplevel_count; } else if (desc->dimension == D3D11_SRV_DIMENSION_TEXTURE1DARRAY) { U(*d3d11_desc).Texture1DArray.MostDetailedMip = desc->miplevel_idx; U(*d3d11_desc).Texture1DArray.MipLevels = desc->miplevel_count; U(*d3d11_desc).Texture1DArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture1DArray.ArraySize = desc->layer_count; } else if (desc->dimension == D3D11_SRV_DIMENSION_TEXTURE2D) { U(*d3d11_desc).Texture2D.MostDetailedMip = desc->miplevel_idx; U(*d3d11_desc).Texture2D.MipLevels = desc->miplevel_count; } else if (desc->dimension == D3D11_SRV_DIMENSION_TEXTURE2DARRAY) { U(*d3d11_desc).Texture2DArray.MostDetailedMip = desc->miplevel_idx; U(*d3d11_desc).Texture2DArray.MipLevels = desc->miplevel_count; U(*d3d11_desc).Texture2DArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture2DArray.ArraySize = desc->layer_count; } else if (desc->dimension == D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY) { U(*d3d11_desc).Texture2DMSArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture2DMSArray.ArraySize = desc->layer_count; } else if (desc->dimension == D3D11_SRV_DIMENSION_TEXTURE3D) { U(*d3d11_desc).Texture3D.MostDetailedMip = desc->miplevel_idx; U(*d3d11_desc).Texture3D.MipLevels = desc->miplevel_count; } else if (desc->dimension == D3D11_SRV_DIMENSION_TEXTURECUBE) { U(*d3d11_desc).TextureCube.MostDetailedMip = desc->miplevel_idx; U(*d3d11_desc).TextureCube.MipLevels = desc->miplevel_count; } else if (desc->dimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) { U(*d3d11_desc).TextureCubeArray.MostDetailedMip = desc->miplevel_idx; U(*d3d11_desc).TextureCubeArray.MipLevels = desc->miplevel_count; U(*d3d11_desc).TextureCubeArray.First2DArrayFace = desc->layer_idx; U(*d3d11_desc).TextureCubeArray.NumCubes = desc->layer_count; } else if (desc->dimension != D3D11_SRV_DIMENSION_UNKNOWN && desc->dimension != D3D11_SRV_DIMENSION_TEXTURE2DMS) { trace("Unhandled view dimension %#x.\n", desc->dimension); } } #define check_srv_desc(a, b) check_srv_desc_(__LINE__, a, b) static void check_srv_desc_(unsigned int line, const D3D11_SHADER_RESOURCE_VIEW_DESC *desc, const struct srv_desc *expected_desc) { ok_(__FILE__, line)(desc->Format == expected_desc->format, "Got format %#x, expected %#x.\n", desc->Format, expected_desc->format); ok_(__FILE__, line)(desc->ViewDimension == expected_desc->dimension, "Got view dimension %#x, expected %#x.\n", desc->ViewDimension, expected_desc->dimension); if (desc->ViewDimension != expected_desc->dimension) return; if (desc->ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2D) { ok_(__FILE__, line)(U(*desc).Texture2D.MostDetailedMip == expected_desc->miplevel_idx, "Got MostDetailedMip %u, expected %u.\n", U(*desc).Texture2D.MostDetailedMip, expected_desc->miplevel_idx); ok_(__FILE__, line)(U(*desc).Texture2D.MipLevels == expected_desc->miplevel_count, "Got MipLevels %u, expected %u.\n", U(*desc).Texture2D.MipLevels, expected_desc->miplevel_count); } else if (desc->ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DARRAY) { ok_(__FILE__, line)(U(*desc).Texture2DArray.MostDetailedMip == expected_desc->miplevel_idx, "Got MostDetailedMip %u, expected %u.\n", U(*desc).Texture2DArray.MostDetailedMip, expected_desc->miplevel_idx); ok_(__FILE__, line)(U(*desc).Texture2DArray.MipLevels == expected_desc->miplevel_count, "Got MipLevels %u, expected %u.\n", U(*desc).Texture2DArray.MipLevels, expected_desc->miplevel_count); ok_(__FILE__, line)(U(*desc).Texture2DArray.FirstArraySlice == expected_desc->layer_idx, "Got FirstArraySlice %u, expected %u.\n", U(*desc).Texture2DArray.FirstArraySlice, expected_desc->layer_idx); ok_(__FILE__, line)(U(*desc).Texture2DArray.ArraySize == expected_desc->layer_count, "Got ArraySize %u, expected %u.\n", U(*desc).Texture2DArray.ArraySize, expected_desc->layer_count); } else if (desc->ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY) { ok_(__FILE__, line)(U(*desc).Texture2DMSArray.FirstArraySlice == expected_desc->layer_idx, "Got FirstArraySlice %u, expected %u.\n", U(*desc).Texture2DMSArray.FirstArraySlice, expected_desc->layer_idx); ok_(__FILE__, line)(U(*desc).Texture2DMSArray.ArraySize == expected_desc->layer_count, "Got ArraySize %u, expected %u.\n", U(*desc).Texture2DMSArray.ArraySize, expected_desc->layer_count); } else if (desc->ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) { ok_(__FILE__, line)(U(*desc).Texture3D.MostDetailedMip == expected_desc->miplevel_idx, "Got MostDetailedMip %u, expected %u.\n", U(*desc).Texture3D.MostDetailedMip, expected_desc->miplevel_idx); ok_(__FILE__, line)(U(*desc).Texture3D.MipLevels == expected_desc->miplevel_count, "Got MipLevels %u, expected %u.\n", U(*desc).Texture3D.MipLevels, expected_desc->miplevel_count); } else if (desc->ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBE) { ok_(__FILE__, line)(U(*desc).TextureCube.MostDetailedMip == expected_desc->miplevel_idx, "Got MostDetailedMip %u, expected %u.\n", U(*desc).TextureCube.MostDetailedMip, expected_desc->miplevel_idx); ok_(__FILE__, line)(U(*desc).TextureCube.MipLevels == expected_desc->miplevel_count, "Got MipLevels %u, expected %u.\n", U(*desc).TextureCube.MipLevels, expected_desc->miplevel_count); } else if (desc->ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) { ok_(__FILE__, line)(U(*desc).TextureCubeArray.MostDetailedMip == expected_desc->miplevel_idx, "Got MostDetailedMip %u, expected %u.\n", U(*desc).TextureCubeArray.MostDetailedMip, expected_desc->miplevel_idx); ok_(__FILE__, line)(U(*desc).TextureCubeArray.MipLevels == expected_desc->miplevel_count, "Got MipLevels %u, expected %u.\n", U(*desc).TextureCubeArray.MipLevels, expected_desc->miplevel_count); ok_(__FILE__, line)(U(*desc).TextureCubeArray.First2DArrayFace == expected_desc->layer_idx, "Got First2DArrayFace %u, expected %u.\n", U(*desc).TextureCubeArray.First2DArrayFace, expected_desc->layer_idx); ok_(__FILE__, line)(U(*desc).TextureCubeArray.NumCubes == expected_desc->layer_count, "Got NumCubes %u, expected %u.\n", U(*desc).TextureCubeArray.NumCubes, expected_desc->layer_count); } else if (desc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2DMS) { trace("Unhandled view dimension %#x.\n", desc->ViewDimension); } } struct rtv_desc { DXGI_FORMAT format; D3D11_RTV_DIMENSION dimension; unsigned int miplevel_idx; unsigned int layer_idx; unsigned int layer_count; }; static void get_rtv_desc(D3D11_RENDER_TARGET_VIEW_DESC *d3d11_desc, const struct rtv_desc *desc) { d3d11_desc->Format = desc->format; d3d11_desc->ViewDimension = desc->dimension; if (desc->dimension == D3D11_RTV_DIMENSION_TEXTURE1D) { U(*d3d11_desc).Texture1D.MipSlice = desc->miplevel_idx; } else if (desc->dimension == D3D11_RTV_DIMENSION_TEXTURE1DARRAY) { U(*d3d11_desc).Texture1DArray.MipSlice = desc->miplevel_idx; U(*d3d11_desc).Texture1DArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture1DArray.ArraySize = desc->layer_count; } else if (desc->dimension == D3D11_RTV_DIMENSION_TEXTURE2D) { U(*d3d11_desc).Texture2D.MipSlice = desc->miplevel_idx; } else if (desc->dimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY) { U(*d3d11_desc).Texture2DArray.MipSlice = desc->miplevel_idx; U(*d3d11_desc).Texture2DArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture2DArray.ArraySize = desc->layer_count; } else if (desc->dimension == D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY) { U(*d3d11_desc).Texture2DMSArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture2DMSArray.ArraySize = desc->layer_count; } else if (desc->dimension == D3D11_RTV_DIMENSION_TEXTURE3D) { U(*d3d11_desc).Texture3D.MipSlice = desc->miplevel_idx; U(*d3d11_desc).Texture3D.FirstWSlice = desc->layer_idx; U(*d3d11_desc).Texture3D.WSize = desc->layer_count; } else if (desc->dimension != D3D11_RTV_DIMENSION_UNKNOWN && desc->dimension != D3D11_RTV_DIMENSION_TEXTURE2DMS) { trace("Unhandled view dimension %#x.\n", desc->dimension); } } #define check_rtv_desc(a, b) check_rtv_desc_(__LINE__, a, b) static void check_rtv_desc_(unsigned int line, const D3D11_RENDER_TARGET_VIEW_DESC *desc, const struct rtv_desc *expected_desc) { ok_(__FILE__, line)(desc->Format == expected_desc->format, "Got format %#x, expected %#x.\n", desc->Format, expected_desc->format); ok_(__FILE__, line)(desc->ViewDimension == expected_desc->dimension, "Got view dimension %#x, expected %#x.\n", desc->ViewDimension, expected_desc->dimension); if (desc->ViewDimension != expected_desc->dimension) return; if (desc->ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2D) { ok_(__FILE__, line)(U(*desc).Texture2D.MipSlice == expected_desc->miplevel_idx, "Got MipSlice %u, expected %u.\n", U(*desc).Texture2D.MipSlice, expected_desc->miplevel_idx); } else if (desc->ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY) { ok_(__FILE__, line)(U(*desc).Texture2DArray.MipSlice == expected_desc->miplevel_idx, "Got MipSlice %u, expected %u.\n", U(*desc).Texture2DArray.MipSlice, expected_desc->miplevel_idx); ok_(__FILE__, line)(U(*desc).Texture2DArray.FirstArraySlice == expected_desc->layer_idx, "Got FirstArraySlice %u, expected %u.\n", U(*desc).Texture2DArray.FirstArraySlice, expected_desc->layer_idx); ok_(__FILE__, line)(U(*desc).Texture2DArray.ArraySize == expected_desc->layer_count, "Got ArraySize %u, expected %u.\n", U(*desc).Texture2DArray.ArraySize, expected_desc->layer_count); } else if (desc->ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY) { ok_(__FILE__, line)(U(*desc).Texture2DMSArray.FirstArraySlice == expected_desc->layer_idx, "Got FirstArraySlice %u, expected %u.\n", U(*desc).Texture2DMSArray.FirstArraySlice, expected_desc->layer_idx); ok_(__FILE__, line)(U(*desc).Texture2DMSArray.ArraySize == expected_desc->layer_count, "Got ArraySize %u, expected %u.\n", U(*desc).Texture2DMSArray.ArraySize, expected_desc->layer_count); } else if (desc->ViewDimension == D3D11_RTV_DIMENSION_TEXTURE3D) { ok_(__FILE__, line)(U(*desc).Texture3D.MipSlice == expected_desc->miplevel_idx, "Got MipSlice %u, expected %u.\n", U(*desc).Texture3D.MipSlice, expected_desc->miplevel_idx); ok_(__FILE__, line)(U(*desc).Texture3D.FirstWSlice == expected_desc->layer_idx, "Got FirstWSlice %u, expected %u.\n", U(*desc).Texture3D.FirstWSlice, expected_desc->layer_idx); ok_(__FILE__, line)(U(*desc).Texture3D.WSize == expected_desc->layer_count, "Got WSize %u, expected %u.\n", U(*desc).Texture3D.WSize, expected_desc->layer_count); } else if (desc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2DMS) { trace("Unhandled view dimension %#x.\n", desc->ViewDimension); } } struct dsv_desc { DXGI_FORMAT format; D3D11_DSV_DIMENSION dimension; unsigned int miplevel_idx; unsigned int layer_idx; unsigned int layer_count; }; static void get_dsv_desc(D3D11_DEPTH_STENCIL_VIEW_DESC *d3d11_desc, const struct dsv_desc *desc) { d3d11_desc->Format = desc->format; d3d11_desc->ViewDimension = desc->dimension; d3d11_desc->Flags = 0; if (desc->dimension == D3D11_DSV_DIMENSION_TEXTURE1D) { U(*d3d11_desc).Texture1D.MipSlice = desc->miplevel_idx; } else if (desc->dimension == D3D11_DSV_DIMENSION_TEXTURE1DARRAY) { U(*d3d11_desc).Texture1DArray.MipSlice = desc->miplevel_idx; U(*d3d11_desc).Texture1DArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture1DArray.ArraySize = desc->layer_count; } else if (desc->dimension == D3D11_DSV_DIMENSION_TEXTURE2D) { U(*d3d11_desc).Texture2D.MipSlice = desc->miplevel_idx; } else if (desc->dimension == D3D11_DSV_DIMENSION_TEXTURE2DARRAY) { U(*d3d11_desc).Texture2DArray.MipSlice = desc->miplevel_idx; U(*d3d11_desc).Texture2DArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture2DArray.ArraySize = desc->layer_count; } else if (desc->dimension == D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY) { U(*d3d11_desc).Texture2DMSArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture2DMSArray.ArraySize = desc->layer_count; } else if (desc->dimension != D3D11_DSV_DIMENSION_UNKNOWN && desc->dimension != D3D11_DSV_DIMENSION_TEXTURE2DMS) { trace("Unhandled view dimension %#x.\n", desc->dimension); } } #define check_dsv_desc(a, b) check_dsv_desc_(__LINE__, a, b) static void check_dsv_desc_(unsigned int line, const D3D11_DEPTH_STENCIL_VIEW_DESC *desc, const struct dsv_desc *expected_desc) { ok_(__FILE__, line)(desc->Format == expected_desc->format, "Got format %#x, expected %#x.\n", desc->Format, expected_desc->format); ok_(__FILE__, line)(desc->ViewDimension == expected_desc->dimension, "Got view dimension %#x, expected %#x.\n", desc->ViewDimension, expected_desc->dimension); if (desc->ViewDimension != expected_desc->dimension) return; if (desc->ViewDimension == D3D11_DSV_DIMENSION_TEXTURE2D) { ok_(__FILE__, line)(U(*desc).Texture2D.MipSlice == expected_desc->miplevel_idx, "Got MipSlice %u, expected %u.\n", U(*desc).Texture2D.MipSlice, expected_desc->miplevel_idx); } else if (desc->ViewDimension == D3D11_DSV_DIMENSION_TEXTURE2DARRAY) { ok_(__FILE__, line)(U(*desc).Texture2DArray.MipSlice == expected_desc->miplevel_idx, "Got MipSlice %u, expected %u.\n", U(*desc).Texture2DArray.MipSlice, expected_desc->miplevel_idx); ok_(__FILE__, line)(U(*desc).Texture2DArray.FirstArraySlice == expected_desc->layer_idx, "Got FirstArraySlice %u, expected %u.\n", U(*desc).Texture2DArray.FirstArraySlice, expected_desc->layer_idx); ok_(__FILE__, line)(U(*desc).Texture2DArray.ArraySize == expected_desc->layer_count, "Got ArraySize %u, expected %u.\n", U(*desc).Texture2DArray.ArraySize, expected_desc->layer_count); } else if (desc->ViewDimension == D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY) { ok_(__FILE__, line)(U(*desc).Texture2DMSArray.FirstArraySlice == expected_desc->layer_idx, "Got FirstArraySlice %u, expected %u.\n", U(*desc).Texture2DMSArray.FirstArraySlice, expected_desc->layer_idx); ok_(__FILE__, line)(U(*desc).Texture2DMSArray.ArraySize == expected_desc->layer_count, "Got ArraySize %u, expected %u.\n", U(*desc).Texture2DMSArray.ArraySize, expected_desc->layer_count); } else if (desc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2DMS) { trace("Unhandled view dimension %#x.\n", desc->ViewDimension); } } struct uav_desc { DXGI_FORMAT format; D3D11_UAV_DIMENSION dimension; unsigned int miplevel_idx; unsigned int layer_idx; unsigned int layer_count; }; static void get_uav_desc(D3D11_UNORDERED_ACCESS_VIEW_DESC *d3d11_desc, const struct uav_desc *desc) { d3d11_desc->Format = desc->format; d3d11_desc->ViewDimension = desc->dimension; if (desc->dimension == D3D11_UAV_DIMENSION_TEXTURE1D) { U(*d3d11_desc).Texture1D.MipSlice = desc->miplevel_idx; } else if (desc->dimension == D3D11_UAV_DIMENSION_TEXTURE1DARRAY) { U(*d3d11_desc).Texture1DArray.MipSlice = desc->miplevel_idx; U(*d3d11_desc).Texture1DArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture1DArray.ArraySize = desc->layer_count; } else if (desc->dimension == D3D11_UAV_DIMENSION_TEXTURE2D) { U(*d3d11_desc).Texture2D.MipSlice = desc->miplevel_idx; } else if (desc->dimension == D3D11_UAV_DIMENSION_TEXTURE2DARRAY) { U(*d3d11_desc).Texture2DArray.MipSlice = desc->miplevel_idx; U(*d3d11_desc).Texture2DArray.FirstArraySlice = desc->layer_idx; U(*d3d11_desc).Texture2DArray.ArraySize = desc->layer_count; } else if (desc->dimension == D3D11_UAV_DIMENSION_TEXTURE3D) { U(*d3d11_desc).Texture3D.MipSlice = desc->miplevel_idx; U(*d3d11_desc).Texture3D.FirstWSlice = desc->layer_idx; U(*d3d11_desc).Texture3D.WSize = desc->layer_count; } else if (desc->dimension != D3D11_UAV_DIMENSION_UNKNOWN) { trace("Unhandled view dimension %#x.\n", desc->dimension); } } #define check_uav_desc(a, b) check_uav_desc_(__LINE__, a, b) static void check_uav_desc_(unsigned int line, const D3D11_UNORDERED_ACCESS_VIEW_DESC *desc, const struct uav_desc *expected_desc) { ok_(__FILE__, line)(desc->Format == expected_desc->format, "Got format %#x, expected %#x.\n", desc->Format, expected_desc->format); ok_(__FILE__, line)(desc->ViewDimension == expected_desc->dimension, "Got view dimension %#x, expected %#x.\n", desc->ViewDimension, expected_desc->dimension); if (desc->ViewDimension != expected_desc->dimension) return; if (desc->ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2D) { ok_(__FILE__, line)(U(*desc).Texture2D.MipSlice == expected_desc->miplevel_idx, "Got MipSlice %u, expected %u.\n", U(*desc).Texture2D.MipSlice, expected_desc->miplevel_idx); } else if (desc->ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2DARRAY) { ok_(__FILE__, line)(U(*desc).Texture2DArray.MipSlice == expected_desc->miplevel_idx, "Got MipSlice %u, expected %u.\n", U(*desc).Texture2DArray.MipSlice, expected_desc->miplevel_idx); ok_(__FILE__, line)(U(*desc).Texture2DArray.FirstArraySlice == expected_desc->layer_idx, "Got FirstArraySlice %u, expected %u.\n", U(*desc).Texture2DArray.FirstArraySlice, expected_desc->layer_idx); ok_(__FILE__, line)(U(*desc).Texture2DArray.ArraySize == expected_desc->layer_count, "Got ArraySize %u, expected %u.\n", U(*desc).Texture2DArray.ArraySize, expected_desc->layer_count); } else if (desc->ViewDimension == D3D11_UAV_DIMENSION_TEXTURE3D) { ok_(__FILE__, line)(U(*desc).Texture3D.MipSlice == expected_desc->miplevel_idx, "Got MipSlice %u, expected %u.\n", U(*desc).Texture3D.MipSlice, expected_desc->miplevel_idx); ok_(__FILE__, line)(U(*desc).Texture3D.FirstWSlice == expected_desc->layer_idx, "Got FirstWSlice %u, expected %u.\n", U(*desc).Texture3D.FirstWSlice, expected_desc->layer_idx); ok_(__FILE__, line)(U(*desc).Texture3D.WSize == expected_desc->layer_count, "Got WSize %u, expected %u.\n", U(*desc).Texture3D.WSize, expected_desc->layer_count); } else { trace("Unhandled view dimension %#x.\n", desc->ViewDimension); } } static void set_viewport(ID3D11DeviceContext *context, float x, float y, float width, float height, float min_depth, float max_depth) { D3D11_VIEWPORT vp; vp.TopLeftX = x; vp.TopLeftY = y; vp.Width = width; vp.Height = height; vp.MinDepth = min_depth; vp.MaxDepth = max_depth; ID3D11DeviceContext_RSSetViewports(context, 1, &vp); } #define create_buffer(a, b, c, d) create_buffer_(__LINE__, a, b, 0, c, d) #define create_buffer_misc(a, b, c, d, e) create_buffer_(__LINE__, a, b, c, d, e) static ID3D11Buffer *create_buffer_(unsigned int line, ID3D11Device *device, unsigned int bind_flags, unsigned int misc_flags, unsigned int size, const void *data) { D3D11_SUBRESOURCE_DATA resource_data; D3D11_BUFFER_DESC buffer_desc; ID3D11Buffer *buffer; HRESULT hr; buffer_desc.ByteWidth = size; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = bind_flags; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = misc_flags; buffer_desc.StructureByteStride = 0; resource_data.pSysMem = data; resource_data.SysMemPitch = 0; resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, data ? &resource_data : NULL, &buffer); ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); return buffer; } struct resource_readback { ID3D11Resource *resource; D3D11_MAPPED_SUBRESOURCE map_desc; ID3D11DeviceContext *immediate_context; unsigned int width, height, depth, sub_resource_idx; }; static void init_resource_readback(ID3D11Resource *resource, ID3D11Resource *readback_resource, unsigned int width, unsigned int height, unsigned int depth, unsigned int sub_resource_idx, ID3D11Device *device, struct resource_readback *rb) { HRESULT hr; rb->resource = readback_resource; rb->width = width; rb->height = height; rb->depth = depth; rb->sub_resource_idx = sub_resource_idx; ID3D11Device_GetImmediateContext(device, &rb->immediate_context); ID3D11DeviceContext_CopyResource(rb->immediate_context, rb->resource, resource); if (FAILED(hr = ID3D11DeviceContext_Map(rb->immediate_context, rb->resource, sub_resource_idx, D3D11_MAP_READ, 0, &rb->map_desc))) { trace("Failed to map resource, hr %#x.\n", hr); ID3D11Resource_Release(rb->resource); rb->resource = NULL; ID3D11DeviceContext_Release(rb->immediate_context); rb->immediate_context = NULL; } } static void get_buffer_readback(ID3D11Buffer *buffer, struct resource_readback *rb) { D3D11_BUFFER_DESC buffer_desc; ID3D11Resource *rb_buffer; ID3D11Device *device; HRESULT hr; memset(rb, 0, sizeof(*rb)); ID3D11Buffer_GetDevice(buffer, &device); ID3D11Buffer_GetDesc(buffer, &buffer_desc); buffer_desc.Usage = D3D11_USAGE_STAGING; buffer_desc.BindFlags = 0; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; buffer_desc.MiscFlags = 0; buffer_desc.StructureByteStride = 0; if (FAILED(hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, (ID3D11Buffer **)&rb_buffer))) { trace("Failed to create staging buffer, hr %#x.\n", hr); ID3D11Device_Release(device); return; } init_resource_readback((ID3D11Resource *)buffer, rb_buffer, buffer_desc.ByteWidth, 1, 1, 0, device, rb); ID3D11Device_Release(device); } static void get_texture1d_readback(ID3D11Texture1D *texture, unsigned int sub_resource_idx, struct resource_readback *rb) { D3D11_TEXTURE1D_DESC texture_desc; ID3D11Resource *rb_texture; unsigned int miplevel; ID3D11Device *device; HRESULT hr; memset(rb, 0, sizeof(*rb)); ID3D11Texture1D_GetDevice(texture, &device); ID3D11Texture1D_GetDesc(texture, &texture_desc); texture_desc.Usage = D3D11_USAGE_STAGING; texture_desc.BindFlags = 0; texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; texture_desc.MiscFlags = 0; if (FAILED(hr = ID3D11Device_CreateTexture1D(device, &texture_desc, NULL, (ID3D11Texture1D **)&rb_texture))) { trace("Failed to create texture, hr %#x.\n", hr); ID3D11Device_Release(device); return; } miplevel = sub_resource_idx % texture_desc.MipLevels; init_resource_readback((ID3D11Resource *)texture, rb_texture, max(1, texture_desc.Width >> miplevel), 1, 1, sub_resource_idx, device, rb); ID3D11Device_Release(device); } static void get_texture_readback(ID3D11Texture2D *texture, unsigned int sub_resource_idx, struct resource_readback *rb) { D3D11_TEXTURE2D_DESC texture_desc; ID3D11Resource *rb_texture; unsigned int miplevel; ID3D11Device *device; HRESULT hr; memset(rb, 0, sizeof(*rb)); ID3D11Texture2D_GetDevice(texture, &device); ID3D11Texture2D_GetDesc(texture, &texture_desc); texture_desc.Usage = D3D11_USAGE_STAGING; texture_desc.BindFlags = 0; texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; texture_desc.MiscFlags = 0; if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&rb_texture))) { trace("Failed to create texture, hr %#x.\n", hr); ID3D11Device_Release(device); return; } miplevel = sub_resource_idx % texture_desc.MipLevels; init_resource_readback((ID3D11Resource *)texture, rb_texture, max(1, texture_desc.Width >> miplevel), max(1, texture_desc.Height >> miplevel), 1, sub_resource_idx, device, rb); ID3D11Device_Release(device); } static void get_texture3d_readback(ID3D11Texture3D *texture, unsigned int sub_resource_idx, struct resource_readback *rb) { D3D11_TEXTURE3D_DESC texture_desc; ID3D11Resource *rb_texture; unsigned int miplevel; ID3D11Device *device; HRESULT hr; memset(rb, 0, sizeof(*rb)); ID3D11Texture3D_GetDevice(texture, &device); ID3D11Texture3D_GetDesc(texture, &texture_desc); texture_desc.Usage = D3D11_USAGE_STAGING; texture_desc.BindFlags = 0; texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; texture_desc.MiscFlags = 0; if (FAILED(hr = ID3D11Device_CreateTexture3D(device, &texture_desc, NULL, (ID3D11Texture3D **)&rb_texture))) { trace("Failed to create texture, hr %#x.\n", hr); ID3D11Device_Release(device); return; } miplevel = sub_resource_idx % texture_desc.MipLevels; init_resource_readback((ID3D11Resource *)texture, rb_texture, max(1, texture_desc.Width >> miplevel), max(1, texture_desc.Height >> miplevel), max(1, texture_desc.Depth >> miplevel), sub_resource_idx, device, rb); ID3D11Device_Release(device); } static void *get_readback_data(struct resource_readback *rb, unsigned int x, unsigned int y, unsigned int z, unsigned byte_width) { return (BYTE *)rb->map_desc.pData + z * rb->map_desc.DepthPitch + y * rb->map_desc.RowPitch + x * byte_width; } static BYTE get_readback_u8(struct resource_readback *rb, unsigned int x, unsigned int y, unsigned int z) { return *(BYTE *)get_readback_data(rb, x, y, z, sizeof(BYTE)); } static WORD get_readback_u16(struct resource_readback *rb, unsigned int x, unsigned int y, unsigned int z) { return *(WORD *)get_readback_data(rb, x, y, z, sizeof(WORD)); } static DWORD get_readback_u32(struct resource_readback *rb, unsigned int x, unsigned int y, unsigned int z) { return *(DWORD *)get_readback_data(rb, x, y, z, sizeof(DWORD)); } static DWORD get_readback_color(struct resource_readback *rb, unsigned int x, unsigned int y, unsigned int z) { return get_readback_u32(rb, x, y, z); } static float get_readback_float(struct resource_readback *rb, unsigned int x, unsigned int y) { return *(float *)get_readback_data(rb, x, y, 0, sizeof(float)); } static const struct vec4 *get_readback_vec4(struct resource_readback *rb, unsigned int x, unsigned int y) { return get_readback_data(rb, x, y, 0, sizeof(struct vec4)); } static const struct uvec4 *get_readback_uvec4(struct resource_readback *rb, unsigned int x, unsigned int y) { return get_readback_data(rb, x, y, 0, sizeof(struct uvec4)); } static void release_resource_readback(struct resource_readback *rb) { ID3D11DeviceContext_Unmap(rb->immediate_context, rb->resource, rb->sub_resource_idx); ID3D11Resource_Release(rb->resource); ID3D11DeviceContext_Release(rb->immediate_context); } static DWORD get_texture_color(ID3D11Texture2D *texture, unsigned int x, unsigned int y) { struct resource_readback rb; DWORD color; get_texture_readback(texture, 0, &rb); color = get_readback_color(&rb, x, y, 0); release_resource_readback(&rb); return color; } #define check_readback_data_u8(a, b, c, d) check_readback_data_u8_(__LINE__, a, b, c, d) static void check_readback_data_u8_(unsigned int line, struct resource_readback *rb, const RECT *rect, BYTE expected_value, BYTE max_diff) { unsigned int x = 0, y = 0, z = 0; BOOL all_match = FALSE; RECT default_rect; BYTE value = 0; if (!rect) { SetRect(&default_rect, 0, 0, rb->width, rb->height); rect = &default_rect; } for (z = 0; z < rb->depth; ++z) { for (y = rect->top; y < rect->bottom; ++y) { for (x = rect->left; x < rect->right; ++x) { value = get_readback_u8(rb, x, y, z); if (!compare_uint(value, expected_value, max_diff)) goto done; } } } all_match = TRUE; done: ok_(__FILE__, line)(all_match, "Got 0x%02x, expected 0x%02x at (%u, %u, %u), sub-resource %u.\n", value, expected_value, x, y, z, rb->sub_resource_idx); } #define check_readback_data_u16(a, b, c, d) check_readback_data_u16_(__LINE__, a, b, c, d) static void check_readback_data_u16_(unsigned int line, struct resource_readback *rb, const RECT *rect, WORD expected_value, BYTE max_diff) { unsigned int x = 0, y = 0, z = 0; BOOL all_match = FALSE; RECT default_rect; WORD value = 0; if (!rect) { SetRect(&default_rect, 0, 0, rb->width, rb->height); rect = &default_rect; } for (z = 0; z < rb->depth; ++z) { for (y = rect->top; y < rect->bottom; ++y) { for (x = rect->left; x < rect->right; ++x) { value = get_readback_u16(rb, x, y, z); if (!compare_uint(value, expected_value, max_diff)) goto done; } } } all_match = TRUE; done: ok_(__FILE__, line)(all_match, "Got 0x%04x, expected 0x%04x at (%u, %u, %u), sub-resource %u.\n", value, expected_value, x, y, z, rb->sub_resource_idx); } #define check_readback_data_u24(a, b, c, d, e) check_readback_data_u24_(__LINE__, a, b, c, d, e) static void check_readback_data_u24_(unsigned int line, struct resource_readback *rb, const RECT *rect, unsigned int shift, DWORD expected_value, BYTE max_diff) { unsigned int x = 0, y = 0, z = 0; BOOL all_match = FALSE; RECT default_rect; DWORD value = 0; if (!rect) { SetRect(&default_rect, 0, 0, rb->width, rb->height); rect = &default_rect; } for (z = 0; z < rb->depth; ++z) { for (y = rect->top; y < rect->bottom; ++y) { for (x = rect->left; x < rect->right; ++x) { value = get_readback_u32(rb, x, y, z) >> shift; if (!compare_uint(value, expected_value, max_diff)) goto done; } } } all_match = TRUE; done: ok_(__FILE__, line)(all_match, "Got 0x%06x, expected 0x%06x at (%u, %u, %u), sub-resource %u.\n", value, expected_value, x, y, z, rb->sub_resource_idx); } #define check_readback_data_color(a, b, c, d) check_readback_data_color_(__LINE__, a, b, c, d) static void check_readback_data_color_(unsigned int line, struct resource_readback *rb, const RECT *rect, DWORD expected_color, BYTE max_diff) { unsigned int x = 0, y = 0, z = 0; BOOL all_match = FALSE; RECT default_rect; DWORD color = 0; if (!rect) { SetRect(&default_rect, 0, 0, rb->width, rb->height); rect = &default_rect; } for (z = 0; z < rb->depth; ++z) { for (y = rect->top; y < rect->bottom; ++y) { for (x = rect->left; x < rect->right; ++x) { color = get_readback_color(rb, x, y, z); if (!compare_color(color, expected_color, max_diff)) goto done; } } } all_match = TRUE; done: ok_(__FILE__, line)(all_match, "Got 0x%08x, expected 0x%08x at (%u, %u, %u), sub-resource %u.\n", color, expected_color, x, y, z, rb->sub_resource_idx); } #define check_texture_sub_resource_color(a, b, c, d, e) check_texture_sub_resource_color_(__LINE__, a, b, c, d, e) static void check_texture_sub_resource_color_(unsigned int line, ID3D11Texture2D *texture, unsigned int sub_resource_idx, const RECT *rect, DWORD expected_color, BYTE max_diff) { struct resource_readback rb; get_texture_readback(texture, sub_resource_idx, &rb); check_readback_data_color_(line, &rb, rect, expected_color, max_diff); release_resource_readback(&rb); } #define check_texture_color(t, c, d) check_texture_color_(__LINE__, t, c, d) static void check_texture_color_(unsigned int line, ID3D11Texture2D *texture, DWORD expected_color, BYTE max_diff) { unsigned int sub_resource_idx, sub_resource_count; D3D11_TEXTURE2D_DESC texture_desc; ID3D11Texture2D_GetDesc(texture, &texture_desc); sub_resource_count = texture_desc.ArraySize * texture_desc.MipLevels; for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) check_texture_sub_resource_color_(line, texture, sub_resource_idx, NULL, expected_color, max_diff); } #define check_texture1d_sub_resource_color(a, b, c, d, e) check_texture1d_sub_resource_color_(__LINE__, a, b, c, d, e) static void check_texture1d_sub_resource_color_(unsigned int line, ID3D11Texture1D *texture, unsigned int sub_resource_idx, const RECT *rect, DWORD expected_color, BYTE max_diff) { struct resource_readback rb; get_texture1d_readback(texture, sub_resource_idx, &rb); check_readback_data_color_(line, &rb, rect, expected_color, max_diff); release_resource_readback(&rb); } #define check_texture1d_color(t, c, d) check_texture1d_color_(__LINE__, t, c, d) static void check_texture1d_color_(unsigned int line, ID3D11Texture1D *texture, DWORD expected_color, BYTE max_diff) { unsigned int sub_resource_idx, sub_resource_count; D3D11_TEXTURE1D_DESC texture_desc; ID3D11Texture1D_GetDesc(texture, &texture_desc); sub_resource_count = texture_desc.ArraySize * texture_desc.MipLevels; for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) check_texture1d_sub_resource_color_(line, texture, sub_resource_idx, NULL, expected_color, max_diff); } #define check_texture3d_sub_resource_color(a, b, c, d, e) check_texture3d_sub_resource_color_(__LINE__, a, b, c, d, e) static void check_texture3d_sub_resource_color_(unsigned int line, ID3D11Texture3D *texture, unsigned int sub_resource_idx, const RECT *rect, DWORD expected_color, BYTE max_diff) { struct resource_readback rb; get_texture3d_readback(texture, sub_resource_idx, &rb); check_readback_data_color_(line, &rb, rect, expected_color, max_diff); release_resource_readback(&rb); } #define check_texture3d_color(t, c, d) check_texture3d_color_(__LINE__, t, c, d) static void check_texture3d_color_(unsigned int line, ID3D11Texture3D *texture, DWORD expected_color, BYTE max_diff) { unsigned int sub_resource_idx, sub_resource_count; D3D11_TEXTURE3D_DESC texture_desc; ID3D11Texture3D_GetDesc(texture, &texture_desc); sub_resource_count = texture_desc.MipLevels; for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) check_texture3d_sub_resource_color_(line, texture, sub_resource_idx, NULL, expected_color, max_diff); } #define check_texture_sub_resource_float(a, b, c, d, e) check_texture_sub_resource_float_(__LINE__, a, b, c, d, e) static void check_texture_sub_resource_float_(unsigned int line, ID3D11Texture2D *texture, unsigned int sub_resource_idx, const RECT *rect, float expected_value, BYTE max_diff) { struct resource_readback rb; unsigned int x = 0, y = 0; BOOL all_match = TRUE; float value = 0.0f; RECT default_rect; get_texture_readback(texture, sub_resource_idx, &rb); if (!rect) { SetRect(&default_rect, 0, 0, rb.width, rb.height); rect = &default_rect; } for (y = rect->top; y < rect->bottom; ++y) { for (x = rect->left; x < rect->right; ++x) { value = get_readback_float(&rb, x, y); if (!compare_float(value, expected_value, max_diff)) { all_match = FALSE; break; } } if (!all_match) break; } release_resource_readback(&rb); ok_(__FILE__, line)(all_match, "Got %.8e, expected %.8e at (%u, %u), sub-resource %u.\n", value, expected_value, x, y, sub_resource_idx); } #define check_texture_float(r, f, d) check_texture_float_(__LINE__, r, f, d) static void check_texture_float_(unsigned int line, ID3D11Texture2D *texture, float expected_value, BYTE max_diff) { unsigned int sub_resource_idx, sub_resource_count; D3D11_TEXTURE2D_DESC texture_desc; ID3D11Texture2D_GetDesc(texture, &texture_desc); sub_resource_count = texture_desc.ArraySize * texture_desc.MipLevels; for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) check_texture_sub_resource_float_(line, texture, sub_resource_idx, NULL, expected_value, max_diff); } #define check_texture_sub_resource_vec4(a, b, c, d, e) check_texture_sub_resource_vec4_(__LINE__, a, b, c, d, e) static void check_texture_sub_resource_vec4_(unsigned int line, ID3D11Texture2D *texture, unsigned int sub_resource_idx, const RECT *rect, const struct vec4 *expected_value, BYTE max_diff) { struct resource_readback rb; unsigned int x = 0, y = 0; struct vec4 value = {0}; BOOL all_match = TRUE; RECT default_rect; get_texture_readback(texture, sub_resource_idx, &rb); if (!rect) { SetRect(&default_rect, 0, 0, rb.width, rb.height); rect = &default_rect; } for (y = rect->top; y < rect->bottom; ++y) { for (x = rect->left; x < rect->right; ++x) { value = *get_readback_vec4(&rb, x, y); if (!compare_vec4(&value, expected_value, max_diff)) { all_match = FALSE; break; } } if (!all_match) break; } release_resource_readback(&rb); ok_(__FILE__, line)(all_match, "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e} at (%u, %u), sub-resource %u.\n", value.x, value.y, value.z, value.w, expected_value->x, expected_value->y, expected_value->z, expected_value->w, x, y, sub_resource_idx); } #define check_texture_vec4(a, b, c) check_texture_vec4_(__LINE__, a, b, c) static void check_texture_vec4_(unsigned int line, ID3D11Texture2D *texture, const struct vec4 *expected_value, BYTE max_diff) { unsigned int sub_resource_idx, sub_resource_count; D3D11_TEXTURE2D_DESC texture_desc; ID3D11Texture2D_GetDesc(texture, &texture_desc); sub_resource_count = texture_desc.ArraySize * texture_desc.MipLevels; for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) check_texture_sub_resource_vec4_(line, texture, sub_resource_idx, NULL, expected_value, max_diff); } #define check_texture_sub_resource_uvec4(a, b, c, d) check_texture_sub_resource_uvec4_(__LINE__, a, b, c, d) static void check_texture_sub_resource_uvec4_(unsigned int line, ID3D11Texture2D *texture, unsigned int sub_resource_idx, const RECT *rect, const struct uvec4 *expected_value) { struct resource_readback rb; unsigned int x = 0, y = 0; struct uvec4 value = {0}; BOOL all_match = TRUE; RECT default_rect; get_texture_readback(texture, sub_resource_idx, &rb); if (!rect) { SetRect(&default_rect, 0, 0, rb.width, rb.height); rect = &default_rect; } for (y = rect->top; y < rect->bottom; ++y) { for (x = rect->left; x < rect->right; ++x) { value = *get_readback_uvec4(&rb, x, y); if (!compare_uvec4(&value, expected_value)) { all_match = FALSE; break; } } if (!all_match) break; } release_resource_readback(&rb); ok_(__FILE__, line)(all_match, "Got {0x%08x, 0x%08x, 0x%08x, 0x%08x}, expected {0x%08x, 0x%08x, 0x%08x, 0x%08x} " "at (%u, %u), sub-resource %u.\n", value.x, value.y, value.z, value.w, expected_value->x, expected_value->y, expected_value->z, expected_value->w, x, y, sub_resource_idx); } #define check_texture_uvec4(a, b) check_texture_uvec4_(__LINE__, a, b) static void check_texture_uvec4_(unsigned int line, ID3D11Texture2D *texture, const struct uvec4 *expected_value) { unsigned int sub_resource_idx, sub_resource_count; D3D11_TEXTURE2D_DESC texture_desc; ID3D11Texture2D_GetDesc(texture, &texture_desc); sub_resource_count = texture_desc.ArraySize * texture_desc.MipLevels; for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) check_texture_sub_resource_uvec4_(line, texture, sub_resource_idx, NULL, expected_value); } static IDXGIAdapter *create_adapter(void) { IDXGIFactory4 *factory4; IDXGIFactory *factory; IDXGIAdapter *adapter; HRESULT hr; if (!use_warp_adapter && !use_adapter_idx) return NULL; if (FAILED(hr = CreateDXGIFactory1(&IID_IDXGIFactory, (void **)&factory))) { trace("Failed to create IDXGIFactory, hr %#x.\n", hr); return NULL; } adapter = NULL; if (use_warp_adapter) { if (SUCCEEDED(hr = IDXGIFactory_QueryInterface(factory, &IID_IDXGIFactory4, (void **)&factory4))) { hr = IDXGIFactory4_EnumWarpAdapter(factory4, &IID_IDXGIAdapter, (void **)&adapter); IDXGIFactory4_Release(factory4); } else { trace("Failed to get IDXGIFactory4, hr %#x.\n", hr); } } else { hr = IDXGIFactory_EnumAdapters(factory, use_adapter_idx, &adapter); } IDXGIFactory_Release(factory); if (FAILED(hr)) trace("Failed to get adapter, hr %#x.\n", hr); return adapter; } static ID3D11Device *create_device(const struct device_desc *desc) { static const D3D_FEATURE_LEVEL default_feature_level[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; const D3D_FEATURE_LEVEL *feature_level; UINT flags = desc ? desc->flags : 0; unsigned int feature_level_count; IDXGIAdapter *adapter; ID3D11Device *device; HRESULT hr; if (desc && desc->feature_level) { feature_level = desc->feature_level; feature_level_count = 1; } else { feature_level = default_feature_level; feature_level_count = ARRAY_SIZE(default_feature_level); } if (enable_debug_layer) flags |= D3D11_CREATE_DEVICE_DEBUG; if ((adapter = create_adapter())) { hr = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, feature_level, feature_level_count, D3D11_SDK_VERSION, &device, NULL, NULL); IDXGIAdapter_Release(adapter); return SUCCEEDED(hr) ? device : NULL; } if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, feature_level, feature_level_count, D3D11_SDK_VERSION, &device, NULL, NULL))) return device; if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL, flags, feature_level, feature_level_count, D3D11_SDK_VERSION, &device, NULL, NULL))) return device; if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, flags, feature_level, feature_level_count, D3D11_SDK_VERSION, &device, NULL, NULL))) return device; return NULL; } static void get_device_adapter_desc(ID3D11Device *device, DXGI_ADAPTER_DESC *adapter_desc) { IDXGIDevice *dxgi_device; IDXGIAdapter *adapter; HRESULT hr; hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); ok(SUCCEEDED(hr), "Failed to query IDXGIDevice interface, hr %#x.\n", hr); hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter); ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr); IDXGIDevice_Release(dxgi_device); hr = IDXGIAdapter_GetDesc(adapter, adapter_desc); ok(SUCCEEDED(hr), "Failed to get adapter desc, hr %#x.\n", hr); IDXGIAdapter_Release(adapter); } static void print_adapter_info(void) { DXGI_ADAPTER_DESC adapter_desc; ID3D11Device *device; if (!(device = create_device(NULL))) return; get_device_adapter_desc(device, &adapter_desc); trace("Adapter: %s, %04x:%04x.\n", wine_dbgstr_w(adapter_desc.Description), adapter_desc.VendorId, adapter_desc.DeviceId); ID3D11Device_Release(device); } static BOOL is_warp_device(ID3D11Device *device) { DXGI_ADAPTER_DESC adapter_desc; get_device_adapter_desc(device, &adapter_desc); return !adapter_desc.SubSysId && !adapter_desc.Revision && ((!adapter_desc.VendorId && !adapter_desc.DeviceId) || (adapter_desc.VendorId == 0x1414 && adapter_desc.DeviceId == 0x008c)); } static BOOL is_vendor_device(ID3D11Device *device, unsigned int vendor_id) { DXGI_ADAPTER_DESC adapter_desc; if (!strcmp(winetest_platform, "wine")) return FALSE; get_device_adapter_desc(device, &adapter_desc); return adapter_desc.VendorId == vendor_id; } static BOOL is_amd_device(ID3D11Device *device) { return is_vendor_device(device, 0x1002); } static BOOL is_intel_device(ID3D11Device *device) { return is_vendor_device(device, 0x8086); } static BOOL is_nvidia_device(ID3D11Device *device) { return is_vendor_device(device, 0x10de); } static BOOL is_d3d11_2_runtime(ID3D11Device *device) { ID3D11Device2 *device2; HRESULT hr; hr = ID3D11Device_QueryInterface(device, &IID_ID3D11Device2, (void **)&device2); if (SUCCEEDED(hr)) ID3D11Device2_Release(device2); return hr == S_OK; } static BOOL check_compute_shaders_via_sm4_support(ID3D11Device *device) { D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS options; if (FAILED(ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &options, sizeof(options)))) return FALSE; return options.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x; } static BOOL check_viewport_array_index_from_any_shader_support(ID3D11Device *device) { D3D11_FEATURE_DATA_D3D11_OPTIONS3 options; if (FAILED(ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_D3D11_OPTIONS3, &options, sizeof(options)))) return FALSE; return options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer; } static BOOL is_buffer(ID3D11Resource *resource) { D3D11_RESOURCE_DIMENSION dimension; ID3D11Resource_GetType(resource, &dimension); return dimension == D3D11_RESOURCE_DIMENSION_BUFFER; } static IDXGISwapChain *create_swapchain(ID3D11Device *device, HWND window, const struct swapchain_desc *swapchain_desc) { DXGI_SWAP_CHAIN_DESC dxgi_desc; IDXGISwapChain *swapchain; IDXGIDevice *dxgi_device; IDXGIAdapter *adapter; IDXGIFactory *factory; HRESULT hr; hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); ok(SUCCEEDED(hr), "Failed to get DXGI device, hr %#x.\n", hr); hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter); ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr); IDXGIDevice_Release(dxgi_device); hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory); ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr); IDXGIAdapter_Release(adapter); dxgi_desc.BufferDesc.Width = 640; dxgi_desc.BufferDesc.Height = 480; dxgi_desc.BufferDesc.RefreshRate.Numerator = 60; dxgi_desc.BufferDesc.RefreshRate.Denominator = 1; dxgi_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; dxgi_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; dxgi_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; dxgi_desc.SampleDesc.Count = 1; dxgi_desc.SampleDesc.Quality = 0; dxgi_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; dxgi_desc.BufferCount = 1; dxgi_desc.OutputWindow = window; dxgi_desc.Windowed = TRUE; dxgi_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; dxgi_desc.Flags = 0; if (swapchain_desc) { dxgi_desc.Windowed = swapchain_desc->windowed; dxgi_desc.SwapEffect = swapchain_desc->swap_effect; dxgi_desc.BufferCount = swapchain_desc->buffer_count; if (swapchain_desc->width) dxgi_desc.BufferDesc.Width = swapchain_desc->width; if (swapchain_desc->height) dxgi_desc.BufferDesc.Height = swapchain_desc->height; if (swapchain_desc->flags & SWAPCHAIN_FLAG_SHADER_INPUT) dxgi_desc.BufferUsage |= DXGI_USAGE_SHADER_INPUT; } hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &dxgi_desc, &swapchain); ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr); IDXGIFactory_Release(factory); return swapchain; } struct d3d11_test_context { ID3D11Device *device; HWND window; IDXGISwapChain *swapchain; ID3D11Texture2D *backbuffer; ID3D11RenderTargetView *backbuffer_rtv; ID3D11DeviceContext *immediate_context; ID3D11InputLayout *input_layout; ID3D11VertexShader *vs; const DWORD *vs_code; ID3D11Buffer *vs_cb; ID3D11Buffer *vb; ID3D11PixelShader *ps; ID3D11Buffer *ps_cb; }; #define init_test_context(a, b) init_test_context_(__LINE__, a, b, NULL) #define init_test_context_ext(a, b, c) init_test_context_(__LINE__, a, b, c) static BOOL init_test_context_(unsigned int line, struct d3d11_test_context *context, const D3D_FEATURE_LEVEL *feature_level, const struct swapchain_desc *swapchain_desc) { unsigned int rt_width, rt_height; struct device_desc device_desc; HRESULT hr; RECT rect; memset(context, 0, sizeof(*context)); device_desc.feature_level = feature_level; device_desc.flags = 0; if (!(context->device = create_device(&device_desc))) { skip_(__FILE__, line)("Failed to create device.\n"); return FALSE; } rt_width = swapchain_desc && swapchain_desc->width ? swapchain_desc->width : 640; rt_height = swapchain_desc && swapchain_desc->height ? swapchain_desc->height : 480; SetRect(&rect, 0, 0, rt_width, rt_height); AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE); context->window = CreateWindowA("static", "d3d11_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL); context->swapchain = create_swapchain(context->device, context->window, swapchain_desc); hr = IDXGISwapChain_GetBuffer(context->swapchain, 0, &IID_ID3D11Texture2D, (void **)&context->backbuffer); ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(context->device, (ID3D11Resource *)context->backbuffer, NULL, &context->backbuffer_rtv); ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); ID3D11Device_GetImmediateContext(context->device, &context->immediate_context); ID3D11DeviceContext_OMSetRenderTargets(context->immediate_context, 1, &context->backbuffer_rtv, NULL); set_viewport(context->immediate_context, 0.0f, 0.0f, rt_width, rt_height, 0.0f, 1.0f); return TRUE; } #define release_test_context(context) release_test_context_(__LINE__, context) static void release_test_context_(unsigned int line, struct d3d11_test_context *context) { ULONG ref; if (context->input_layout) ID3D11InputLayout_Release(context->input_layout); if (context->vs) ID3D11VertexShader_Release(context->vs); if (context->vs_cb) ID3D11Buffer_Release(context->vs_cb); if (context->vb) ID3D11Buffer_Release(context->vb); if (context->ps) ID3D11PixelShader_Release(context->ps); if (context->ps_cb) ID3D11Buffer_Release(context->ps_cb); ID3D11DeviceContext_Release(context->immediate_context); ID3D11RenderTargetView_Release(context->backbuffer_rtv); ID3D11Texture2D_Release(context->backbuffer); IDXGISwapChain_Release(context->swapchain); DestroyWindow(context->window); ref = ID3D11Device_Release(context->device); ok_(__FILE__, line)(!ref, "Device has %u references left.\n", ref); } #define draw_quad(context) draw_quad_vs_(__LINE__, context, NULL, 0) #define draw_quad_vs(a, b, c) draw_quad_vs_(__LINE__, a, b, c) static void draw_quad_vs_(unsigned int line, struct d3d11_test_context *context, const DWORD *vs_code, size_t vs_code_size) { static const D3D11_INPUT_ELEMENT_DESC default_layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const DWORD default_vs_code[] = { #if 0 float4 main(float4 position : POSITION) : SV_POSITION { return position; } #endif 0x43425844, 0x4fb19b86, 0x955fa240, 0x1a630688, 0x24eb9db4, 0x00000001, 0x000001e0, 0x00000006, 0x00000038, 0x00000084, 0x000000d0, 0x00000134, 0x00000178, 0x000001ac, 0x53414e58, 0x00000044, 0x00000044, 0xfffe0200, 0x00000020, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0xfffe0200, 0x0200001f, 0x80000005, 0x900f0000, 0x02000001, 0xc00f0000, 0x80e40000, 0x0000ffff, 0x50414e58, 0x00000044, 0x00000044, 0xfffe0200, 0x00000020, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0xfffe0200, 0x0200001f, 0x80000005, 0x900f0000, 0x02000001, 0xc00f0000, 0x80e40000, 0x0000ffff, 0x396e6f41, 0x0000005c, 0x0000005c, 0xfffe0200, 0x00000034, 0x00000028, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240001, 0x00000000, 0xfffe0200, 0x0200001f, 0x80000005, 0x900f0000, 0x04000004, 0xc0030000, 0x90ff0000, 0xa0e40000, 0x90e40000, 0x02000001, 0xc00c0000, 0x90e40000, 0x0000ffff, 0x52444853, 0x0000003c, 0x00010040, 0x0000000f, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, }; static const struct vec3 quad[] = { {-1.0f, -1.0f, 0.0f}, {-1.0f, 1.0f, 0.0f}, { 1.0f, -1.0f, 0.0f}, { 1.0f, 1.0f, 0.0f}, }; ID3D11Device *device = context->device; unsigned int stride, offset; HRESULT hr; if (!vs_code) { vs_code = default_vs_code; vs_code_size = sizeof(default_vs_code); } if (!context->input_layout) { hr = ID3D11Device_CreateInputLayout(device, default_layout_desc, ARRAY_SIZE(default_layout_desc), vs_code, vs_code_size, &context->input_layout); ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); } if (context->vs_code != vs_code) { if (context->vs) ID3D11VertexShader_Release(context->vs); hr = ID3D11Device_CreateVertexShader(device, vs_code, vs_code_size, NULL, &context->vs); ok_(__FILE__, line)(hr == S_OK, "Failed to create vertex shader, hr %#x.\n", hr); context->vs_code = vs_code; } if (!context->vb) context->vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(quad), quad); ID3D11DeviceContext_IASetInputLayout(context->immediate_context, context->input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context->immediate_context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); stride = sizeof(*quad); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context->immediate_context, 0, 1, &context->vb, &stride, &offset); ID3D11DeviceContext_VSSetShader(context->immediate_context, context->vs, NULL, 0); ID3D11DeviceContext_Draw(context->immediate_context, 4, 0); } #define draw_quad_z(context, z) draw_quad_z_(__LINE__, context, z) static void draw_quad_z_(unsigned int line, struct d3d11_test_context *context, float z) { static const DWORD vs_code[] = { #if 0 float depth; void main(float4 in_position : POSITION, out float4 out_position : SV_Position) { out_position = in_position; out_position.z = depth; } #endif 0x43425844, 0x22d7ff76, 0xd53b167c, 0x1b49ccf1, 0xbebfec39, 0x00000001, 0x00000100, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000b0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52444853, 0x00000064, 0x00010040, 0x00000019, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005f, 0x001010b2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x05000036, 0x001020b2, 0x00000000, 0x00101c46, 0x00000000, 0x06000036, 0x00102042, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; struct vec4 data = {z}; if (!context->vs_cb) context->vs_cb = create_buffer(context->device, D3D11_BIND_CONSTANT_BUFFER, sizeof(data), NULL); ID3D11DeviceContext_UpdateSubresource(context->immediate_context, (ID3D11Resource *)context->vs_cb, 0, NULL, &data, 0, 0); ID3D11DeviceContext_VSSetConstantBuffers(context->immediate_context, 0, 1, &context->vs_cb); draw_quad_vs_(__LINE__, context, vs_code, sizeof(vs_code)); } static void set_quad_color(struct d3d11_test_context *context, const struct vec4 *color) { ID3D11DeviceContext_UpdateSubresource(context->immediate_context, (ID3D11Resource *)context->ps_cb, 0, NULL, color, 0, 0); } #define draw_color_quad(a, b) draw_color_quad_(__LINE__, a, b, NULL, 0) #define draw_color_quad_vs(a, b, c, d) draw_color_quad_(__LINE__, a, b, c, d) static void draw_color_quad_(unsigned int line, struct d3d11_test_context *context, const struct vec4 *color, const DWORD *vs_code, size_t vs_code_size) { static const DWORD ps_color_code[] = { #if 0 float4 color; float4 main() : SV_TARGET { return color; } #endif 0x43425844, 0xe7ffb369, 0x72bb84ee, 0x6f684dcd, 0xd367d788, 0x00000001, 0x00000158, 0x00000005, 0x00000034, 0x00000080, 0x000000cc, 0x00000114, 0x00000124, 0x53414e58, 0x00000044, 0x00000044, 0xffff0200, 0x00000014, 0x00000030, 0x00240001, 0x00300000, 0x00300000, 0x00240000, 0x00300000, 0x00000000, 0x00000001, 0x00000000, 0xffff0200, 0x02000001, 0x800f0800, 0xa0e40000, 0x0000ffff, 0x396e6f41, 0x00000044, 0x00000044, 0xffff0200, 0x00000014, 0x00000030, 0x00240001, 0x00300000, 0x00300000, 0x00240000, 0x00300000, 0x00000000, 0x00000001, 0x00000000, 0xffff0200, 0x02000001, 0x800f0800, 0xa0e40000, 0x0000ffff, 0x52444853, 0x00000040, 0x00000040, 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, }; ID3D11Device *device = context->device; HRESULT hr; if (!context->ps) { hr = ID3D11Device_CreatePixelShader(device, ps_color_code, sizeof(ps_color_code), NULL, &context->ps); ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); } if (!context->ps_cb) context->ps_cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(*color), NULL); ID3D11DeviceContext_PSSetShader(context->immediate_context, context->ps, NULL, 0); ID3D11DeviceContext_PSSetConstantBuffers(context->immediate_context, 0, 1, &context->ps_cb); set_quad_color(context, color); draw_quad_vs_(line, context, vs_code, vs_code_size); } static void test_create_device(void) { static const D3D_FEATURE_LEVEL default_feature_levels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, }; D3D_FEATURE_LEVEL feature_level, supported_feature_level; DXGI_SWAP_CHAIN_DESC swapchain_desc, obtained_desc; ID3D11DeviceContext *immediate_context; IDXGISwapChain *swapchain; ID3D11Device *device; ULONG refcount; HWND window; HRESULT hr; if (FAILED(hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, NULL))) { skip("Failed to create HAL device.\n"); if ((device = create_device(NULL))) { trace("Feature level %#x.\n", ID3D11Device_GetFeatureLevel(device)); ID3D11Device_Release(device); } return; } supported_feature_level = ID3D11Device_GetFeatureLevel(device); trace("Feature level %#x.\n", supported_feature_level); ID3D11Device_Release(device); hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, NULL, NULL, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, NULL, &feature_level, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); ok(feature_level == supported_feature_level, "Got feature level %#x, expected %#x.\n", feature_level, supported_feature_level); hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, default_feature_levels, ARRAY_SIZE(default_feature_levels), D3D11_SDK_VERSION, NULL, &feature_level, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); ok(feature_level == supported_feature_level, "Got feature level %#x, expected %#x.\n", feature_level, supported_feature_level); hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, NULL, NULL, &immediate_context); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(!!immediate_context, "Expected immediate device context pointer, got NULL.\n"); refcount = get_refcount(immediate_context); ok(refcount == 1, "Got refcount %u, expected 1.\n", refcount); ID3D11DeviceContext_GetDevice(immediate_context, &device); refcount = ID3D11Device_Release(device); ok(refcount == 1, "Got refcount %u, expected 1.\n", refcount); refcount = ID3D11DeviceContext_Release(immediate_context); ok(!refcount, "ID3D11DeviceContext has %u references left.\n", refcount); device = (ID3D11Device *)0xdeadbeef; feature_level = 0xdeadbeef; immediate_context = (ID3D11DeviceContext *)0xdeadbeef; hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, &feature_level, &immediate_context); todo_wine ok(hr == E_INVALIDARG, "D3D11CreateDevice returned %#x.\n", hr); ok(!device, "Got unexpected device pointer %p.\n", device); ok(!feature_level, "Got unexpected feature level %#x.\n", feature_level); ok(!immediate_context, "Got unexpected immediate context pointer %p.\n", immediate_context); window = CreateWindowA("static", "d3d11_test", 0, 0, 0, 0, 0, 0, 0, 0, 0); swapchain_desc.BufferDesc.Width = 800; swapchain_desc.BufferDesc.Height = 600; swapchain_desc.BufferDesc.RefreshRate.Numerator = 60; swapchain_desc.BufferDesc.RefreshRate.Denominator = 60; swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; swapchain_desc.SampleDesc.Count = 1; swapchain_desc.SampleDesc.Quality = 0; swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapchain_desc.BufferCount = 1; swapchain_desc.OutputWindow = window; swapchain_desc.Windowed = TRUE; swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swapchain_desc.Flags = 0; hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swapchain_desc, NULL, NULL, NULL, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swapchain_desc, NULL, NULL, &feature_level, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); ok(feature_level == supported_feature_level, "Got feature level %#x, expected %#x.\n", feature_level, supported_feature_level); hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swapchain_desc, &swapchain, &device, NULL, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); check_interface(swapchain, &IID_IDXGISwapChain1, TRUE, FALSE); memset(&obtained_desc, 0, sizeof(obtained_desc)); hr = IDXGISwapChain_GetDesc(swapchain, &obtained_desc); ok(SUCCEEDED(hr), "GetDesc failed %#x.\n", hr); ok(obtained_desc.BufferDesc.Width == swapchain_desc.BufferDesc.Width, "Got unexpected BufferDesc.Width %u.\n", obtained_desc.BufferDesc.Width); ok(obtained_desc.BufferDesc.Height == swapchain_desc.BufferDesc.Height, "Got unexpected BufferDesc.Height %u.\n", obtained_desc.BufferDesc.Height); todo_wine ok(obtained_desc.BufferDesc.RefreshRate.Numerator == swapchain_desc.BufferDesc.RefreshRate.Numerator, "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n", obtained_desc.BufferDesc.RefreshRate.Numerator); todo_wine ok(obtained_desc.BufferDesc.RefreshRate.Denominator == swapchain_desc.BufferDesc.RefreshRate.Denominator, "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n", obtained_desc.BufferDesc.RefreshRate.Denominator); ok(obtained_desc.BufferDesc.Format == swapchain_desc.BufferDesc.Format, "Got unexpected BufferDesc.Format %#x.\n", obtained_desc.BufferDesc.Format); ok(obtained_desc.BufferDesc.ScanlineOrdering == swapchain_desc.BufferDesc.ScanlineOrdering, "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", obtained_desc.BufferDesc.ScanlineOrdering); ok(obtained_desc.BufferDesc.Scaling == swapchain_desc.BufferDesc.Scaling, "Got unexpected BufferDesc.Scaling %#x.\n", obtained_desc.BufferDesc.Scaling); ok(obtained_desc.SampleDesc.Count == swapchain_desc.SampleDesc.Count, "Got unexpected SampleDesc.Count %u.\n", obtained_desc.SampleDesc.Count); ok(obtained_desc.SampleDesc.Quality == swapchain_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", obtained_desc.SampleDesc.Quality); ok(obtained_desc.BufferUsage == swapchain_desc.BufferUsage, "Got unexpected BufferUsage %#x.\n", obtained_desc.BufferUsage); ok(obtained_desc.BufferCount == swapchain_desc.BufferCount, "Got unexpected BufferCount %u.\n", obtained_desc.BufferCount); ok(obtained_desc.OutputWindow == swapchain_desc.OutputWindow, "Got unexpected OutputWindow %p.\n", obtained_desc.OutputWindow); ok(obtained_desc.Windowed == swapchain_desc.Windowed, "Got unexpected Windowed %#x.\n", obtained_desc.Windowed); ok(obtained_desc.SwapEffect == swapchain_desc.SwapEffect, "Got unexpected SwapEffect %#x.\n", obtained_desc.SwapEffect); ok(obtained_desc.Flags == swapchain_desc.Flags, "Got unexpected Flags %#x.\n", obtained_desc.Flags); refcount = IDXGISwapChain_Release(swapchain); ok(!refcount, "Swapchain has %u references left.\n", refcount); feature_level = ID3D11Device_GetFeatureLevel(device); ok(feature_level == supported_feature_level, "Got feature level %#x, expected %#x.\n", feature_level, supported_feature_level); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, NULL, NULL, &device, NULL, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11Device_Release(device); hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, NULL, NULL, NULL, NULL, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, NULL, NULL, NULL, &feature_level, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); ok(feature_level == supported_feature_level, "Got feature level %#x, expected %#x.\n", feature_level, supported_feature_level); hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, NULL, NULL, NULL, NULL, &immediate_context); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_Release(immediate_context); hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swapchain_desc, NULL, NULL, NULL, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swapchain_desc, &swapchain, NULL, NULL, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); IDXGISwapChain_Release(swapchain); swapchain_desc.OutputWindow = NULL; hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swapchain_desc, NULL, NULL, NULL, NULL); ok(hr == S_FALSE, "D3D11CreateDeviceAndSwapChain returned %#x.\n", hr); hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swapchain_desc, NULL, &device, NULL, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11Device_Release(device); swapchain = (IDXGISwapChain *)0xdeadbeef; device = (ID3D11Device *)0xdeadbeef; feature_level = 0xdeadbeef; immediate_context = (ID3D11DeviceContext *)0xdeadbeef; swapchain_desc.OutputWindow = NULL; hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swapchain_desc, &swapchain, &device, &feature_level, &immediate_context); ok(hr == DXGI_ERROR_INVALID_CALL, "D3D11CreateDeviceAndSwapChain returned %#x.\n", hr); ok(!swapchain, "Got unexpected swapchain pointer %p.\n", swapchain); ok(!device, "Got unexpected device pointer %p.\n", device); ok(!feature_level, "Got unexpected feature level %#x.\n", feature_level); ok(!immediate_context, "Got unexpected immediate context pointer %p.\n", immediate_context); swapchain = (IDXGISwapChain *)0xdeadbeef; device = (ID3D11Device *)0xdeadbeef; feature_level = 0xdeadbeef; immediate_context = (ID3D11DeviceContext *)0xdeadbeef; swapchain_desc.OutputWindow = window; swapchain_desc.BufferDesc.Format = DXGI_FORMAT_BC5_UNORM; hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swapchain_desc, &swapchain, &device, &feature_level, &immediate_context); ok(hr == E_INVALIDARG, "D3D11CreateDeviceAndSwapChain returned %#x.\n", hr); ok(!swapchain, "Got unexpected swapchain pointer %p.\n", swapchain); ok(!device, "Got unexpected device pointer %p.\n", device); ok(!feature_level, "Got unexpected feature level %#x.\n", feature_level); ok(!immediate_context, "Got unexpected immediate context pointer %p.\n", immediate_context); DestroyWindow(window); } static void test_device_interfaces(const D3D_FEATURE_LEVEL feature_level) { struct device_desc device_desc; IDXGIAdapter *dxgi_adapter; IDXGIDevice *dxgi_device; ID3D11Device *device; IUnknown *iface; ULONG refcount; HRESULT hr; device_desc.feature_level = &feature_level; device_desc.flags = 0; if (!(device = create_device(&device_desc))) { skip("Failed to create device for feature level %#x.\n", feature_level); return; } check_interface(device, &IID_IUnknown, TRUE, FALSE); check_interface(device, &IID_IDXGIObject, TRUE, FALSE); check_interface(device, &IID_IDXGIDevice, TRUE, FALSE); check_interface(device, &IID_IDXGIDevice1, TRUE, FALSE); check_interface(device, &IID_ID3D10Multithread, TRUE, TRUE); /* Not available on all Windows versions. */ check_interface(device, &IID_ID3D10Device, FALSE, FALSE); check_interface(device, &IID_ID3D10Device1, FALSE, FALSE); check_interface(device, &IID_ID3D11InfoQueue, enable_debug_layer, FALSE); hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); ok(SUCCEEDED(hr), "Device should implement IDXGIDevice.\n"); hr = IDXGIDevice_GetParent(dxgi_device, &IID_IDXGIAdapter, (void **)&dxgi_adapter); ok(SUCCEEDED(hr), "Device parent should implement IDXGIAdapter.\n"); hr = IDXGIAdapter_GetParent(dxgi_adapter, &IID_IDXGIFactory, (void **)&iface); ok(SUCCEEDED(hr), "Adapter parent should implement IDXGIFactory.\n"); IUnknown_Release(iface); IDXGIAdapter_Release(dxgi_adapter); hr = IDXGIDevice_GetParent(dxgi_device, &IID_IDXGIAdapter1, (void **)&dxgi_adapter); ok(SUCCEEDED(hr), "Device parent should implement IDXGIAdapter1.\n"); hr = IDXGIAdapter_GetParent(dxgi_adapter, &IID_IDXGIFactory1, (void **)&iface); ok(SUCCEEDED(hr), "Adapter parent should implement IDXGIFactory1.\n"); IUnknown_Release(iface); IDXGIAdapter_Release(dxgi_adapter); IDXGIDevice_Release(dxgi_device); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); device_desc.feature_level = &feature_level; device_desc.flags = D3D11_CREATE_DEVICE_DEBUG; if (!(device = create_device(&device_desc))) { skip("Failed to create debug device for feature level %#x.\n", feature_level); return; } todo_wine check_interface(device, &IID_ID3D11InfoQueue, TRUE, FALSE); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_immediate_context(void) { ID3D11DeviceContext *immediate_context, *previous_immediate_context; ULONG expected_refcount, refcount; ID3D11CommandList *command_list; ID3D11Multithread *multithread; ID3D11Buffer *buffer[2]; ID3D11Device *device; unsigned int flags; BOOL enabled; HRESULT hr; static const unsigned int buffer_contents[] = { 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888, }; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } expected_refcount = get_refcount(device) + 1; ID3D11Device_GetImmediateContext(device, &immediate_context); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u.\n", refcount); previous_immediate_context = immediate_context; ID3D11Device_GetImmediateContext(device, &immediate_context); ok(immediate_context == previous_immediate_context, "Got different immediate device context objects.\n"); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u.\n", refcount); refcount = ID3D11DeviceContext_Release(previous_immediate_context); ok(refcount == 1, "Got unexpected refcount %u.\n", refcount); refcount = ID3D11DeviceContext_Release(immediate_context); ok(!refcount, "Got unexpected refcount %u.\n", refcount); ID3D11Device_GetImmediateContext(device, &immediate_context); ok(immediate_context == previous_immediate_context, "Got different immediate device context objects.\n"); refcount = ID3D11DeviceContext_Release(immediate_context); ok(!refcount, "Got unexpected refcount %u.\n", refcount); ID3D11Device_GetImmediateContext(device, &immediate_context); expected_refcount = get_refcount(immediate_context) + 1; hr = ID3D11DeviceContext_QueryInterface(immediate_context, &IID_ID3D11Multithread, (void **)&multithread); if (hr == E_NOINTERFACE) { win_skip("ID3D11Multithread is not supported.\n"); goto done; } ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); refcount = get_refcount(immediate_context); ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount); expected_refcount = refcount; refcount = get_refcount(multithread); ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount); enabled = ID3D11Multithread_GetMultithreadProtected(multithread); todo_wine ok(!enabled, "Multithread protection is %#x.\n", enabled); ID3D11Multithread_Release(multithread); ID3D11Device_GetImmediateContext(device, &immediate_context); flags = ID3D11DeviceContext_GetContextFlags(immediate_context); ok(!flags, "Got unexpected flags %#x.\n", flags); hr = ID3D11DeviceContext_FinishCommandList(immediate_context, FALSE, &command_list); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); buffer[0] = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, 16, &buffer_contents[0]); buffer[1] = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, 16, &buffer_contents[4]); ID3D11DeviceContext_CopyResource(immediate_context, (ID3D11Resource *)buffer[1], (ID3D11Resource *)buffer[0]); hr = ID3D11DeviceContext_FinishCommandList(immediate_context, FALSE, &command_list); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ID3D11Buffer_Release(buffer[1]); ID3D11Buffer_Release(buffer[0]); ID3D11DeviceContext_Release(immediate_context); done: refcount = ID3D11DeviceContext_Release(immediate_context); ok(!refcount, "Got unexpected refcount %u.\n", refcount); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_deferred_context(void) { ULONG refcount, expected_refcount; struct device_desc device_desc; ID3D11DeviceContext *context; ID3D11Device *device; HRESULT hr; device_desc.feature_level = NULL; device_desc.flags = D3D11_CREATE_DEVICE_SINGLETHREADED; if (!(device = create_device(&device_desc))) { skip("Failed to create single-threaded device.\n"); return; } hr = ID3D11Device_CreateDeferredContext(device, 0, &context); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Failed to create deferred context, hr %#x.\n", hr); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateDeferredContext(device, 0, &context); todo_wine ok(hr == S_OK, "Failed to create deferred context, hr %#x.\n", hr); if (FAILED(hr)) goto done; refcount = get_refcount(device); ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount); refcount = get_refcount(context); ok(refcount == 1, "Got unexpected refcount %u.\n", refcount); check_interface(context, &IID_IUnknown, TRUE, FALSE); check_interface(context, &IID_ID3D11DeviceChild, TRUE, FALSE); check_interface(context, &IID_ID3D11DeviceContext, TRUE, FALSE); check_interface(context, &IID_ID3D11Multithread, FALSE, FALSE); refcount = ID3D11DeviceContext_Release(context); ok(!refcount, "Got unexpected refcount %u.\n", refcount); done: refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_texture1d(void) { ULONG refcount, expected_refcount; D3D11_SUBRESOURCE_DATA data = {0}; ID3D11Device *device, *tmp; D3D11_TEXTURE1D_DESC desc; ID3D11Texture1D *texture; unsigned int i; HRESULT hr; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } desc.Width = 512; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture1D(device, &desc, &data, &texture); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateTexture1D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 1d texture, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11Texture1D_GetDevice(texture, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); check_interface(texture, &IID_IDXGISurface, TRUE, FALSE); ID3D11Texture1D_Release(texture); desc.MipLevels = 0; expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateTexture1D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 1d texture, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11Texture1D_GetDevice(texture, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); ID3D11Texture1D_GetDesc(texture, &desc); ok(desc.Width == 512, "Got unexpected Width %u.\n", desc.Width); ok(desc.MipLevels == 10, "Got unexpected MipLevels %u.\n", desc.MipLevels); ok(desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", desc.ArraySize); ok(desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", desc.Format); ok(desc.Usage == D3D11_USAGE_DEFAULT, "Got unexpected Usage %u.\n", desc.Usage); ok(desc.BindFlags == D3D11_BIND_SHADER_RESOURCE, "Got unexpected BindFlags %#x.\n", desc.BindFlags); ok(desc.CPUAccessFlags == 0, "Got unexpected CPUAccessFlags %#x.\n", desc.CPUAccessFlags); ok(desc.MiscFlags == 0, "Got unexpected MiscFlags %#x.\n", desc.MiscFlags); check_interface(texture, &IID_IDXGISurface, FALSE, FALSE); ID3D11Texture1D_Release(texture); desc.MipLevels = 1; desc.ArraySize = 2; hr = ID3D11Device_CreateTexture1D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 1d texture, hr %#x.\n", hr); check_interface(texture, &IID_IDXGISurface, FALSE, FALSE); ID3D11Texture1D_Release(texture); for (i = 0; i < 4; ++i) { desc.ArraySize = i; desc.Format = DXGI_FORMAT_R32G32B32A32_TYPELESS; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture1D(device, &desc, NULL, &texture); ok(hr == (i ? S_OK : E_INVALIDARG), "Test %u: Got unexpected hr %#x.\n", i, hr); if (SUCCEEDED(hr)) ID3D11Texture1D_Release(texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_texture1d_interfaces(void) { ID3D10Texture1D *d3d10_texture; D3D11_TEXTURE1D_DESC desc; ID3D11Texture1D *texture; ID3D11Device *device; unsigned int i; ULONG refcount; HRESULT hr; static const struct test { BOOL implements_d3d10_interfaces; UINT bind_flags; UINT misc_flags; UINT expected_bind_flags; UINT expected_misc_flags; } desc_conversion_tests[] = { { TRUE, D3D11_BIND_SHADER_RESOURCE, 0, D3D10_BIND_SHADER_RESOURCE, 0 }, { TRUE, D3D11_BIND_UNORDERED_ACCESS, 0, D3D11_BIND_UNORDERED_ACCESS, 0 }, { FALSE, 0, D3D11_RESOURCE_MISC_RESOURCE_CLAMP, 0, 0 }, { TRUE, 0, D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX, 0, D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX }, }; if (!(device = create_device(NULL))) { skip("Failed to create ID3D11Device, skipping tests.\n"); return; } desc.Width = 512; desc.MipLevels = 0; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture1D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 1d texture, hr %#x.\n", hr); check_interface(texture, &IID_IDXGISurface, FALSE, FALSE); hr = check_interface(texture, &IID_ID3D10Texture1D, TRUE, TRUE); /* Not available on all Windows versions. */ ID3D11Texture1D_Release(texture); if (FAILED(hr)) { win_skip("1D textures do not implement ID3D10Texture1D, skipping tests.\n"); ID3D11Device_Release(device); return; } for (i = 0; i < ARRAY_SIZE(desc_conversion_tests); ++i) { const struct test *current = &desc_conversion_tests[i]; D3D10_TEXTURE1D_DESC d3d10_desc; ID3D10Device *d3d10_device; desc.Width = 512; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = current->bind_flags; desc.CPUAccessFlags = 0; desc.MiscFlags = current->misc_flags; hr = ID3D11Device_CreateTexture1D(device, &desc, NULL, &texture); /* Shared resources are not supported by REF and WARP devices. */ ok(SUCCEEDED(hr) || broken(hr == E_OUTOFMEMORY), "Test %u: Failed to create a 1d texture, hr %#x.\n", i, hr); if (FAILED(hr)) { win_skip("Failed to create ID3D11Texture1D, skipping test %u.\n", i); continue; } check_interface(texture, &IID_IDXGISurface, TRUE, FALSE); hr = ID3D11Texture1D_QueryInterface(texture, &IID_ID3D10Texture1D, (void **)&d3d10_texture); ID3D11Texture1D_Release(texture); if (current->implements_d3d10_interfaces) { ok(SUCCEEDED(hr), "Test %u: Texture should implement ID3D10Texture1D.\n", i); } else { todo_wine ok(hr == E_NOINTERFACE, "Test %u: Texture should not implement ID3D10Texture1D.\n", i); if (SUCCEEDED(hr)) ID3D10Texture1D_Release(d3d10_texture); continue; } ID3D10Texture1D_GetDesc(d3d10_texture, &d3d10_desc); ok(d3d10_desc.Width == desc.Width, "Test %u: Got unexpected Width %u.\n", i, d3d10_desc.Width); ok(d3d10_desc.MipLevels == desc.MipLevels, "Test %u: Got unexpected MipLevels %u.\n", i, d3d10_desc.MipLevels); ok(d3d10_desc.ArraySize == desc.ArraySize, "Test %u: Got unexpected ArraySize %u.\n", i, d3d10_desc.ArraySize); ok(d3d10_desc.Format == desc.Format, "Test %u: Got unexpected Format %u.\n", i, d3d10_desc.Format); ok(d3d10_desc.BindFlags == current->expected_bind_flags, "Test %u: Got unexpected BindFlags %#x.\n", i, d3d10_desc.BindFlags); ok(d3d10_desc.CPUAccessFlags == desc.CPUAccessFlags, "Test %u: Got unexpected CPUAccessFlags %#x.\n", i, d3d10_desc.CPUAccessFlags); ok(d3d10_desc.MiscFlags == current->expected_misc_flags, "Test %u: Got unexpected MiscFlags %#x.\n", i, d3d10_desc.MiscFlags); d3d10_device = (ID3D10Device *)0xdeadbeef; ID3D10Texture1D_GetDevice(d3d10_texture, &d3d10_device); ok(!d3d10_device, "Test %u: Got unexpected device pointer %p, expected NULL.\n", i, d3d10_device); if (d3d10_device) ID3D10Device_Release(d3d10_device); ID3D10Texture1D_Release(d3d10_texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_texture2d(void) { ULONG refcount, expected_refcount; D3D11_SUBRESOURCE_DATA data = {0}; D3D_FEATURE_LEVEL feature_level; ID3D11Device *device, *tmp; D3D11_TEXTURE2D_DESC desc; ID3D11Texture2D *texture; UINT quality_level_count; unsigned int i; HRESULT hr; static const struct { DXGI_FORMAT format; UINT array_size; D3D11_BIND_FLAG bind_flags; UINT misc_flags; BOOL succeeds; BOOL todo; } tests[] = { {DXGI_FORMAT_R32G32B32A32_TYPELESS, 1, D3D11_BIND_VERTEX_BUFFER, 0, FALSE, TRUE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 1, D3D11_BIND_INDEX_BUFFER, 0, FALSE, TRUE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 1, D3D11_BIND_CONSTANT_BUFFER, 0, FALSE, TRUE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 0, D3D11_BIND_SHADER_RESOURCE, 0, FALSE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 2, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 3, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 3, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_TEXTURECUBE, FALSE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_TEXTURECUBE, FALSE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 5, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_TEXTURECUBE, FALSE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 6, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_TEXTURECUBE, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 7, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_TEXTURECUBE, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 10, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_TEXTURECUBE, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 12, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_TEXTURECUBE, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 0, D3D11_BIND_RENDER_TARGET, 0, FALSE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 2, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 9, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, 1, D3D11_BIND_DEPTH_STENCIL, 0, FALSE, FALSE}, {DXGI_FORMAT_R32G32B32A32_UINT, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32A32_SINT, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G32B32_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R16G16B16A16_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R16G16B16A16_TYPELESS, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G32_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G8X24_TYPELESS, 1, D3D11_BIND_DEPTH_STENCIL, 0, TRUE, FALSE}, {DXGI_FORMAT_R32G8X24_TYPELESS, 1, D3D11_BIND_UNORDERED_ACCESS, 0, FALSE, TRUE}, {DXGI_FORMAT_X32_TYPELESS_G8X24_UINT, 1, D3D11_BIND_UNORDERED_ACCESS, 0, FALSE, TRUE}, {DXGI_FORMAT_R10G10B10A2_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R10G10B10A2_TYPELESS, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R16G16_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R16G16_UNORM, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R16G16_SNORM, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R32_TYPELESS, 0, D3D11_BIND_SHADER_RESOURCE, 0, FALSE, FALSE}, {DXGI_FORMAT_R32_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R32_TYPELESS, 9, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R32_TYPELESS, 9, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL, 0, TRUE, FALSE}, {DXGI_FORMAT_R32_TYPELESS, 9, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_TEXTURECUBE, TRUE, FALSE}, {DXGI_FORMAT_R32_TYPELESS, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R32_TYPELESS, 1, D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL, 0, FALSE, TRUE}, {DXGI_FORMAT_R32_TYPELESS, 1, D3D11_BIND_DEPTH_STENCIL, 0, TRUE, FALSE}, {DXGI_FORMAT_R32_TYPELESS, 1, D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_UNORDERED_ACCESS, 0, FALSE, TRUE}, {DXGI_FORMAT_R24G8_TYPELESS, 1, D3D11_BIND_VERTEX_BUFFER, 0, FALSE, TRUE}, {DXGI_FORMAT_R24G8_TYPELESS, 1, D3D11_BIND_INDEX_BUFFER, 0, FALSE, TRUE}, {DXGI_FORMAT_R24G8_TYPELESS, 1, D3D11_BIND_CONSTANT_BUFFER, 0, FALSE, TRUE}, {DXGI_FORMAT_R24G8_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R24G8_TYPELESS, 1, D3D11_BIND_DEPTH_STENCIL, 0, TRUE, FALSE}, {DXGI_FORMAT_R24G8_TYPELESS, 1, D3D11_BIND_UNORDERED_ACCESS, 0, FALSE, TRUE}, {DXGI_FORMAT_X24_TYPELESS_G8_UINT, 1, D3D11_BIND_UNORDERED_ACCESS, 0, FALSE, TRUE}, {DXGI_FORMAT_R8G8_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8_TYPELESS, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8_UNORM, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8_SNORM, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R16_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R16_TYPELESS, 1, D3D11_BIND_DEPTH_STENCIL, 0, TRUE, FALSE}, {DXGI_FORMAT_R16_TYPELESS, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R16_UINT, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R16_SINT, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R8_TYPELESS, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8B8A8_UNORM, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8B8A8_UNORM, 1, D3D11_BIND_DEPTH_STENCIL, 0, FALSE, FALSE}, {DXGI_FORMAT_R8G8B8A8_UINT, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8B8A8_SNORM, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8B8A8_SINT, 1, D3D11_BIND_RENDER_TARGET, 0, TRUE, FALSE}, {DXGI_FORMAT_D24_UNORM_S8_UINT, 1, D3D11_BIND_SHADER_RESOURCE, 0, FALSE, TRUE}, {DXGI_FORMAT_D24_UNORM_S8_UINT, 1, D3D11_BIND_RENDER_TARGET, 0, FALSE, FALSE}, {DXGI_FORMAT_D32_FLOAT, 1, D3D11_BIND_SHADER_RESOURCE, 0, FALSE, TRUE}, {DXGI_FORMAT_D32_FLOAT, 1, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL, 0, FALSE, TRUE}, {DXGI_FORMAT_D32_FLOAT, 1, D3D11_BIND_RENDER_TARGET, 0, FALSE, FALSE}, {DXGI_FORMAT_D32_FLOAT, 1, D3D11_BIND_DEPTH_STENCIL, 0, TRUE, FALSE}, {DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 1, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, FALSE}, {DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 1, D3D11_BIND_RENDER_TARGET, 0, FALSE, FALSE}, {DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 1, D3D11_BIND_DEPTH_STENCIL, 0, FALSE, FALSE}, }; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } feature_level = ID3D11Device_GetFeatureLevel(device); desc.Width = 512; desc.Height = 512; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &desc, &data, &texture); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11Texture2D_GetDevice(texture, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); check_interface(texture, &IID_IDXGISurface, TRUE, FALSE); ID3D11Texture2D_Release(texture); desc.MipLevels = 0; expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11Texture2D_GetDevice(texture, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); ID3D11Texture2D_GetDesc(texture, &desc); ok(desc.Width == 512, "Got unexpected Width %u.\n", desc.Width); ok(desc.Height == 512, "Got unexpected Height %u.\n", desc.Height); ok(desc.MipLevels == 10, "Got unexpected MipLevels %u.\n", desc.MipLevels); ok(desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", desc.ArraySize); ok(desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", desc.Format); ok(desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", desc.SampleDesc.Count); ok(desc.SampleDesc.Quality == 0, "Got unexpected SampleDesc.Quality %u.\n", desc.SampleDesc.Quality); ok(desc.Usage == D3D11_USAGE_DEFAULT, "Got unexpected Usage %u.\n", desc.Usage); ok(desc.BindFlags == D3D11_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", desc.BindFlags); ok(desc.CPUAccessFlags == 0, "Got unexpected CPUAccessFlags %#x.\n", desc.CPUAccessFlags); ok(desc.MiscFlags == 0, "Got unexpected MiscFlags %#x.\n", desc.MiscFlags); check_interface(texture, &IID_IDXGISurface, FALSE, FALSE); ID3D11Texture2D_Release(texture); desc.MipLevels = 1; desc.ArraySize = 2; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); check_interface(texture, &IID_IDXGISurface, FALSE, FALSE); ID3D11Texture2D_Release(texture); hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 2, &quality_level_count); ok(hr == S_OK, "Failed to check multisample quality levels, hr %#x.\n", hr); desc.ArraySize = 1; desc.SampleDesc.Count = 2; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); if (quality_level_count) { ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); ID3D11Texture2D_Release(texture); desc.SampleDesc.Quality = quality_level_count; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); } ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); /* We assume 15 samples multisampling is never supported in practice. */ desc.SampleDesc.Count = 15; desc.SampleDesc.Quality = 0; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); desc.SampleDesc.Count = 1; for (i = 0; i < ARRAY_SIZE(tests); ++i) { HRESULT expected_hr = tests[i].succeeds ? S_OK : E_INVALIDARG; BOOL todo = tests[i].todo; if (feature_level < D3D_FEATURE_LEVEL_10_1 && (tests[i].misc_flags & D3D11_RESOURCE_MISC_TEXTURECUBE) && tests[i].array_size > 6) { expected_hr = E_INVALIDARG; todo = TRUE; } desc.ArraySize = tests[i].array_size; desc.Format = tests[i].format; desc.BindFlags = tests[i].bind_flags; desc.MiscFlags = tests[i].misc_flags; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); todo_wine_if(todo) ok(hr == expected_hr, "Test %u: Got unexpected hr %#x (format %#x).\n", i, hr, desc.Format); if (SUCCEEDED(hr)) ID3D11Texture2D_Release(texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_texture2d_interfaces(void) { ID3D10Texture2D *d3d10_texture; D3D11_TEXTURE2D_DESC desc; ID3D11Texture2D *texture; ID3D11Device *device; unsigned int i; ULONG refcount; HRESULT hr; static const struct test { BOOL implements_d3d10_interfaces; UINT bind_flags; UINT misc_flags; UINT expected_bind_flags; UINT expected_misc_flags; } desc_conversion_tests[] = { { TRUE, D3D11_BIND_SHADER_RESOURCE, 0, D3D10_BIND_SHADER_RESOURCE, 0 }, { TRUE, D3D11_BIND_UNORDERED_ACCESS, 0, D3D11_BIND_UNORDERED_ACCESS, 0 }, { FALSE, 0, D3D11_RESOURCE_MISC_RESOURCE_CLAMP, 0, 0 }, { TRUE, 0, D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX, 0, D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX }, { TRUE, 0, D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_SHARED_NTHANDLE, 0, D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX }, }; if (!(device = create_device(NULL))) { skip("Failed to create ID3D11Device, skipping tests.\n"); return; } desc.Width = 512; desc.Height = 512; desc.MipLevels = 0; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); check_interface(texture, &IID_IDXGISurface, FALSE, FALSE); hr = check_interface(texture, &IID_ID3D10Texture2D, TRUE, TRUE); /* Not available on all Windows versions. */ ID3D11Texture2D_Release(texture); if (FAILED(hr)) { win_skip("2D textures do not implement ID3D10Texture2D, skipping tests.\n"); ID3D11Device_Release(device); return; } for (i = 0; i < ARRAY_SIZE(desc_conversion_tests); ++i) { const struct test *current = &desc_conversion_tests[i]; D3D10_TEXTURE2D_DESC d3d10_desc; ID3D10Device *d3d10_device; desc.Width = 512; desc.Height = 512; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = current->bind_flags; desc.CPUAccessFlags = 0; desc.MiscFlags = current->misc_flags; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); /* Shared resources are not supported by REF and WARP devices. */ ok(SUCCEEDED(hr) || broken(hr == E_OUTOFMEMORY), "Test %u: Failed to create a 2d texture, hr %#x.\n", i, hr); if (FAILED(hr)) { win_skip("Failed to create ID3D11Texture2D, skipping test %u.\n", i); continue; } check_interface(texture, &IID_IDXGISurface, TRUE, FALSE); hr = ID3D11Texture2D_QueryInterface(texture, &IID_ID3D10Texture2D, (void **)&d3d10_texture); ID3D11Texture2D_Release(texture); if (current->implements_d3d10_interfaces) { ok(SUCCEEDED(hr), "Test %u: Texture should implement ID3D10Texture2D.\n", i); } else { todo_wine ok(hr == E_NOINTERFACE, "Test %u: Texture should not implement ID3D10Texture2D.\n", i); if (SUCCEEDED(hr)) ID3D10Texture2D_Release(d3d10_texture); continue; } ID3D10Texture2D_GetDesc(d3d10_texture, &d3d10_desc); ok(d3d10_desc.Width == desc.Width, "Test %u: Got unexpected Width %u.\n", i, d3d10_desc.Width); ok(d3d10_desc.Height == desc.Height, "Test %u: Got unexpected Height %u.\n", i, d3d10_desc.Height); ok(d3d10_desc.MipLevels == desc.MipLevels, "Test %u: Got unexpected MipLevels %u.\n", i, d3d10_desc.MipLevels); ok(d3d10_desc.ArraySize == desc.ArraySize, "Test %u: Got unexpected ArraySize %u.\n", i, d3d10_desc.ArraySize); ok(d3d10_desc.Format == desc.Format, "Test %u: Got unexpected Format %u.\n", i, d3d10_desc.Format); ok(d3d10_desc.SampleDesc.Count == desc.SampleDesc.Count, "Test %u: Got unexpected SampleDesc.Count %u.\n", i, d3d10_desc.SampleDesc.Count); ok(d3d10_desc.SampleDesc.Quality == desc.SampleDesc.Quality, "Test %u: Got unexpected SampleDesc.Quality %u.\n", i, d3d10_desc.SampleDesc.Quality); ok(d3d10_desc.Usage == (D3D10_USAGE)desc.Usage, "Test %u: Got unexpected Usage %u.\n", i, d3d10_desc.Usage); ok(d3d10_desc.BindFlags == current->expected_bind_flags, "Test %u: Got unexpected BindFlags %#x.\n", i, d3d10_desc.BindFlags); ok(d3d10_desc.CPUAccessFlags == desc.CPUAccessFlags, "Test %u: Got unexpected CPUAccessFlags %#x.\n", i, d3d10_desc.CPUAccessFlags); ok(d3d10_desc.MiscFlags == current->expected_misc_flags, "Test %u: Got unexpected MiscFlags %#x.\n", i, d3d10_desc.MiscFlags); d3d10_device = (ID3D10Device *)0xdeadbeef; ID3D10Texture2D_GetDevice(d3d10_texture, &d3d10_device); ok(!d3d10_device, "Test %u: Got unexpected device pointer %p, expected NULL.\n", i, d3d10_device); if (d3d10_device) ID3D10Device_Release(d3d10_device); ID3D10Texture2D_Release(d3d10_texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_texture3d(void) { ULONG refcount, expected_refcount; D3D11_SUBRESOURCE_DATA data = {0}; ID3D11Device *device, *tmp; D3D11_TEXTURE3D_DESC desc; ID3D11Texture3D *texture; unsigned int i; HRESULT hr; static const struct { DXGI_FORMAT format; D3D11_BIND_FLAG bind_flags; BOOL succeeds; BOOL todo; } tests[] = { {DXGI_FORMAT_R32G32B32A32_TYPELESS, D3D11_BIND_VERTEX_BUFFER, FALSE, TRUE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, D3D11_BIND_INDEX_BUFFER, FALSE, TRUE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, D3D11_BIND_CONSTANT_BUFFER, FALSE, TRUE}, {DXGI_FORMAT_R32G32B32A32_TYPELESS, D3D11_BIND_SHADER_RESOURCE, TRUE, FALSE}, {DXGI_FORMAT_R16G16B16A16_TYPELESS, D3D11_BIND_SHADER_RESOURCE, TRUE, FALSE}, {DXGI_FORMAT_R10G10B10A2_TYPELESS, D3D11_BIND_SHADER_RESOURCE, TRUE, FALSE}, {DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_DEPTH_STENCIL, FALSE, FALSE}, {DXGI_FORMAT_D24_UNORM_S8_UINT, D3D11_BIND_RENDER_TARGET, FALSE, FALSE}, {DXGI_FORMAT_D32_FLOAT, D3D11_BIND_RENDER_TARGET, FALSE, FALSE}, {DXGI_FORMAT_R9G9B9E5_SHAREDEXP, D3D11_BIND_SHADER_RESOURCE, TRUE, FALSE}, {DXGI_FORMAT_R9G9B9E5_SHAREDEXP, D3D11_BIND_RENDER_TARGET, FALSE, FALSE}, {DXGI_FORMAT_R9G9B9E5_SHAREDEXP, D3D11_BIND_DEPTH_STENCIL, FALSE, FALSE}, }; if (!(device = create_device(NULL))) { skip("Failed to create ID3D11Device, skipping tests.\n"); return; } desc.Width = 64; desc.Height = 64; desc.Depth = 64; desc.MipLevels = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture3D(device, &desc, &data, &texture); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateTexture3D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 3d texture, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11Texture3D_GetDevice(texture, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); check_interface(texture, &IID_IDXGISurface, FALSE, FALSE); ID3D11Texture3D_Release(texture); desc.MipLevels = 0; expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateTexture3D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 3d texture, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11Texture3D_GetDevice(texture, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); ID3D11Texture3D_GetDesc(texture, &desc); ok(desc.Width == 64, "Got unexpected Width %u.\n", desc.Width); ok(desc.Height == 64, "Got unexpected Height %u.\n", desc.Height); ok(desc.Depth == 64, "Got unexpected Depth %u.\n", desc.Depth); ok(desc.MipLevels == 7, "Got unexpected MipLevels %u.\n", desc.MipLevels); ok(desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", desc.Format); ok(desc.Usage == D3D11_USAGE_DEFAULT, "Got unexpected Usage %u.\n", desc.Usage); ok(desc.BindFlags == D3D11_BIND_RENDER_TARGET, "Got unexpected BindFlags %u.\n", desc.BindFlags); ok(desc.CPUAccessFlags == 0, "Got unexpected CPUAccessFlags %u.\n", desc.CPUAccessFlags); ok(desc.MiscFlags == 0, "Got unexpected MiscFlags %u.\n", desc.MiscFlags); check_interface(texture, &IID_IDXGISurface, FALSE, FALSE); ID3D11Texture3D_Release(texture); desc.MipLevels = 1; for (i = 0; i < ARRAY_SIZE(tests); ++i) { desc.Format = tests[i].format; desc.BindFlags = tests[i].bind_flags; hr = ID3D11Device_CreateTexture3D(device, &desc, NULL, &texture); todo_wine_if(tests[i].todo) ok(hr == (tests[i].succeeds ? S_OK : E_INVALIDARG), "Test %u: Got unexpected hr %#x.\n", i, hr); if (SUCCEEDED(hr)) ID3D11Texture3D_Release(texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_texture3d_interfaces(void) { ID3D10Texture3D *d3d10_texture; D3D11_TEXTURE3D_DESC desc; ID3D11Texture3D *texture; ID3D11Device *device; unsigned int i; ULONG refcount; HRESULT hr; static const struct test { BOOL implements_d3d10_interfaces; UINT bind_flags; UINT misc_flags; UINT expected_bind_flags; UINT expected_misc_flags; } desc_conversion_tests[] = { { TRUE, D3D11_BIND_SHADER_RESOURCE, 0, D3D10_BIND_SHADER_RESOURCE, 0 }, { TRUE, D3D11_BIND_UNORDERED_ACCESS, 0, D3D11_BIND_UNORDERED_ACCESS, 0 }, { FALSE, 0, D3D11_RESOURCE_MISC_RESOURCE_CLAMP, 0, 0 }, { TRUE, 0, D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX, 0, D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX }, }; if (!(device = create_device(NULL))) { skip("Failed to create ID3D11Device.\n"); return; } desc.Width = 64; desc.Height = 64; desc.Depth = 64; desc.MipLevels = 0; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture3D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 3d texture, hr %#x.\n", hr); check_interface(texture, &IID_IDXGISurface, FALSE, FALSE); hr = check_interface(texture, &IID_ID3D10Texture3D, TRUE, TRUE); /* Not available on all Windows versions. */ ID3D11Texture3D_Release(texture); if (FAILED(hr)) { win_skip("3D textures do not implement ID3D10Texture3D.\n"); ID3D11Device_Release(device); return; } for (i = 0; i < ARRAY_SIZE(desc_conversion_tests); ++i) { const struct test *current = &desc_conversion_tests[i]; D3D10_TEXTURE3D_DESC d3d10_desc; ID3D10Device *d3d10_device; desc.Width = 64; desc.Height = 64; desc.Depth = 64; desc.MipLevels = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = current->bind_flags; desc.CPUAccessFlags = 0; desc.MiscFlags = current->misc_flags; hr = ID3D11Device_CreateTexture3D(device, &desc, NULL, &texture); /* Shared resources are not supported by REF and WARP devices. */ ok(SUCCEEDED(hr) || broken(hr == E_OUTOFMEMORY), "Test %u: Failed to create a 3d texture, hr %#x.\n", i, hr); if (FAILED(hr)) { win_skip("Failed to create ID3D11Texture3D, skipping test %u.\n", i); continue; } check_interface(texture, &IID_IDXGISurface, FALSE, FALSE); hr = ID3D11Texture3D_QueryInterface(texture, &IID_ID3D10Texture3D, (void **)&d3d10_texture); ID3D11Texture3D_Release(texture); if (current->implements_d3d10_interfaces) { ok(SUCCEEDED(hr), "Test %u: Texture should implement ID3D10Texture3D.\n", i); } else { todo_wine ok(hr == E_NOINTERFACE, "Test %u: Texture should not implement ID3D10Texture3D.\n", i); if (SUCCEEDED(hr)) ID3D10Texture3D_Release(d3d10_texture); continue; } ID3D10Texture3D_GetDesc(d3d10_texture, &d3d10_desc); ok(d3d10_desc.Width == desc.Width, "Test %u: Got unexpected Width %u.\n", i, d3d10_desc.Width); ok(d3d10_desc.Height == desc.Height, "Test %u: Got unexpected Height %u.\n", i, d3d10_desc.Height); ok(d3d10_desc.Depth == desc.Depth, "Test %u: Got unexpected Depth %u.\n", i, d3d10_desc.Depth); ok(d3d10_desc.MipLevels == desc.MipLevels, "Test %u: Got unexpected MipLevels %u.\n", i, d3d10_desc.MipLevels); ok(d3d10_desc.Format == desc.Format, "Test %u: Got unexpected Format %u.\n", i, d3d10_desc.Format); ok(d3d10_desc.Usage == (D3D10_USAGE)desc.Usage, "Test %u: Got unexpected Usage %u.\n", i, d3d10_desc.Usage); ok(d3d10_desc.BindFlags == current->expected_bind_flags, "Test %u: Got unexpected BindFlags %#x.\n", i, d3d10_desc.BindFlags); ok(d3d10_desc.CPUAccessFlags == desc.CPUAccessFlags, "Test %u: Got unexpected CPUAccessFlags %#x.\n", i, d3d10_desc.CPUAccessFlags); ok(d3d10_desc.MiscFlags == current->expected_misc_flags, "Test %u: Got unexpected MiscFlags %#x.\n", i, d3d10_desc.MiscFlags); d3d10_device = (ID3D10Device *)0xdeadbeef; ID3D10Texture3D_GetDevice(d3d10_texture, &d3d10_device); ok(!d3d10_device, "Test %u: Got unexpected device pointer %p, expected NULL.\n", i, d3d10_device); if (d3d10_device) ID3D10Device_Release(d3d10_device); ID3D10Texture3D_Release(d3d10_texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_buffer(void) { ID3D10Buffer *d3d10_buffer; HRESULT expected_hr, hr; D3D11_BUFFER_DESC desc; ID3D11Buffer *buffer; ID3D11Device *device; unsigned int i; ULONG refcount; static const struct test { BOOL succeeds; BOOL implements_d3d10_interfaces; UINT bind_flags; UINT misc_flags; UINT structure_stride; UINT expected_bind_flags; UINT expected_misc_flags; } tests[] = { { TRUE, TRUE, D3D11_BIND_VERTEX_BUFFER, 0, 0, D3D10_BIND_VERTEX_BUFFER, 0 }, { TRUE, TRUE, D3D11_BIND_INDEX_BUFFER, 0, 0, D3D10_BIND_INDEX_BUFFER, 0 }, { TRUE, TRUE, D3D11_BIND_CONSTANT_BUFFER, 0, 0, D3D10_BIND_CONSTANT_BUFFER, 0 }, { TRUE, TRUE, D3D11_BIND_SHADER_RESOURCE, 0, 0, D3D10_BIND_SHADER_RESOURCE, 0 }, { TRUE, TRUE, D3D11_BIND_STREAM_OUTPUT, 0, 0, D3D10_BIND_STREAM_OUTPUT, 0 }, { TRUE, TRUE, D3D11_BIND_RENDER_TARGET, 0, 0, D3D10_BIND_RENDER_TARGET, 0 }, { TRUE, TRUE, D3D11_BIND_UNORDERED_ACCESS, 0, 0, D3D11_BIND_UNORDERED_ACCESS, 0 }, { TRUE, TRUE, 0, D3D11_RESOURCE_MISC_SHARED, 0, 0, D3D10_RESOURCE_MISC_SHARED }, { TRUE, TRUE, 0, D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS, 0, 0, 0 }, { FALSE, FALSE, D3D11_BIND_VERTEX_BUFFER, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS, 0, }, { FALSE, FALSE, D3D11_BIND_INDEX_BUFFER, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS, 0, }, { FALSE, FALSE, D3D11_BIND_CONSTANT_BUFFER, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS, 0, }, { TRUE, TRUE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS, 0, D3D10_BIND_SHADER_RESOURCE, 0 }, { FALSE, FALSE, D3D11_BIND_STREAM_OUTPUT, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS, 0, }, { FALSE, FALSE, D3D11_BIND_RENDER_TARGET, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS, 0, }, { TRUE, TRUE, D3D11_BIND_UNORDERED_ACCESS, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS, 0, D3D11_BIND_UNORDERED_ACCESS, 0 }, { FALSE, FALSE, 0, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS, 0, }, /* Structured buffers do not implement ID3D10Buffer. */ { TRUE, FALSE, 0, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 16, }, { TRUE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 16, }, { FALSE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, ~0u, }, { FALSE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 0, }, { FALSE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 1, }, { FALSE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 2, }, { FALSE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 3, }, { TRUE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 4, }, { FALSE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 5, }, { TRUE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 8, }, { TRUE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 512, }, { FALSE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 513, }, { TRUE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 1024, }, { TRUE, TRUE, 0, 0, 513, 0, 0 }, { TRUE, TRUE, D3D11_BIND_CONSTANT_BUFFER, 0, 513, D3D10_BIND_CONSTANT_BUFFER, 0 }, { TRUE, TRUE, D3D11_BIND_SHADER_RESOURCE, 0, 513, D3D10_BIND_SHADER_RESOURCE, 0 }, { TRUE, TRUE, D3D11_BIND_UNORDERED_ACCESS, 0, 513, D3D11_BIND_UNORDERED_ACCESS, 0 }, { FALSE, FALSE, 0, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS | D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 16, }, { FALSE, FALSE, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS | D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 16, }, { TRUE, TRUE, 0, D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX, 0, 0, D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX }, }; if (!(device = create_device(NULL))) { skip("Failed to create ID3D11Device.\n"); return; } buffer = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, 1024, NULL); hr = check_interface(buffer, &IID_ID3D10Buffer, TRUE, TRUE); /* Not available on all Windows versions. */ ID3D11Buffer_Release(buffer); if (FAILED(hr)) { win_skip("Buffers do not implement ID3D10Buffer.\n"); ID3D11Device_Release(device); return; } for (i = 0; i < ARRAY_SIZE(tests); ++i) { const struct test *current = &tests[i]; D3D11_BUFFER_DESC obtained_desc; D3D10_BUFFER_DESC d3d10_desc; ID3D10Device *d3d10_device; desc.ByteWidth = 1024; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = current->bind_flags; desc.CPUAccessFlags = 0; desc.MiscFlags = current->misc_flags; desc.StructureByteStride = current->structure_stride; hr = ID3D11Device_CreateBuffer(device, &desc, NULL, &buffer); expected_hr = current->succeeds ? S_OK : E_INVALIDARG; /* Shared resources are not supported by REF and WARP devices. */ ok(hr == expected_hr || broken(hr == E_OUTOFMEMORY), "Test %u: Got hr %#x, expected %#x.\n", i, hr, expected_hr); if (FAILED(hr)) { if (hr == E_OUTOFMEMORY) win_skip("Failed to create a buffer, skipping test %u.\n", i); continue; } if (!(desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED)) desc.StructureByteStride = 0; ID3D11Buffer_GetDesc(buffer, &obtained_desc); ok(obtained_desc.ByteWidth == desc.ByteWidth, "Test %u: Got unexpected ByteWidth %u.\n", i, obtained_desc.ByteWidth); ok(obtained_desc.Usage == desc.Usage, "Test %u: Got unexpected Usage %u.\n", i, obtained_desc.Usage); ok(obtained_desc.BindFlags == desc.BindFlags, "Test %u: Got unexpected BindFlags %#x.\n", i, obtained_desc.BindFlags); ok(obtained_desc.CPUAccessFlags == desc.CPUAccessFlags, "Test %u: Got unexpected CPUAccessFlags %#x.\n", i, obtained_desc.CPUAccessFlags); ok(obtained_desc.MiscFlags == desc.MiscFlags, "Test %u: Got unexpected MiscFlags %#x.\n", i, obtained_desc.MiscFlags); ok(obtained_desc.StructureByteStride == desc.StructureByteStride, "Test %u: Got unexpected StructureByteStride %u.\n", i, obtained_desc.StructureByteStride); hr = ID3D11Buffer_QueryInterface(buffer, &IID_ID3D10Buffer, (void **)&d3d10_buffer); ID3D11Buffer_Release(buffer); if (current->implements_d3d10_interfaces) { ok(SUCCEEDED(hr), "Test %u: Buffer should implement ID3D10Buffer.\n", i); } else { todo_wine ok(hr == E_NOINTERFACE, "Test %u: Buffer should not implement ID3D10Buffer.\n", i); if (SUCCEEDED(hr)) ID3D10Buffer_Release(d3d10_buffer); continue; } ID3D10Buffer_GetDesc(d3d10_buffer, &d3d10_desc); ok(d3d10_desc.ByteWidth == desc.ByteWidth, "Test %u: Got unexpected ByteWidth %u.\n", i, d3d10_desc.ByteWidth); ok(d3d10_desc.Usage == (D3D10_USAGE)desc.Usage, "Test %u: Got unexpected Usage %u.\n", i, d3d10_desc.Usage); ok(d3d10_desc.BindFlags == current->expected_bind_flags, "Test %u: Got unexpected BindFlags %#x.\n", i, d3d10_desc.BindFlags); ok(d3d10_desc.CPUAccessFlags == desc.CPUAccessFlags, "Test %u: Got unexpected CPUAccessFlags %#x.\n", i, d3d10_desc.CPUAccessFlags); ok(d3d10_desc.MiscFlags == current->expected_misc_flags, "Test %u: Got unexpected MiscFlags %#x.\n", i, d3d10_desc.MiscFlags); d3d10_device = (ID3D10Device *)0xdeadbeef; ID3D10Buffer_GetDevice(d3d10_buffer, &d3d10_device); ok(!d3d10_device, "Test %u: Got unexpected device pointer %p, expected NULL.\n", i, d3d10_device); if (d3d10_device) ID3D10Device_Release(d3d10_device); ID3D10Buffer_Release(d3d10_buffer); } memset(&desc, 0, sizeof(desc)); desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; for (i = 0; i <= 32; ++i) { desc.ByteWidth = i; expected_hr = !i || i % 16 ? E_INVALIDARG : S_OK; hr = ID3D11Device_CreateBuffer(device, &desc, NULL, &buffer); ok(hr == expected_hr, "Got unexpected hr %#x for constant buffer size %u.\n", hr, i); if (SUCCEEDED(hr)) ID3D11Buffer_Release(buffer); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_depthstencil_view(void) { D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc; D3D11_TEXTURE2D_DESC texture_desc; ULONG refcount, expected_refcount; ID3D11DepthStencilView *dsview; ID3D11Device *device, *tmp; ID3D11Texture2D *texture; unsigned int i; HRESULT hr; #define FMT_UNKNOWN DXGI_FORMAT_UNKNOWN #define D24S8 DXGI_FORMAT_D24_UNORM_S8_UINT #define R24G8_TL DXGI_FORMAT_R24G8_TYPELESS #define DIM_UNKNOWN D3D11_DSV_DIMENSION_UNKNOWN #define TEX_1D D3D11_DSV_DIMENSION_TEXTURE1D #define TEX_1D_ARRAY D3D11_DSV_DIMENSION_TEXTURE1DARRAY #define TEX_2D D3D11_DSV_DIMENSION_TEXTURE2D #define TEX_2D_ARRAY D3D11_DSV_DIMENSION_TEXTURE2DARRAY #define TEX_2DMS D3D11_DSV_DIMENSION_TEXTURE2DMS #define TEX_2DMS_ARR D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY static const struct { struct { unsigned int miplevel_count; unsigned int array_size; DXGI_FORMAT format; } texture; struct dsv_desc dsv_desc; struct dsv_desc expected_dsv_desc; } tests[] = { {{ 1, 1, D24S8}, {0}, {D24S8, TEX_2D, 0}}, {{10, 1, D24S8}, {0}, {D24S8, TEX_2D, 0}}, {{10, 1, D24S8}, {FMT_UNKNOWN, TEX_2D, 0}, {D24S8, TEX_2D, 0}}, {{10, 1, D24S8}, {FMT_UNKNOWN, TEX_2D, 1}, {D24S8, TEX_2D, 1}}, {{10, 1, D24S8}, {FMT_UNKNOWN, TEX_2D, 9}, {D24S8, TEX_2D, 9}}, {{ 1, 1, R24G8_TL}, {D24S8, TEX_2D, 0}, {D24S8, TEX_2D, 0}}, {{10, 1, R24G8_TL}, {D24S8, TEX_2D, 0}, {D24S8, TEX_2D, 0}}, {{ 1, 4, D24S8}, {0}, {D24S8, TEX_2D_ARRAY, 0, 0, 4}}, {{10, 4, D24S8}, {0}, {D24S8, TEX_2D_ARRAY, 0, 0, 4}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 0, ~0u}, {D24S8, TEX_2D_ARRAY, 0, 0, 4}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2D_ARRAY, 1, 0, ~0u}, {D24S8, TEX_2D_ARRAY, 1, 0, 4}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2D_ARRAY, 3, 0, ~0u}, {D24S8, TEX_2D_ARRAY, 3, 0, 4}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2D_ARRAY, 5, 0, ~0u}, {D24S8, TEX_2D_ARRAY, 5, 0, 4}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2D_ARRAY, 9, 0, ~0u}, {D24S8, TEX_2D_ARRAY, 9, 0, 4}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 1, ~0u}, {D24S8, TEX_2D_ARRAY, 0, 1, 3}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 2, ~0u}, {D24S8, TEX_2D_ARRAY, 0, 2, 2}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 3, ~0u}, {D24S8, TEX_2D_ARRAY, 0, 3, 1}}, {{ 1, 1, D24S8}, {FMT_UNKNOWN, TEX_2DMS}, {D24S8, TEX_2DMS}}, {{ 1, 4, D24S8}, {FMT_UNKNOWN, TEX_2DMS}, {D24S8, TEX_2DMS}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2DMS}, {D24S8, TEX_2DMS}}, {{ 1, 1, D24S8}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, 1}, {D24S8, TEX_2DMS_ARR, 0, 0, 1}}, {{ 1, 1, D24S8}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, ~0u}, {D24S8, TEX_2DMS_ARR, 0, 0, 1}}, {{10, 1, D24S8}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, 1}, {D24S8, TEX_2DMS_ARR, 0, 0, 1}}, {{10, 1, D24S8}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, ~0u}, {D24S8, TEX_2DMS_ARR, 0, 0, 1}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, 1}, {D24S8, TEX_2DMS_ARR, 0, 0, 1}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, 4}, {D24S8, TEX_2DMS_ARR, 0, 0, 4}}, {{10, 4, D24S8}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, ~0u}, {D24S8, TEX_2DMS_ARR, 0, 0, 4}}, }; static const struct { struct { unsigned int miplevel_count; unsigned int array_size; DXGI_FORMAT format; } texture; struct dsv_desc dsv_desc; } invalid_desc_tests[] = { {{1, 1, D24S8}, {D24S8, DIM_UNKNOWN}}, {{6, 4, D24S8}, {D24S8, DIM_UNKNOWN}}, {{1, 1, D24S8}, {D24S8, TEX_1D, 0}}, {{1, 1, D24S8}, {D24S8, TEX_1D_ARRAY, 0, 0, 1}}, {{1, 1, D24S8}, {R24G8_TL, TEX_2D, 0}}, {{1, 1, R24G8_TL}, {FMT_UNKNOWN, TEX_2D, 0}}, {{1, 1, D24S8}, {D24S8, TEX_2D, 1}}, {{1, 1, D24S8}, {D24S8, TEX_2D_ARRAY, 0, 0, 0}}, {{1, 1, D24S8}, {D24S8, TEX_2D_ARRAY, 1, 0, 1}}, {{1, 1, D24S8}, {D24S8, TEX_2D_ARRAY, 0, 0, 2}}, {{1, 1, D24S8}, {D24S8, TEX_2D_ARRAY, 0, 1, 1}}, {{1, 1, D24S8}, {D24S8, TEX_2DMS_ARR, 0, 0, 2}}, {{1, 1, D24S8}, {D24S8, TEX_2DMS_ARR, 0, 1, 1}}, }; #undef FMT_UNKNOWN #undef D24S8 #undef R24G8_TL #undef DIM_UNKNOWN #undef TEX_1D #undef TEX_1D_ARRAY #undef TEX_2D #undef TEX_2D_ARRAY #undef TEX_2DMS #undef TEX_2DMS_ARR if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } texture_desc.Width = 512; texture_desc.Height = 512; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, NULL, &dsview); ok(SUCCEEDED(hr), "Failed to create a depthstencil view, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11DepthStencilView_GetDevice(dsview, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); memset(&dsv_desc, 0, sizeof(dsv_desc)); ID3D11DepthStencilView_GetDesc(dsview, &dsv_desc); ok(dsv_desc.Format == texture_desc.Format, "Got unexpected format %#x.\n", dsv_desc.Format); ok(dsv_desc.ViewDimension == D3D11_DSV_DIMENSION_TEXTURE2D, "Got unexpected view dimension %#x.\n", dsv_desc.ViewDimension); ok(!dsv_desc.Flags, "Got unexpected flags %#x.\n", dsv_desc.Flags); ok(!U(dsv_desc).Texture2D.MipSlice, "Got unexpected mip slice %u.\n", U(dsv_desc).Texture2D.MipSlice); ID3D11DepthStencilView_Release(dsview); ID3D11Texture2D_Release(texture); for (i = 0; i < ARRAY_SIZE(tests); ++i) { D3D11_DEPTH_STENCIL_VIEW_DESC *current_desc; texture_desc.MipLevels = tests[i].texture.miplevel_count; texture_desc.ArraySize = tests[i].texture.array_size; texture_desc.Format = tests[i].texture.format; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); if (tests[i].dsv_desc.dimension == D3D11_DSV_DIMENSION_UNKNOWN) { current_desc = NULL; } else { current_desc = &dsv_desc; get_dsv_desc(current_desc, &tests[i].dsv_desc); } expected_refcount = get_refcount(texture); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, current_desc, &dsview); ok(SUCCEEDED(hr), "Test %u: Failed to create depth stencil view, hr %#x.\n", i, hr); refcount = get_refcount(texture); ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount); /* Not available on all Windows versions. */ check_interface(dsview, &IID_ID3D10DepthStencilView, TRUE, TRUE); memset(&dsv_desc, 0, sizeof(dsv_desc)); ID3D11DepthStencilView_GetDesc(dsview, &dsv_desc); check_dsv_desc(&dsv_desc, &tests[i].expected_dsv_desc); ID3D11DepthStencilView_Release(dsview); ID3D11Texture2D_Release(texture); } for (i = 0; i < ARRAY_SIZE(invalid_desc_tests); ++i) { texture_desc.MipLevels = invalid_desc_tests[i].texture.miplevel_count; texture_desc.ArraySize = invalid_desc_tests[i].texture.array_size; texture_desc.Format = invalid_desc_tests[i].texture.format; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); get_dsv_desc(&dsv_desc, &invalid_desc_tests[i].dsv_desc); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, &dsv_desc, &dsview); ok(hr == E_INVALIDARG, "Test %u: Got unexpected hr %#x.\n", i, hr); ID3D11Texture2D_Release(texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_depthstencil_view_interfaces(void) { D3D10_DEPTH_STENCIL_VIEW_DESC d3d10_dsv_desc; D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc; ID3D10DepthStencilView *d3d10_dsview; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DepthStencilView *dsview; ID3D11Texture2D *texture; ID3D11Device *device; ULONG refcount; HRESULT hr; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } texture_desc.Width = 512; texture_desc.Height = 512; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); dsv_desc.Format = texture_desc.Format; dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; dsv_desc.Flags = 0; U(dsv_desc).Texture2D.MipSlice = 0; hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, &dsv_desc, &dsview); ok(SUCCEEDED(hr), "Failed to create a depthstencil view, hr %#x.\n", hr); hr = ID3D11DepthStencilView_QueryInterface(dsview, &IID_ID3D10DepthStencilView, (void **)&d3d10_dsview); ID3D11DepthStencilView_Release(dsview); ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, "Depth stencil view should implement ID3D10DepthStencilView.\n"); if (FAILED(hr)) { win_skip("Depth stencil view does not implement ID3D10DepthStencilView.\n"); goto done; } ID3D10DepthStencilView_GetDesc(d3d10_dsview, &d3d10_dsv_desc); ok(d3d10_dsv_desc.Format == dsv_desc.Format, "Got unexpected format %#x.\n", d3d10_dsv_desc.Format); ok(d3d10_dsv_desc.ViewDimension == (D3D10_DSV_DIMENSION)dsv_desc.ViewDimension, "Got unexpected view dimension %u.\n", d3d10_dsv_desc.ViewDimension); ok(U(d3d10_dsv_desc).Texture2D.MipSlice == U(dsv_desc).Texture2D.MipSlice, "Got unexpected mip slice %u.\n", U(d3d10_dsv_desc).Texture2D.MipSlice); ID3D10DepthStencilView_Release(d3d10_dsview); done: ID3D11Texture2D_Release(texture); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_rendertarget_view(void) { D3D11_RENDER_TARGET_VIEW_DESC rtv_desc; D3D11_TEXTURE3D_DESC texture3d_desc; D3D11_TEXTURE2D_DESC texture2d_desc; D3D11_SUBRESOURCE_DATA data = {0}; ULONG refcount, expected_refcount; D3D11_BUFFER_DESC buffer_desc; ID3D11RenderTargetView *rtview; ID3D11Device *device, *tmp; ID3D11Texture3D *texture3d; ID3D11Texture2D *texture2d; ID3D11Resource *texture; ID3D11Buffer *buffer; unsigned int i; HRESULT hr; #define FMT_UNKNOWN DXGI_FORMAT_UNKNOWN #define RGBA8_UNORM DXGI_FORMAT_R8G8B8A8_UNORM #define RGBA8_TL DXGI_FORMAT_R8G8B8A8_TYPELESS #define DIM_UNKNOWN D3D11_RTV_DIMENSION_UNKNOWN #define TEX_1D D3D11_RTV_DIMENSION_TEXTURE1D #define TEX_1D_ARRAY D3D11_RTV_DIMENSION_TEXTURE1DARRAY #define TEX_2D D3D11_RTV_DIMENSION_TEXTURE2D #define TEX_2D_ARRAY D3D11_RTV_DIMENSION_TEXTURE2DARRAY #define TEX_2DMS D3D11_RTV_DIMENSION_TEXTURE2DMS #define TEX_2DMS_ARR D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY #define TEX_3D D3D11_RTV_DIMENSION_TEXTURE3D static const struct { struct { unsigned int miplevel_count; unsigned int depth_or_array_size; DXGI_FORMAT format; } texture; struct rtv_desc rtv_desc; struct rtv_desc expected_rtv_desc; } tests[] = { {{ 1, 1, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_2D, 0}}, {{10, 1, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_2D, 0}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D, 0}, {RGBA8_UNORM, TEX_2D, 0}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D, 1}, {RGBA8_UNORM, TEX_2D, 1}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D, 9}, {RGBA8_UNORM, TEX_2D, 9}}, {{ 1, 1, RGBA8_TL}, {RGBA8_UNORM, TEX_2D, 0}, {RGBA8_UNORM, TEX_2D, 0}}, {{10, 1, RGBA8_TL}, {RGBA8_UNORM, TEX_2D, 0}, {RGBA8_UNORM, TEX_2D, 0}}, {{ 1, 4, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 4}}, {{10, 4, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 1, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 1, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 3, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 3, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 5, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 5, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 9, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 9, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 1, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 1, 3}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 2, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 2, 2}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 3, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 3, 1}}, {{ 1, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS}, {RGBA8_UNORM, TEX_2DMS}}, {{ 1, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS}, {RGBA8_UNORM, TEX_2DMS}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS}, {RGBA8_UNORM, TEX_2DMS}}, {{ 1, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, 1}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 0, 1}}, {{ 1, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, ~0u}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 0, 1}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, 1}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 0, 1}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, ~0u}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 0, 1}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, 1}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 0, 1}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, 4}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 0, ~0u}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 0, 4}}, {{ 1, 6, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_3D, 0, 0, 6}}, {{ 2, 6, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_3D, 0, 0, 6}}, {{ 2, 6, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 0, 6}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 1, 0, 2}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 1, 0, 2}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 1, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 1, 3}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 2, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 2, 2}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 3, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 3, 1}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 1, 1}, {RGBA8_UNORM, TEX_3D, 0, 1, 1}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 1, 1}, {RGBA8_UNORM, TEX_3D, 1, 1, 1}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 1, ~0u}, {RGBA8_UNORM, TEX_3D, 1, 1, 1}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 0, 8}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 1, 0, 4}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 2, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 2, 0, 2}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 3, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 3, 0, 1}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 4, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 4, 0, 1}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 5, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 5, 0, 1}}, }; static const struct { struct { D3D11_RTV_DIMENSION dimension; unsigned int miplevel_count; unsigned int depth_or_array_size; DXGI_FORMAT format; } texture; struct rtv_desc rtv_desc; } invalid_desc_tests[] = { {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, DIM_UNKNOWN}}, {{TEX_2D, 6, 4, RGBA8_UNORM}, {RGBA8_UNORM, DIM_UNKNOWN}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, ~0u}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_TL, TEX_2D, 0}}, {{TEX_2D, 1, 1, RGBA8_TL}, {FMT_UNKNOWN, TEX_2D, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 1, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 2}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 1, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 0, 2}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 1, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, 0}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 1, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_TL, TEX_3D, 0, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_TL, TEX_3D, 0, 0, 1}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, 9}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 3, 0, 2}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 2, 0, 4}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 1, 0, 8}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 8, ~0u}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 1, 4, ~0u}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 2, 2, ~0u}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 3, 1, ~0u}}, }; #undef FMT_UNKNOWN #undef RGBA8_UNORM #undef RGBA8_TL #undef DIM_UNKNOWN #undef TEX_1D #undef TEX_1D_ARRAY #undef TEX_2D #undef TEX_2D_ARRAY #undef TEX_2DMS #undef TEX_2DMS_ARR #undef TEX_3D if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } buffer_desc.ByteWidth = 1024; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_RENDER_TARGET; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = 0; buffer_desc.StructureByteStride = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, &data, &buffer); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11Buffer_GetDevice(buffer, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); rtv_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER; U1(U(rtv_desc).Buffer).ElementOffset = 0; U2(U(rtv_desc).Buffer).ElementWidth = 64; if (!enable_debug_layer) { hr = ID3D11Device_CreateRenderTargetView(device, NULL, &rtv_desc, &rtview); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); } expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)buffer, &rtv_desc, &rtview); ok(SUCCEEDED(hr), "Failed to create a rendertarget view, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11RenderTargetView_GetDevice(rtview, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); /* Not available on all Windows versions. */ check_interface(rtview, &IID_ID3D10RenderTargetView, TRUE, TRUE); ID3D11RenderTargetView_Release(rtview); ID3D11Buffer_Release(buffer); texture2d_desc.Width = 512; texture2d_desc.Height = 512; texture2d_desc.SampleDesc.Count = 1; texture2d_desc.SampleDesc.Quality = 0; texture2d_desc.Usage = D3D11_USAGE_DEFAULT; texture2d_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture2d_desc.CPUAccessFlags = 0; texture2d_desc.MiscFlags = 0; texture3d_desc.Width = 64; texture3d_desc.Height = 64; texture3d_desc.Usage = D3D11_USAGE_DEFAULT; texture3d_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture3d_desc.CPUAccessFlags = 0; texture3d_desc.MiscFlags = 0; for (i = 0; i < ARRAY_SIZE(tests); ++i) { D3D11_RENDER_TARGET_VIEW_DESC *current_desc; if (tests[i].expected_rtv_desc.dimension != D3D11_RTV_DIMENSION_TEXTURE3D) { texture2d_desc.MipLevels = tests[i].texture.miplevel_count; texture2d_desc.ArraySize = tests[i].texture.depth_or_array_size; texture2d_desc.Format = tests[i].texture.format; hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, NULL, &texture2d); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture2d; } else { texture3d_desc.MipLevels = tests[i].texture.miplevel_count; texture3d_desc.Depth = tests[i].texture.depth_or_array_size; texture3d_desc.Format = tests[i].texture.format; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, &texture3d); ok(SUCCEEDED(hr), "Test %u: Failed to create 3d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture3d; } if (tests[i].rtv_desc.dimension == D3D11_RTV_DIMENSION_UNKNOWN) { current_desc = NULL; } else { current_desc = &rtv_desc; get_rtv_desc(current_desc, &tests[i].rtv_desc); } expected_refcount = get_refcount(texture); hr = ID3D11Device_CreateRenderTargetView(device, texture, current_desc, &rtview); ok(SUCCEEDED(hr), "Test %u: Failed to create render target view, hr %#x.\n", i, hr); refcount = get_refcount(texture); ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount); /* Not available on all Windows versions. */ check_interface(rtview, &IID_ID3D10RenderTargetView, TRUE, TRUE); memset(&rtv_desc, 0, sizeof(rtv_desc)); ID3D11RenderTargetView_GetDesc(rtview, &rtv_desc); check_rtv_desc(&rtv_desc, &tests[i].expected_rtv_desc); ID3D11RenderTargetView_Release(rtview); ID3D11Resource_Release(texture); } for (i = 0; i < ARRAY_SIZE(invalid_desc_tests); ++i) { assert(invalid_desc_tests[i].texture.dimension == D3D11_RTV_DIMENSION_TEXTURE2D || invalid_desc_tests[i].texture.dimension == D3D11_RTV_DIMENSION_TEXTURE3D); if (invalid_desc_tests[i].texture.dimension != D3D11_RTV_DIMENSION_TEXTURE3D) { texture2d_desc.MipLevels = invalid_desc_tests[i].texture.miplevel_count; texture2d_desc.ArraySize = invalid_desc_tests[i].texture.depth_or_array_size; texture2d_desc.Format = invalid_desc_tests[i].texture.format; hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, NULL, &texture2d); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture2d; } else { texture3d_desc.MipLevels = invalid_desc_tests[i].texture.miplevel_count; texture3d_desc.Depth = invalid_desc_tests[i].texture.depth_or_array_size; texture3d_desc.Format = invalid_desc_tests[i].texture.format; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, &texture3d); ok(SUCCEEDED(hr), "Test %u: Failed to create 3d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture3d; } get_rtv_desc(&rtv_desc, &invalid_desc_tests[i].rtv_desc); hr = ID3D11Device_CreateRenderTargetView(device, texture, &rtv_desc, &rtview); ok(hr == E_INVALIDARG, "Test %u: Got unexpected hr %#x.\n", i, hr); ID3D11Resource_Release(texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_shader_resource_view(void) { D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; D3D11_TEXTURE3D_DESC texture3d_desc; D3D11_TEXTURE2D_DESC texture2d_desc; ULONG refcount, expected_refcount; ID3D11ShaderResourceView *srview; D3D_FEATURE_LEVEL feature_level; D3D11_BUFFER_DESC buffer_desc; ID3D11Device *device, *tmp; ID3D11Texture3D *texture3d; ID3D11Texture2D *texture2d; ID3D11Resource *texture; ID3D11Buffer *buffer; unsigned int i; HRESULT hr; #define FMT_UNKNOWN DXGI_FORMAT_UNKNOWN #define RGBA8_UNORM DXGI_FORMAT_R8G8B8A8_UNORM #define RGBA8_SRGB DXGI_FORMAT_R8G8B8A8_UNORM_SRGB #define RGBA8_UINT DXGI_FORMAT_R8G8B8A8_UINT #define RGBA8_TL DXGI_FORMAT_R8G8B8A8_TYPELESS #define DIM_UNKNOWN D3D11_SRV_DIMENSION_UNKNOWN #define TEX_1D D3D11_SRV_DIMENSION_TEXTURE1D #define TEX_1D_ARRAY D3D11_SRV_DIMENSION_TEXTURE1DARRAY #define TEX_2D D3D11_SRV_DIMENSION_TEXTURE2D #define TEX_2D_ARRAY D3D11_SRV_DIMENSION_TEXTURE2DARRAY #define TEX_2DMS D3D11_SRV_DIMENSION_TEXTURE2DMS #define TEX_2DMS_ARR D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY #define TEX_3D D3D11_SRV_DIMENSION_TEXTURE3D #define TEX_CUBE D3D11_SRV_DIMENSION_TEXTURECUBE #define CUBE_ARRAY D3D11_SRV_DIMENSION_TEXTURECUBEARRAY static const struct { struct { unsigned int miplevel_count; unsigned int depth_or_array_size; DXGI_FORMAT format; } texture; struct srv_desc srv_desc; struct srv_desc expected_srv_desc; } tests[] = { {{10, 1, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_2D, 0, 10}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D, 0, ~0u}, {RGBA8_UNORM, TEX_2D, 0, 10}}, {{10, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0, ~0u}, {RGBA8_UNORM, TEX_2D, 0, 10}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D, 0, 10}, {RGBA8_UNORM, TEX_2D, 0, 10}}, {{ 1, 1, RGBA8_TL}, {RGBA8_UNORM, TEX_2D, 0, ~0u}, {RGBA8_UNORM, TEX_2D, 0, 1}}, {{10, 1, RGBA8_TL}, {RGBA8_UNORM, TEX_2D, 0, ~0u}, {RGBA8_UNORM, TEX_2D, 0, 10}}, {{10, 4, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 10, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, ~0u, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 10, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 1, ~0u, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 1, 9, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 3, ~0u, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 3, 7, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 5, ~0u, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 5, 5, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 9, ~0u, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 9, 1, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, ~0u, 1, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 10, 1, 3}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, ~0u, 2, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 10, 2, 2}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, ~0u, 3, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 10, 3, 1}}, {{ 1, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS}, {RGBA8_UNORM, TEX_2DMS}}, {{ 1, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS}, {RGBA8_UNORM, TEX_2DMS}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS}, {RGBA8_UNORM, TEX_2DMS}}, {{ 1, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 1, 0, 1}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 1, 0, 1}}, {{ 1, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 1, 0, ~0u}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 1, 0, 1}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 1, 0, 1}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 1, 0, 1}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 1, 0, ~0u}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 1, 0, 1}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 1, 0, 1}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 1, 0, 1}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 1, 0, 4}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 1, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2DMS_ARR, 0, 1, 0, ~0u}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 1, 0, 4}}, {{ 1, 12, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_3D, 0, 1}}, {{ 1, 12, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 1}, {RGBA8_UNORM, TEX_3D, 0, 1}}, {{ 1, 12, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 1}}, {{ 4, 12, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 4}}, {{ 1, 6, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_CUBE, 0, 1}}, {{ 2, 6, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_CUBE, 0, 2}}, {{ 2, 9, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_CUBE, 0, 2}}, {{ 2, 11, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_CUBE, 0, 2}}, {{ 2, 6, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_CUBE, 0, ~0u}, {RGBA8_UNORM, TEX_CUBE, 0, 2}}, {{ 2, 6, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_CUBE, 0, 1}, {RGBA8_UNORM, TEX_CUBE , 0, 1}}, {{ 2, 6, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_CUBE, 1, 1}, {RGBA8_UNORM, TEX_CUBE , 1, 1}}, {{ 2, 6, RGBA8_UNORM}, {FMT_UNKNOWN, CUBE_ARRAY, 0, 1, 0, 1}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 1}}, {{ 2, 6, RGBA8_UNORM}, {FMT_UNKNOWN, CUBE_ARRAY, 0, ~0u, 0, ~0u}, {RGBA8_UNORM, CUBE_ARRAY, 0, 2, 0, 1}}, {{ 1, 8, RGBA8_UNORM}, {FMT_UNKNOWN, CUBE_ARRAY, 0, ~0u, 0, ~0u}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 1}}, {{ 1, 12, RGBA8_UNORM}, {0}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 2}}, {{ 1, 12, RGBA8_UNORM}, {FMT_UNKNOWN, CUBE_ARRAY, 0, ~0u, 0, ~0u}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 2}}, {{ 1, 12, RGBA8_UNORM}, {FMT_UNKNOWN, CUBE_ARRAY, 0, ~0u, 0, 1}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 1}}, {{ 1, 12, RGBA8_UNORM}, {FMT_UNKNOWN, CUBE_ARRAY, 0, ~0u, 0, 2}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 2}}, {{ 1, 13, RGBA8_UNORM}, {0}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 2}}, {{ 1, 14, RGBA8_UNORM}, {0}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 2}}, {{ 1, 18, RGBA8_UNORM}, {0}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 3}}, {{ 1, 1, RGBA8_UINT}, {0}, {RGBA8_UINT, TEX_2D, 0, 1, 0, 1}}, {{ 1, 1, RGBA8_TL}, {RGBA8_UINT, TEX_2D, 0, ~0u}, {RGBA8_UINT, TEX_2D, 0, 1, 0, 1}}, }; static const struct { struct { D3D11_SRV_DIMENSION dimension; unsigned int miplevel_count; unsigned int depth_or_array_size; DXGI_FORMAT format; } texture; struct srv_desc srv_desc; } invalid_desc_tests[] = { {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, DIM_UNKNOWN}}, {{TEX_2D, 6, 4, RGBA8_UNORM}, {RGBA8_UNORM, DIM_UNKNOWN}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 1, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_TL, TEX_2D, 0, ~0u}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_TL, TEX_2D, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_TL}, {FMT_UNKNOWN, TEX_2D, 0, ~0u}}, {{TEX_2D, 1, 1, RGBA8_TL}, {FMT_UNKNOWN, TEX_2D, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0, 2}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 1, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 0, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 1, 0, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 2, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 1, 1, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 1, 0, 2}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 1, 1, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 1, 0, 2}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2DMS_ARR, 0, 1, 1, 1}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, TEX_CUBE, 0, 0}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, TEX_CUBE, 0, 2}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, TEX_CUBE, 1, 1}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 0, 0, 0}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 0, 0, 1}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 0}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 0}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 2, 0, 1}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 1, 1, 0, 1}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 1, 1}}, {{TEX_2D, 1, 6, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 1, ~0u}}, {{TEX_2D, 1, 7, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 2, 1}}, {{TEX_2D, 1, 7, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 2, ~0u}}, {{TEX_2D, 1, 7, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 2}}, {{TEX_2D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, CUBE_ARRAY, 0, 1, 0, 2}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UINT, TEX_2D, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UINT}, {RGBA8_UNORM, TEX_2D, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_SRGB, TEX_2D, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_SRGB}, {RGBA8_UNORM, TEX_2D, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 1, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_CUBE, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 1, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 1, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_CUBE, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 1, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_TL, TEX_3D, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 2}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 2}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 1, 1}}, }; #undef FMT_UNKNOWN #undef RGBA8_UNORM #undef RGBA8_SRGB #undef RGBA8_UINT #undef RGBA8_TL #undef DIM_UNKNOWN #undef TEX_1D #undef TEX_1D_ARRAY #undef TEX_2D #undef TEX_2D_ARRAY #undef TEX_2DMS #undef TEX_2DMS_ARR #undef TEX_3D #undef TEX_CUBE #undef CUBE_ARRAY if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } feature_level = ID3D11Device_GetFeatureLevel(device); buffer = create_buffer(device, D3D11_BIND_SHADER_RESOURCE, 1024, NULL); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)buffer, NULL, &srview); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); srv_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; U1(U(srv_desc).Buffer).ElementOffset = 0; U2(U(srv_desc).Buffer).ElementWidth = 64; hr = ID3D11Device_CreateShaderResourceView(device, NULL, &srv_desc, &srview); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)buffer, &srv_desc, &srview); ok(SUCCEEDED(hr), "Failed to create a shader resource view, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11ShaderResourceView_GetDevice(srview, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); /* Not available on all Windows versions. */ check_interface(srview, &IID_ID3D10ShaderResourceView, TRUE, TRUE); check_interface(srview, &IID_ID3D10ShaderResourceView1, TRUE, TRUE); ID3D11ShaderResourceView_Release(srview); ID3D11Buffer_Release(buffer); /* Without D3D11_BIND_SHADER_RESOURCE. */ buffer = create_buffer(device, 0, 1024, NULL); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)buffer, &srv_desc, &srview); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ID3D11Buffer_Release(buffer); if (feature_level >= D3D_FEATURE_LEVEL_11_0) { buffer_desc.ByteWidth = 1024; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; buffer_desc.StructureByteStride = 4; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)buffer, NULL, &srview); ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); memset(&srv_desc, 0, sizeof(srv_desc)); ID3D11ShaderResourceView_GetDesc(srview, &srv_desc); ok(srv_desc.Format == DXGI_FORMAT_UNKNOWN, "Got unexpected format %#x.\n", srv_desc.Format); ok(srv_desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFER, "Got unexpected view dimension %#x.\n", srv_desc.ViewDimension); ok(!U1(U(srv_desc).Buffer).FirstElement, "Got unexpected first element %u.\n", U1(U(srv_desc).Buffer).FirstElement); ok(U2(U(srv_desc).Buffer).NumElements == 256, "Got unexpected num elements %u.\n", U2(U(srv_desc).Buffer).NumElements); ID3D11ShaderResourceView_Release(srview); ID3D11Buffer_Release(buffer); } else { skip("Structured buffers require feature level 11_0.\n"); } texture2d_desc.Width = 512; texture2d_desc.Height = 512; texture2d_desc.SampleDesc.Count = 1; texture2d_desc.SampleDesc.Quality = 0; texture2d_desc.Usage = D3D11_USAGE_DEFAULT; texture2d_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture2d_desc.CPUAccessFlags = 0; texture3d_desc.Width = 64; texture3d_desc.Height = 64; texture3d_desc.Usage = D3D11_USAGE_DEFAULT; texture3d_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture3d_desc.CPUAccessFlags = 0; texture3d_desc.MiscFlags = 0; for (i = 0; i < ARRAY_SIZE(tests); ++i) { D3D11_SHADER_RESOURCE_VIEW_DESC *current_desc; if (tests[i].expected_srv_desc.dimension != D3D11_SRV_DIMENSION_TEXTURE3D) { texture2d_desc.MipLevels = tests[i].texture.miplevel_count; texture2d_desc.ArraySize = tests[i].texture.depth_or_array_size; texture2d_desc.Format = tests[i].texture.format; texture2d_desc.MiscFlags = 0; if (tests[i].expected_srv_desc.dimension == D3D11_SRV_DIMENSION_TEXTURECUBE || tests[i].expected_srv_desc.dimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) texture2d_desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; if (texture2d_desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE && (texture2d_desc.ArraySize != 6 || tests[i].expected_srv_desc.dimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) && feature_level < D3D_FEATURE_LEVEL_10_1) { skip("Test %u: Cube map array textures require feature level 10_1.\n", i); continue; } hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, NULL, &texture2d); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture2d; } else { texture3d_desc.MipLevels = tests[i].texture.miplevel_count; texture3d_desc.Depth = tests[i].texture.depth_or_array_size; texture3d_desc.Format = tests[i].texture.format; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, &texture3d); ok(SUCCEEDED(hr), "Test %u: Failed to create 3d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture3d; } if (tests[i].srv_desc.dimension == D3D11_SRV_DIMENSION_UNKNOWN) { current_desc = NULL; } else { current_desc = &srv_desc; get_srv_desc(current_desc, &tests[i].srv_desc); } expected_refcount = get_refcount(texture); hr = ID3D11Device_CreateShaderResourceView(device, texture, current_desc, &srview); ok(SUCCEEDED(hr), "Test %u: Failed to create a shader resource view, hr %#x.\n", i, hr); refcount = get_refcount(texture); ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount); /* Not available on all Windows versions. */ check_interface(srview, &IID_ID3D10ShaderResourceView, TRUE, TRUE); check_interface(srview, &IID_ID3D10ShaderResourceView1, TRUE, TRUE); memset(&srv_desc, 0, sizeof(srv_desc)); ID3D11ShaderResourceView_GetDesc(srview, &srv_desc); check_srv_desc(&srv_desc, &tests[i].expected_srv_desc); ID3D11ShaderResourceView_Release(srview); ID3D11Resource_Release(texture); } for (i = 0; i < ARRAY_SIZE(invalid_desc_tests); ++i) { assert(invalid_desc_tests[i].texture.dimension == D3D11_SRV_DIMENSION_TEXTURE2D || invalid_desc_tests[i].texture.dimension == D3D11_SRV_DIMENSION_TEXTURE3D); if (invalid_desc_tests[i].texture.dimension == D3D11_SRV_DIMENSION_TEXTURE2D) { texture2d_desc.MipLevels = invalid_desc_tests[i].texture.miplevel_count; texture2d_desc.ArraySize = invalid_desc_tests[i].texture.depth_or_array_size; texture2d_desc.Format = invalid_desc_tests[i].texture.format; texture2d_desc.MiscFlags = 0; if (invalid_desc_tests[i].srv_desc.dimension == D3D11_SRV_DIMENSION_TEXTURECUBE || invalid_desc_tests[i].srv_desc.dimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) texture2d_desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; if (invalid_desc_tests[i].srv_desc.dimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY && feature_level < D3D_FEATURE_LEVEL_10_1) { skip("Test %u: Cube map array textures require feature level 10_1.\n", i); continue; } hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, NULL, &texture2d); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture2d; } else { texture3d_desc.MipLevels = invalid_desc_tests[i].texture.miplevel_count; texture3d_desc.Depth = invalid_desc_tests[i].texture.depth_or_array_size; texture3d_desc.Format = invalid_desc_tests[i].texture.format; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, &texture3d); ok(SUCCEEDED(hr), "Test %u: Failed to create 3d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture3d; } get_srv_desc(&srv_desc, &invalid_desc_tests[i].srv_desc); hr = ID3D11Device_CreateShaderResourceView(device, texture, &srv_desc, &srview); ok(hr == E_INVALIDARG, "Test %u: Got unexpected hr %#x.\n", i, hr); ID3D11Resource_Release(texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_shader(const D3D_FEATURE_LEVEL feature_level) { #if 0 float4 light; float4x4 mat; struct input { float4 position : POSITION; float3 normal : NORMAL; }; struct output { float4 position : POSITION; float4 diffuse : COLOR; }; output main(const input v) { output o; o.position = mul(v.position, mat); o.diffuse = dot((float3)light, v.normal); return o; } #endif static const DWORD vs_4_1[] = { 0x43425844, 0xfce5b27c, 0x965db93d, 0x8c3d0459, 0x9890ebac, 0x00000001, 0x000001c4, 0x00000003, 0x0000002c, 0x0000007c, 0x000000cc, 0x4e475349, 0x00000048, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x524f4e00, 0x004c414d, 0x4e47534f, 0x00000048, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000041, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x52444853, 0x000000f0, 0x00010041, 0x0000003c, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000005, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x08000011, 0x00102012, 0x00000000, 0x00101e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000001, 0x08000011, 0x00102022, 0x00000000, 0x00101e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000002, 0x08000011, 0x00102042, 0x00000000, 0x00101e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000003, 0x08000011, 0x00102082, 0x00000000, 0x00101e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000004, 0x08000010, 0x001020f2, 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x00101246, 0x00000001, 0x0100003e, }; static const DWORD vs_4_0[] = { 0x43425844, 0x3ae813ca, 0x0f034b91, 0x790f3226, 0x6b4a718a, 0x00000001, 0x000001c0, 0x00000003, 0x0000002c, 0x0000007c, 0x000000cc, 0x4e475349, 0x00000048, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x524f4e00, 0x004c414d, 0x4e47534f, 0x00000048, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000041, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x52444853, 0x000000ec, 0x00010040, 0x0000003b, 0x04000059, 0x00208e46, 0x00000000, 0x00000005, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x08000011, 0x00102012, 0x00000000, 0x00101e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000001, 0x08000011, 0x00102022, 0x00000000, 0x00101e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000002, 0x08000011, 0x00102042, 0x00000000, 0x00101e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000003, 0x08000011, 0x00102082, 0x00000000, 0x00101e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000004, 0x08000010, 0x001020f2, 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x00101246, 0x00000001, 0x0100003e, }; static const DWORD vs_3_0[] = { 0xfffe0300, 0x002bfffe, 0x42415443, 0x0000001c, 0x00000077, 0xfffe0300, 0x00000002, 0x0000001c, 0x00000100, 0x00000070, 0x00000044, 0x00040002, 0x00000001, 0x0000004c, 0x00000000, 0x0000005c, 0x00000002, 0x00000004, 0x00000060, 0x00000000, 0x6867696c, 0xabab0074, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x0074616d, 0x00030003, 0x00040004, 0x00000001, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x80000003, 0x900f0001, 0x0200001f, 0x80000000, 0xe00f0000, 0x0200001f, 0x8000000a, 0xe00f0001, 0x03000009, 0xe0010000, 0x90e40000, 0xa0e40000, 0x03000009, 0xe0020000, 0x90e40000, 0xa0e40001, 0x03000009, 0xe0040000, 0x90e40000, 0xa0e40002, 0x03000009, 0xe0080000, 0x90e40000, 0xa0e40003, 0x03000008, 0xe00f0001, 0xa0e40004, 0x90e40001, 0x0000ffff, }; static const DWORD vs_2_0[] = { 0xfffe0200, 0x002bfffe, 0x42415443, 0x0000001c, 0x00000077, 0xfffe0200, 0x00000002, 0x0000001c, 0x00000100, 0x00000070, 0x00000044, 0x00040002, 0x00000001, 0x0000004c, 0x00000000, 0x0000005c, 0x00000002, 0x00000004, 0x00000060, 0x00000000, 0x6867696c, 0xabab0074, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x0074616d, 0x00030003, 0x00040004, 0x00000001, 0x00000000, 0x325f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x80000003, 0x900f0001, 0x03000009, 0xc0010000, 0x90e40000, 0xa0e40000, 0x03000009, 0xc0020000, 0x90e40000, 0xa0e40001, 0x03000009, 0xc0040000, 0x90e40000, 0xa0e40002, 0x03000009, 0xc0080000, 0x90e40000, 0xa0e40003, 0x03000008, 0xd00f0000, 0xa0e40004, 0x90e40001, 0x0000ffff, }; #if 0 float4 main(const float4 color : COLOR) : SV_TARGET { float4 o; o = color; return o; } #endif static const DWORD ps_4_1[] = { 0x43425844, 0xa1a44423, 0xa4cfcec2, 0x64610832, 0xb7a852bd, 0x00000001, 0x000000d4, 0x00000003, 0x0000002c, 0x0000005c, 0x00000090, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x0000003c, 0x00000041, 0x0000000f, 0x0100086a, 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; static const DWORD ps_4_0[] = { 0x43425844, 0x08c2b568, 0x17d33120, 0xb7d82948, 0x13a570fb, 0x00000001, 0x000000d0, 0x00000003, 0x0000002c, 0x0000005c, 0x00000090, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; static const DWORD ps_4_0_level_9_0[] = { 0x43425844, 0xbc6626e7, 0x7778dc9d, 0xc8a43be2, 0xe4b53f7a, 0x00000001, 0x00000170, 0x00000005, 0x00000034, 0x00000080, 0x000000cc, 0x0000010c, 0x0000013c, 0x53414e58, 0x00000044, 0x00000044, 0xffff0200, 0x00000020, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0xffff0200, 0x0200001f, 0x80000000, 0xb00f0000, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff, 0x396e6f41, 0x00000044, 0x00000044, 0xffff0200, 0x00000020, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0xffff0200, 0x0200001f, 0x80000000, 0xb00f0000, 0x02000001, 0x800f0800, 0xb0e40000, 0x0000ffff, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, }; static const DWORD ps_4_0_level_9_1[] = { 0x43425844, 0x275ecf38, 0x4349ff01, 0xa6b0e324, 0x6e54a4fc, 0x00000001, 0x00000120, 0x00000004, 0x00000030, 0x0000007c, 0x000000bc, 0x000000ec, 0x396e6f41, 0x00000044, 0x00000044, 0xffff0200, 0x00000020, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0xffff0200, 0x0200001f, 0x80000000, 0xb00f0000, 0x02000001, 0x800f0800, 0xb0e40000, 0x0000ffff, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, }; static const DWORD ps_4_0_level_9_3[] = { 0x43425844, 0xc7d541c4, 0x961d4e0e, 0x9ce7ec57, 0x70f47dcb, 0x00000001, 0x00000120, 0x00000004, 0x00000030, 0x0000007c, 0x000000bc, 0x000000ec, 0x396e6f41, 0x00000044, 0x00000044, 0xffff0200, 0x00000020, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0xffff0201, 0x0200001f, 0x80000000, 0xb00f0000, 0x02000001, 0x800f0800, 0xb0e40000, 0x0000ffff, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, }; #if 0 struct gs_out { float4 pos : SV_POSITION; }; [maxvertexcount(4)] void main(point float4 vin[1] : POSITION, inout TriangleStream vout) { float offset = 0.1 * vin[0].w; gs_out v; v.pos = float4(vin[0].x - offset, vin[0].y - offset, vin[0].z, vin[0].w); vout.Append(v); v.pos = float4(vin[0].x - offset, vin[0].y + offset, vin[0].z, vin[0].w); vout.Append(v); v.pos = float4(vin[0].x + offset, vin[0].y - offset, vin[0].z, vin[0].w); vout.Append(v); v.pos = float4(vin[0].x + offset, vin[0].y + offset, vin[0].z, vin[0].w); vout.Append(v); } #endif static const DWORD gs_4_1[] = { 0x43425844, 0x779daaf5, 0x7e154197, 0xcf5e99da, 0xb502b4d2, 0x00000001, 0x00000240, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x000001a4, 0x00020041, 0x00000069, 0x0100086a, 0x0400005f, 0x002010f2, 0x00000001, 0x00000000, 0x02000068, 0x00000001, 0x0100085d, 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x0200005e, 0x00000004, 0x0f000032, 0x00100032, 0x00000000, 0x80201ff6, 0x00000041, 0x00000000, 0x00000000, 0x00004002, 0x3dcccccd, 0x3dcccccd, 0x00000000, 0x00000000, 0x00201046, 0x00000000, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0e000032, 0x00100052, 0x00000000, 0x00201ff6, 0x00000000, 0x00000000, 0x00004002, 0x3dcccccd, 0x00000000, 0x3dcccccd, 0x00000000, 0x00201106, 0x00000000, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010002a, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010001a, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x05000036, 0x00102032, 0x00000000, 0x00100086, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x0100003e, }; static const DWORD gs_4_0[] = { 0x43425844, 0x000ee786, 0xc624c269, 0x885a5cbe, 0x444b3b1f, 0x00000001, 0x0000023c, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x000001a0, 0x00020040, 0x00000068, 0x0400005f, 0x002010f2, 0x00000001, 0x00000000, 0x02000068, 0x00000001, 0x0100085d, 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x0200005e, 0x00000004, 0x0f000032, 0x00100032, 0x00000000, 0x80201ff6, 0x00000041, 0x00000000, 0x00000000, 0x00004002, 0x3dcccccd, 0x3dcccccd, 0x00000000, 0x00000000, 0x00201046, 0x00000000, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0e000032, 0x00100052, 0x00000000, 0x00201ff6, 0x00000000, 0x00000000, 0x00004002, 0x3dcccccd, 0x00000000, 0x3dcccccd, 0x00000000, 0x00201106, 0x00000000, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010002a, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010001a, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x05000036, 0x00102032, 0x00000000, 0x00100086, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x0100003e, }; ULONG refcount, expected_refcount; struct device_desc device_desc; ID3D11Device *device, *tmp; ID3D11GeometryShader *gs; ID3D11VertexShader *vs; ID3D11PixelShader *ps; HRESULT hr; device_desc.feature_level = &feature_level; device_desc.flags = 0; if (!(device = create_device(&device_desc))) { skip("Failed to create device for feature level %#x.\n", feature_level); return; } /* level_9 shaders */ hr = ID3D11Device_CreatePixelShader(device, ps_4_0_level_9_0, sizeof(ps_4_0_level_9_0), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create ps_4_0_level_9_0 shader, hr %#x, feature level %#x.\n", hr, feature_level); ID3D11PixelShader_Release(ps); hr = ID3D11Device_CreatePixelShader(device, ps_4_0_level_9_1, sizeof(ps_4_0_level_9_1), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create ps_4_0_level_9_1 shader, hr %#x, feature level %#x.\n", hr, feature_level); ID3D11PixelShader_Release(ps); hr = ID3D11Device_CreatePixelShader(device, ps_4_0_level_9_3, sizeof(ps_4_0_level_9_3), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create ps_4_0_level_9_3 shader, hr %#x, feature level %#x.\n", hr, feature_level); ID3D11PixelShader_Release(ps); /* vertex shader */ hr = ID3D11Device_CreateVertexShader(device, vs_2_0, sizeof(vs_2_0), NULL, &vs); ok(hr == E_INVALIDARG, "Created a SM2 vertex shader, hr %#x, feature level %#x.\n", hr, feature_level); hr = ID3D11Device_CreateVertexShader(device, vs_3_0, sizeof(vs_3_0), NULL, &vs); ok(hr == E_INVALIDARG, "Created a SM3 vertex shader, hr %#x, feature level %#x.\n", hr, feature_level); hr = ID3D11Device_CreateVertexShader(device, ps_4_0, sizeof(ps_4_0), NULL, &vs); ok(hr == E_INVALIDARG, "Created a SM4 vertex shader from a pixel shader source, hr %#x, feature level %#x.\n", hr, feature_level); expected_refcount = get_refcount(device) + (feature_level >= D3D_FEATURE_LEVEL_10_0); hr = ID3D11Device_CreateVertexShader(device, vs_4_0, sizeof(vs_4_0), NULL, &vs); if (feature_level >= D3D_FEATURE_LEVEL_10_0) ok(SUCCEEDED(hr), "Failed to create SM4 vertex shader, hr %#x, feature level %#x.\n", hr, feature_level); else ok(hr == E_INVALIDARG, "Created a SM4 vertex shader, hr %#x, feature level %#x.\n", hr, feature_level); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); if (feature_level >= D3D_FEATURE_LEVEL_10_0) { tmp = NULL; expected_refcount = refcount + 1; ID3D11VertexShader_GetDevice(vs, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); /* Not available on all Windows versions. */ check_interface(vs, &IID_ID3D10VertexShader, TRUE, TRUE); refcount = ID3D11VertexShader_Release(vs); ok(!refcount, "Vertex shader has %u references left.\n", refcount); } hr = ID3D11Device_CreateVertexShader(device, vs_4_1, sizeof(vs_4_1), NULL, &vs); if (feature_level >= D3D_FEATURE_LEVEL_10_1) { ok(SUCCEEDED(hr), "Failed to create SM4.1 vertex shader, hr %#x, feature level %#x.\n", hr, feature_level); refcount = ID3D11VertexShader_Release(vs); ok(!refcount, "Vertex shader has %u references left.\n", refcount); } else { todo_wine_if(feature_level >= D3D_FEATURE_LEVEL_10_0) ok(hr == E_INVALIDARG, "Created a SM4.1 vertex shader, hr %#x, feature level %#x.\n", hr, feature_level); if (SUCCEEDED(hr)) ID3D11VertexShader_Release(vs); } /* pixel shader */ expected_refcount = get_refcount(device) + (feature_level >= D3D_FEATURE_LEVEL_10_0); hr = ID3D11Device_CreatePixelShader(device, ps_4_0, sizeof(ps_4_0), NULL, &ps); if (feature_level >= D3D_FEATURE_LEVEL_10_0) ok(SUCCEEDED(hr), "Failed to create SM4 pixel shader, hr %#x, feature level %#x.\n", hr, feature_level); else ok(hr == E_INVALIDARG, "Created a SM4 pixel shader, hr %#x, feature level %#x.\n", hr, feature_level); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); if (feature_level >= D3D_FEATURE_LEVEL_10_0) { tmp = NULL; expected_refcount = refcount + 1; ID3D11PixelShader_GetDevice(ps, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); /* Not available on all Windows versions. */ check_interface(ps, &IID_ID3D10PixelShader, TRUE, TRUE); refcount = ID3D11PixelShader_Release(ps); ok(!refcount, "Pixel shader has %u references left.\n", refcount); } hr = ID3D11Device_CreatePixelShader(device, ps_4_1, sizeof(ps_4_1), NULL, &ps); if (feature_level >= D3D_FEATURE_LEVEL_10_1) { ok(SUCCEEDED(hr), "Failed to create SM4.1 pixel shader, hr %#x, feature level %#x.\n", hr, feature_level); refcount = ID3D11PixelShader_Release(ps); ok(!refcount, "Pixel shader has %u references left.\n", refcount); } else { todo_wine_if(feature_level >= D3D_FEATURE_LEVEL_10_0) ok(hr == E_INVALIDARG, "Created a SM4.1 pixel shader, hr %#x, feature level %#x.\n", hr, feature_level); if (SUCCEEDED(hr)) ID3D11PixelShader_Release(ps); } /* geometry shader */ expected_refcount = get_refcount(device) + (feature_level >= D3D_FEATURE_LEVEL_10_0); hr = ID3D11Device_CreateGeometryShader(device, gs_4_0, sizeof(gs_4_0), NULL, &gs); if (feature_level >= D3D_FEATURE_LEVEL_10_0) ok(SUCCEEDED(hr), "Failed to create SM4 geometry shader, hr %#x, feature level %#x.\n", hr, feature_level); else ok(hr == E_INVALIDARG, "Created a SM4 geometry shader, hr %#x, feature level %#x.\n", hr, feature_level); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); if (feature_level >= D3D_FEATURE_LEVEL_10_0) { tmp = NULL; expected_refcount = refcount + 1; ID3D11GeometryShader_GetDevice(gs, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); /* Not available on all Windows versions. */ check_interface(gs, &IID_ID3D10GeometryShader, TRUE, TRUE); refcount = ID3D11GeometryShader_Release(gs); ok(!refcount, "Geometry shader has %u references left.\n", refcount); } hr = ID3D11Device_CreateGeometryShader(device, gs_4_1, sizeof(gs_4_1), NULL, &gs); if (feature_level >= D3D_FEATURE_LEVEL_10_1) { ok(SUCCEEDED(hr), "Failed to create SM4.1 geometry shader, hr %#x, feature level %#x.\n", hr, feature_level); refcount = ID3D11GeometryShader_Release(gs); ok(!refcount, "Geometry shader has %u references left.\n", refcount); } else { todo_wine_if(feature_level >= D3D_FEATURE_LEVEL_10_0) ok(hr == E_INVALIDARG, "Created a SM4.1 geometry shader, hr %#x, feature level %#x.\n", hr, feature_level); if (SUCCEEDED(hr)) ID3D11GeometryShader_Release(gs); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_sampler_state(void) { static const struct test { D3D11_FILTER filter; D3D10_FILTER expected_filter; } desc_conversion_tests[] = { {D3D11_FILTER_MIN_MAG_MIP_POINT, D3D10_FILTER_MIN_MAG_MIP_POINT}, {D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR, D3D10_FILTER_MIN_MAG_POINT_MIP_LINEAR}, {D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, D3D10_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT}, {D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR, D3D10_FILTER_MIN_POINT_MAG_MIP_LINEAR}, {D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT, D3D10_FILTER_MIN_LINEAR_MAG_MIP_POINT}, {D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, D3D10_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR}, {D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT, D3D10_FILTER_MIN_MAG_LINEAR_MIP_POINT}, {D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D10_FILTER_MIN_MAG_MIP_LINEAR}, {D3D11_FILTER_ANISOTROPIC, D3D10_FILTER_ANISOTROPIC}, {D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT, D3D10_FILTER_COMPARISON_MIN_MAG_MIP_POINT}, {D3D11_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR, D3D10_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR}, { D3D11_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT, D3D10_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT }, {D3D11_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR, D3D10_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR}, {D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT, D3D10_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT}, { D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR, D3D10_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR }, {D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT, D3D10_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT}, {D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR, D3D10_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR}, {D3D11_FILTER_COMPARISON_ANISOTROPIC, D3D10_FILTER_COMPARISON_ANISOTROPIC}, }; ID3D11SamplerState *sampler_state1, *sampler_state2; ID3D10SamplerState *d3d10_sampler_state; ULONG refcount, expected_refcount; ID3D11Device *device, *tmp; D3D11_SAMPLER_DESC desc; unsigned int i; HRESULT hr; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } hr = ID3D11Device_CreateSamplerState(device, NULL, &sampler_state1); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; desc.MipLODBias = 0.0f; desc.MaxAnisotropy = 16; desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; desc.BorderColor[0] = 0.0f; desc.BorderColor[1] = 1.0f; desc.BorderColor[2] = 0.0f; desc.BorderColor[3] = 1.0f; desc.MinLOD = 0.0f; desc.MaxLOD = 16.0f; expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateSamplerState(device, &desc, &sampler_state1); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); hr = ID3D11Device_CreateSamplerState(device, &desc, &sampler_state2); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); ok(sampler_state1 == sampler_state2, "Got different sampler state objects.\n"); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11SamplerState_GetDevice(sampler_state1, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); ID3D11SamplerState_GetDesc(sampler_state1, &desc); ok(desc.Filter == D3D11_FILTER_MIN_MAG_MIP_LINEAR, "Got unexpected filter %#x.\n", desc.Filter); ok(desc.AddressU == D3D11_TEXTURE_ADDRESS_WRAP, "Got unexpected address u %u.\n", desc.AddressU); ok(desc.AddressV == D3D11_TEXTURE_ADDRESS_WRAP, "Got unexpected address v %u.\n", desc.AddressV); ok(desc.AddressW == D3D11_TEXTURE_ADDRESS_WRAP, "Got unexpected address w %u.\n", desc.AddressW); ok(!desc.MipLODBias, "Got unexpected mip LOD bias %f.\n", desc.MipLODBias); ok(!desc.MaxAnisotropy, "Got unexpected max anisotropy %u.\n", desc.MaxAnisotropy); ok(desc.ComparisonFunc == D3D11_COMPARISON_NEVER, "Got unexpected comparison func %u.\n", desc.ComparisonFunc); ok(!desc.BorderColor[0] && !desc.BorderColor[1] && !desc.BorderColor[2] && !desc.BorderColor[3], "Got unexpected border color {%.8e, %.8e, %.8e, %.8e}.\n", desc.BorderColor[0], desc.BorderColor[1], desc.BorderColor[2], desc.BorderColor[3]); ok(!desc.MinLOD, "Got unexpected min LOD %f.\n", desc.MinLOD); ok(desc.MaxLOD == 16.0f, "Got unexpected max LOD %f.\n", desc.MaxLOD); refcount = ID3D11SamplerState_Release(sampler_state2); ok(refcount == 1, "Got unexpected refcount %u.\n", refcount); refcount = ID3D11SamplerState_Release(sampler_state1); ok(!refcount, "Got unexpected refcount %u.\n", refcount); for (i = 0; i < ARRAY_SIZE(desc_conversion_tests); ++i) { const struct test *current = &desc_conversion_tests[i]; D3D10_SAMPLER_DESC d3d10_desc, expected_desc; desc.Filter = current->filter; desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER; desc.MipLODBias = 0.0f; desc.MaxAnisotropy = 16; desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; desc.BorderColor[0] = 0.0f; desc.BorderColor[1] = 1.0f; desc.BorderColor[2] = 0.0f; desc.BorderColor[3] = 1.0f; desc.MinLOD = 0.0f; desc.MaxLOD = 16.0f; hr = ID3D11Device_CreateSamplerState(device, &desc, &sampler_state1); ok(SUCCEEDED(hr), "Test %u: Failed to create sampler state, hr %#x.\n", i, hr); hr = ID3D11SamplerState_QueryInterface(sampler_state1, &IID_ID3D10SamplerState, (void **)&d3d10_sampler_state); ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, "Test %u: Sampler state should implement ID3D10SamplerState.\n", i); if (FAILED(hr)) { win_skip("Sampler state does not implement ID3D10SamplerState.\n"); ID3D11SamplerState_Release(sampler_state1); break; } memcpy(&expected_desc, &desc, sizeof(expected_desc)); expected_desc.Filter = current->expected_filter; if (!D3D11_DECODE_IS_ANISOTROPIC_FILTER(current->filter)) expected_desc.MaxAnisotropy = 0; if (!D3D11_DECODE_IS_COMPARISON_FILTER(current->filter)) expected_desc.ComparisonFunc = D3D10_COMPARISON_NEVER; ID3D10SamplerState_GetDesc(d3d10_sampler_state, &d3d10_desc); ok(d3d10_desc.Filter == expected_desc.Filter, "Test %u: Got unexpected filter %#x.\n", i, d3d10_desc.Filter); ok(d3d10_desc.AddressU == expected_desc.AddressU, "Test %u: Got unexpected address u %u.\n", i, d3d10_desc.AddressU); ok(d3d10_desc.AddressV == expected_desc.AddressV, "Test %u: Got unexpected address v %u.\n", i, d3d10_desc.AddressV); ok(d3d10_desc.AddressW == expected_desc.AddressW, "Test %u: Got unexpected address w %u.\n", i, d3d10_desc.AddressW); ok(d3d10_desc.MipLODBias == expected_desc.MipLODBias, "Test %u: Got unexpected mip LOD bias %f.\n", i, d3d10_desc.MipLODBias); ok(d3d10_desc.MaxAnisotropy == expected_desc.MaxAnisotropy, "Test %u: Got unexpected max anisotropy %u.\n", i, d3d10_desc.MaxAnisotropy); ok(d3d10_desc.ComparisonFunc == expected_desc.ComparisonFunc, "Test %u: Got unexpected comparison func %u.\n", i, d3d10_desc.ComparisonFunc); ok(d3d10_desc.BorderColor[0] == expected_desc.BorderColor[0] && d3d10_desc.BorderColor[1] == expected_desc.BorderColor[1] && d3d10_desc.BorderColor[2] == expected_desc.BorderColor[2] && d3d10_desc.BorderColor[3] == expected_desc.BorderColor[3], "Test %u: Got unexpected border color {%.8e, %.8e, %.8e, %.8e}.\n", i, d3d10_desc.BorderColor[0], d3d10_desc.BorderColor[1], d3d10_desc.BorderColor[2], d3d10_desc.BorderColor[3]); ok(d3d10_desc.MinLOD == expected_desc.MinLOD, "Test %u: Got unexpected min LOD %f.\n", i, d3d10_desc.MinLOD); ok(d3d10_desc.MaxLOD == expected_desc.MaxLOD, "Test %u: Got unexpected max LOD %f.\n", i, d3d10_desc.MaxLOD); refcount = ID3D10SamplerState_Release(d3d10_sampler_state); ok(refcount == 1, "Test %u: Got unexpected refcount %u.\n", i, refcount); refcount = ID3D11SamplerState_Release(sampler_state1); ok(!refcount, "Test %u: Got unexpected refcount %u.\n", i, refcount); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_blend_state(void) { static const D3D11_BLEND_DESC desc_conversion_tests[] = { { FALSE, FALSE, { { FALSE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD }, }, }, { FALSE, TRUE, { { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { FALSE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_RED }, { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { FALSE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_GREEN }, { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, }, }, { FALSE, TRUE, { { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { TRUE, D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ONE, D3D11_BLEND_OP_MAX, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ONE, D3D11_BLEND_OP_MIN, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { FALSE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, { FALSE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL }, }, }, }; ID3D11BlendState *blend_state1, *blend_state2; D3D11_BLEND_DESC desc, obtained_desc; ID3D10BlendState *d3d10_blend_state; D3D10_BLEND_DESC d3d10_blend_desc; ULONG refcount, expected_refcount; ID3D11Device *device, *tmp; unsigned int i, j; HRESULT hr; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } hr = ID3D11Device_CreateBlendState(device, NULL, &blend_state1); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); memset(&desc, 0, sizeof(desc)); desc.AlphaToCoverageEnable = FALSE; desc.IndependentBlendEnable = FALSE; desc.RenderTarget[0].BlendEnable = FALSE; desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateBlendState(device, &desc, &blend_state1); ok(SUCCEEDED(hr), "Failed to create blend state, hr %#x.\n", hr); hr = ID3D11Device_CreateBlendState(device, &desc, &blend_state2); ok(SUCCEEDED(hr), "Failed to create blend state, hr %#x.\n", hr); ok(blend_state1 == blend_state2, "Got different blend state objects.\n"); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11BlendState_GetDevice(blend_state1, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); ID3D11BlendState_GetDesc(blend_state1, &obtained_desc); ok(obtained_desc.AlphaToCoverageEnable == FALSE, "Got unexpected alpha to coverage enable %#x.\n", obtained_desc.AlphaToCoverageEnable); ok(obtained_desc.IndependentBlendEnable == FALSE, "Got unexpected independent blend enable %#x.\n", obtained_desc.IndependentBlendEnable); for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) { ok(obtained_desc.RenderTarget[i].BlendEnable == FALSE, "Got unexpected blend enable %#x for render target %u.\n", obtained_desc.RenderTarget[i].BlendEnable, i); ok(obtained_desc.RenderTarget[i].SrcBlend == D3D11_BLEND_ONE, "Got unexpected src blend %u for render target %u.\n", obtained_desc.RenderTarget[i].SrcBlend, i); ok(obtained_desc.RenderTarget[i].DestBlend == D3D11_BLEND_ZERO, "Got unexpected dest blend %u for render target %u.\n", obtained_desc.RenderTarget[i].DestBlend, i); ok(obtained_desc.RenderTarget[i].BlendOp == D3D11_BLEND_OP_ADD, "Got unexpected blend op %u for render target %u.\n", obtained_desc.RenderTarget[i].BlendOp, i); ok(obtained_desc.RenderTarget[i].SrcBlendAlpha == D3D11_BLEND_ONE, "Got unexpected src blend alpha %u for render target %u.\n", obtained_desc.RenderTarget[i].SrcBlendAlpha, i); ok(obtained_desc.RenderTarget[i].DestBlendAlpha == D3D11_BLEND_ZERO, "Got unexpected dest blend alpha %u for render target %u.\n", obtained_desc.RenderTarget[i].DestBlendAlpha, i); ok(obtained_desc.RenderTarget[i].BlendOpAlpha == D3D11_BLEND_OP_ADD, "Got unexpected blend op alpha %u for render target %u.\n", obtained_desc.RenderTarget[i].BlendOpAlpha, i); ok(obtained_desc.RenderTarget[i].RenderTargetWriteMask == D3D11_COLOR_WRITE_ENABLE_ALL, "Got unexpected render target write mask %#x for render target %u.\n", obtained_desc.RenderTarget[0].RenderTargetWriteMask, i); } /* Not available on all Windows versions. */ check_interface(blend_state1, &IID_ID3D10BlendState, TRUE, TRUE); check_interface(blend_state1, &IID_ID3D10BlendState1, TRUE, TRUE); refcount = ID3D11BlendState_Release(blend_state1); ok(refcount == 1, "Got unexpected refcount %u.\n", refcount); refcount = ID3D11BlendState_Release(blend_state2); ok(!refcount, "Blend state has %u references left.\n", refcount); for (i = 0; i < ARRAY_SIZE(desc_conversion_tests); ++i) { const D3D11_BLEND_DESC *current_desc = &desc_conversion_tests[i]; hr = ID3D11Device_CreateBlendState(device, current_desc, &blend_state1); ok(SUCCEEDED(hr), "Failed to create blend state, hr %#x.\n", hr); hr = ID3D11BlendState_QueryInterface(blend_state1, &IID_ID3D10BlendState, (void **)&d3d10_blend_state); ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, "Blend state should implement ID3D10BlendState.\n"); if (FAILED(hr)) { win_skip("Blend state does not implement ID3D10BlendState.\n"); ID3D11BlendState_Release(blend_state1); break; } ID3D10BlendState_GetDesc(d3d10_blend_state, &d3d10_blend_desc); ok(d3d10_blend_desc.AlphaToCoverageEnable == current_desc->AlphaToCoverageEnable, "Got unexpected alpha to coverage enable %#x for test %u.\n", d3d10_blend_desc.AlphaToCoverageEnable, i); ok(d3d10_blend_desc.SrcBlend == (D3D10_BLEND)current_desc->RenderTarget[0].SrcBlend, "Got unexpected src blend %u for test %u.\n", d3d10_blend_desc.SrcBlend, i); ok(d3d10_blend_desc.DestBlend == (D3D10_BLEND)current_desc->RenderTarget[0].DestBlend, "Got unexpected dest blend %u for test %u.\n", d3d10_blend_desc.DestBlend, i); ok(d3d10_blend_desc.BlendOp == (D3D10_BLEND_OP)current_desc->RenderTarget[0].BlendOp, "Got unexpected blend op %u for test %u.\n", d3d10_blend_desc.BlendOp, i); ok(d3d10_blend_desc.SrcBlendAlpha == (D3D10_BLEND)current_desc->RenderTarget[0].SrcBlendAlpha, "Got unexpected src blend alpha %u for test %u.\n", d3d10_blend_desc.SrcBlendAlpha, i); ok(d3d10_blend_desc.DestBlendAlpha == (D3D10_BLEND)current_desc->RenderTarget[0].DestBlendAlpha, "Got unexpected dest blend alpha %u for test %u.\n", d3d10_blend_desc.DestBlendAlpha, i); ok(d3d10_blend_desc.BlendOpAlpha == (D3D10_BLEND_OP)current_desc->RenderTarget[0].BlendOpAlpha, "Got unexpected blend op alpha %u for test %u.\n", d3d10_blend_desc.BlendOpAlpha, i); for (j = 0; j < D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; j++) { unsigned int k = current_desc->IndependentBlendEnable ? j : 0; ok(d3d10_blend_desc.BlendEnable[j] == current_desc->RenderTarget[k].BlendEnable, "Got unexpected blend enable %#x for test %u, render target %u.\n", d3d10_blend_desc.BlendEnable[j], i, j); ok(d3d10_blend_desc.RenderTargetWriteMask[j] == current_desc->RenderTarget[k].RenderTargetWriteMask, "Got unexpected render target write mask %#x for test %u, render target %u.\n", d3d10_blend_desc.RenderTargetWriteMask[j], i, j); } ID3D10BlendState_Release(d3d10_blend_state); refcount = ID3D11BlendState_Release(blend_state1); ok(!refcount, "Got unexpected refcount %u.\n", refcount); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_depthstencil_state(void) { ID3D11DepthStencilState *ds_state1, *ds_state2; ULONG refcount, expected_refcount; D3D11_DEPTH_STENCIL_DESC ds_desc; ID3D11Device *device, *tmp; HRESULT hr; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } hr = ID3D11Device_CreateDepthStencilState(device, NULL, &ds_state1); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ds_desc.DepthEnable = TRUE; ds_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; ds_desc.DepthFunc = D3D11_COMPARISON_LESS; ds_desc.StencilEnable = FALSE; ds_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; ds_desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; ds_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; ds_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; ds_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; ds_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; ds_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; ds_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; ds_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; ds_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateDepthStencilState(device, &ds_desc, &ds_state1); ok(SUCCEEDED(hr), "Failed to create depthstencil state, hr %#x.\n", hr); hr = ID3D11Device_CreateDepthStencilState(device, &ds_desc, &ds_state2); ok(SUCCEEDED(hr), "Failed to create depthstencil state, hr %#x.\n", hr); ok(ds_state1 == ds_state2, "Got different depthstencil state objects.\n"); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11DepthStencilState_GetDevice(ds_state1, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); /* Not available on all Windows versions. */ check_interface(ds_state1, &IID_ID3D10DepthStencilState, TRUE, TRUE); refcount = ID3D11DepthStencilState_Release(ds_state2); ok(refcount == 1, "Got unexpected refcount %u.\n", refcount); refcount = ID3D11DepthStencilState_Release(ds_state1); ok(!refcount, "Got unexpected refcount %u.\n", refcount); ds_desc.DepthEnable = FALSE; ds_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; ds_desc.DepthFunc = D3D11_COMPARISON_NEVER; ds_desc.StencilEnable = FALSE; ds_desc.StencilReadMask = 0; ds_desc.StencilWriteMask = 0; ds_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_ZERO; ds_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_ZERO; ds_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_ZERO; ds_desc.FrontFace.StencilFunc = D3D11_COMPARISON_NEVER; ds_desc.BackFace = ds_desc.FrontFace; hr = ID3D11Device_CreateDepthStencilState(device, &ds_desc, &ds_state1); ok(SUCCEEDED(hr), "Failed to create depthstencil state, hr %#x.\n", hr); memset(&ds_desc, 0, sizeof(ds_desc)); ID3D11DepthStencilState_GetDesc(ds_state1, &ds_desc); ok(!ds_desc.DepthEnable, "Got unexpected depth enable %#x.\n", ds_desc.DepthEnable); ok(ds_desc.DepthWriteMask == D3D11_DEPTH_WRITE_MASK_ALL, "Got unexpected depth write mask %#x.\n", ds_desc.DepthWriteMask); ok(ds_desc.DepthFunc == D3D11_COMPARISON_LESS, "Got unexpected depth func %#x.\n", ds_desc.DepthFunc); ok(!ds_desc.StencilEnable, "Got unexpected stencil enable %#x.\n", ds_desc.StencilEnable); ok(ds_desc.StencilReadMask == D3D11_DEFAULT_STENCIL_READ_MASK, "Got unexpected stencil read mask %#x.\n", ds_desc.StencilReadMask); ok(ds_desc.StencilWriteMask == D3D11_DEFAULT_STENCIL_WRITE_MASK, "Got unexpected stencil write mask %#x.\n", ds_desc.StencilWriteMask); ok(ds_desc.FrontFace.StencilDepthFailOp == D3D11_STENCIL_OP_KEEP, "Got unexpected front face stencil depth fail op %#x.\n", ds_desc.FrontFace.StencilDepthFailOp); ok(ds_desc.FrontFace.StencilPassOp == D3D11_STENCIL_OP_KEEP, "Got unexpected front face stencil pass op %#x.\n", ds_desc.FrontFace.StencilPassOp); ok(ds_desc.FrontFace.StencilFailOp == D3D11_STENCIL_OP_KEEP, "Got unexpected front face stencil fail op %#x.\n", ds_desc.FrontFace.StencilFailOp); ok(ds_desc.FrontFace.StencilFunc == D3D11_COMPARISON_ALWAYS, "Got unexpected front face stencil func %#x.\n", ds_desc.FrontFace.StencilFunc); ok(ds_desc.BackFace.StencilDepthFailOp == D3D11_STENCIL_OP_KEEP, "Got unexpected back face stencil depth fail op %#x.\n", ds_desc.BackFace.StencilDepthFailOp); ok(ds_desc.BackFace.StencilPassOp == D3D11_STENCIL_OP_KEEP, "Got unexpected back face stencil pass op %#x.\n", ds_desc.BackFace.StencilPassOp); ok(ds_desc.BackFace.StencilFailOp == D3D11_STENCIL_OP_KEEP, "Got unexpected back face stencil fail op %#x.\n", ds_desc.BackFace.StencilFailOp); ok(ds_desc.BackFace.StencilFunc == D3D11_COMPARISON_ALWAYS, "Got unexpected back face stencil func %#x.\n", ds_desc.BackFace.StencilFunc); ID3D11DepthStencilState_Release(ds_state1); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_rasterizer_state(void) { ID3D11RasterizerState *rast_state1, *rast_state2; ID3D10RasterizerState *d3d10_rast_state; ULONG refcount, expected_refcount; D3D10_RASTERIZER_DESC d3d10_desc; D3D11_RASTERIZER_DESC desc; ID3D11Device *device, *tmp; HRESULT hr; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } hr = ID3D11Device_CreateRasterizerState(device, NULL, &rast_state1); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); desc.FillMode = D3D11_FILL_SOLID; desc.CullMode = D3D11_CULL_BACK; desc.FrontCounterClockwise = FALSE; desc.DepthBias = 0; desc.DepthBiasClamp = 0.0f; desc.SlopeScaledDepthBias = 0.0f; desc.DepthClipEnable = TRUE; desc.ScissorEnable = FALSE; desc.MultisampleEnable = FALSE; desc.AntialiasedLineEnable = FALSE; expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateRasterizerState(device, &desc, &rast_state1); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); hr = ID3D11Device_CreateRasterizerState(device, &desc, &rast_state2); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ok(rast_state1 == rast_state2, "Got different rasterizer state objects.\n"); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11RasterizerState_GetDevice(rast_state1, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); hr = ID3D11RasterizerState_QueryInterface(rast_state1, &IID_ID3D10RasterizerState, (void **)&d3d10_rast_state); ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, "Rasterizer state should implement ID3D10RasterizerState.\n"); if (SUCCEEDED(hr)) { ID3D10RasterizerState_GetDesc(d3d10_rast_state, &d3d10_desc); ok(d3d10_desc.FillMode == D3D10_FILL_SOLID, "Got unexpected fill mode %u.\n", d3d10_desc.FillMode); ok(d3d10_desc.CullMode == D3D10_CULL_BACK, "Got unexpected cull mode %u.\n", d3d10_desc.CullMode); ok(!d3d10_desc.FrontCounterClockwise, "Got unexpected front counter clockwise %#x.\n", d3d10_desc.FrontCounterClockwise); ok(!d3d10_desc.DepthBias, "Got unexpected depth bias %d.\n", d3d10_desc.DepthBias); ok(!d3d10_desc.DepthBiasClamp, "Got unexpected depth bias clamp %f.\n", d3d10_desc.DepthBiasClamp); ok(!d3d10_desc.SlopeScaledDepthBias, "Got unexpected slope scaled depth bias %f.\n", d3d10_desc.SlopeScaledDepthBias); ok(!!d3d10_desc.DepthClipEnable, "Got unexpected depth clip enable %#x.\n", d3d10_desc.DepthClipEnable); ok(!d3d10_desc.ScissorEnable, "Got unexpected scissor enable %#x.\n", d3d10_desc.ScissorEnable); ok(!d3d10_desc.MultisampleEnable, "Got unexpected multisample enable %#x.\n", d3d10_desc.MultisampleEnable); ok(!d3d10_desc.AntialiasedLineEnable, "Got unexpected antialiased line enable %#x.\n", d3d10_desc.AntialiasedLineEnable); refcount = ID3D10RasterizerState_Release(d3d10_rast_state); ok(refcount == 2, "Got unexpected refcount %u.\n", refcount); } refcount = ID3D11RasterizerState_Release(rast_state2); ok(refcount == 1, "Got unexpected refcount %u.\n", refcount); refcount = ID3D11RasterizerState_Release(rast_state1); ok(!refcount, "Got unexpected refcount %u.\n", refcount); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_query(void) { static const struct { D3D11_QUERY query; D3D_FEATURE_LEVEL required_feature_level; BOOL is_predicate; BOOL can_use_create_predicate; BOOL todo; } tests[] = { {D3D11_QUERY_EVENT, D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, FALSE}, {D3D11_QUERY_OCCLUSION, D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, FALSE}, {D3D11_QUERY_TIMESTAMP, D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, FALSE}, {D3D11_QUERY_TIMESTAMP_DISJOINT, D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, FALSE}, {D3D11_QUERY_PIPELINE_STATISTICS, D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, FALSE}, {D3D11_QUERY_OCCLUSION_PREDICATE, D3D_FEATURE_LEVEL_10_0, TRUE, TRUE, FALSE}, {D3D11_QUERY_SO_STATISTICS, D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, FALSE}, {D3D11_QUERY_SO_OVERFLOW_PREDICATE, D3D_FEATURE_LEVEL_10_0, TRUE, TRUE, TRUE}, {D3D11_QUERY_SO_STATISTICS_STREAM0, D3D_FEATURE_LEVEL_11_0, FALSE, FALSE, FALSE}, {D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0, D3D_FEATURE_LEVEL_11_0, TRUE, FALSE, TRUE}, {D3D11_QUERY_SO_STATISTICS_STREAM1, D3D_FEATURE_LEVEL_11_0, FALSE, FALSE, FALSE}, {D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1, D3D_FEATURE_LEVEL_11_0, TRUE, FALSE, TRUE}, {D3D11_QUERY_SO_STATISTICS_STREAM2, D3D_FEATURE_LEVEL_11_0, FALSE, FALSE, FALSE}, {D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2, D3D_FEATURE_LEVEL_11_0, TRUE, FALSE, TRUE}, {D3D11_QUERY_SO_STATISTICS_STREAM3, D3D_FEATURE_LEVEL_11_0, FALSE, FALSE, FALSE}, {D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3, D3D_FEATURE_LEVEL_11_0, TRUE, FALSE, TRUE}, }; ULONG refcount, expected_refcount; D3D_FEATURE_LEVEL feature_level; D3D11_QUERY_DESC query_desc; ID3D11Predicate *predicate; ID3D11Device *device, *tmp; HRESULT hr, expected_hr; ID3D11Query *query; unsigned int i; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } feature_level = ID3D11Device_GetFeatureLevel(device); hr = ID3D11Device_CreateQuery(device, NULL, &query); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CreatePredicate(device, NULL, &predicate); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(tests); ++i) { if (tests[i].required_feature_level > feature_level) { skip("Query type %u requires feature level %#x.\n", tests[i].query, tests[i].required_feature_level); continue; } query_desc.Query = tests[i].query; query_desc.MiscFlags = 0; hr = ID3D11Device_CreateQuery(device, &query_desc, NULL); todo_wine_if(tests[i].todo) ok(hr == S_FALSE, "Got unexpected hr %#x for query type %u.\n", hr, query_desc.Query); query_desc.Query = tests[i].query; hr = ID3D11Device_CreateQuery(device, &query_desc, &query); todo_wine_if(tests[i].todo) ok(hr == S_OK, "Got unexpected hr %#x for query type %u.\n", hr, query_desc.Query); if (FAILED(hr)) continue; check_interface(query, &IID_ID3D11Predicate, tests[i].is_predicate, FALSE); ID3D11Query_Release(query); expected_hr = tests[i].can_use_create_predicate ? S_FALSE : E_INVALIDARG; hr = ID3D11Device_CreatePredicate(device, &query_desc, NULL); ok(hr == expected_hr, "Got unexpected hr %#x for query type %u.\n", hr, query_desc.Query); expected_hr = tests[i].can_use_create_predicate ? S_OK : E_INVALIDARG; hr = ID3D11Device_CreatePredicate(device, &query_desc, &predicate); ok(hr == expected_hr, "Got unexpected hr %#x for query type %u.\n", hr, query_desc.Query); if (SUCCEEDED(hr)) ID3D11Predicate_Release(predicate); } query_desc.Query = D3D11_QUERY_OCCLUSION_PREDICATE; expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreatePredicate(device, &query_desc, &predicate); ok(SUCCEEDED(hr), "Failed to create predicate, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11Predicate_GetDevice(predicate, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); /* Not available on all Windows versions. */ check_interface(predicate, &IID_ID3D10Predicate, TRUE, TRUE); ID3D11Predicate_Release(predicate); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } #define get_query_data(a, b, c, d) get_query_data_(__LINE__, a, b, c, d) static void get_query_data_(unsigned int line, ID3D11DeviceContext *context, ID3D11Asynchronous *query, void *data, unsigned int data_size) { unsigned int i; HRESULT hr; for (i = 0; i < 500; ++i) { if ((hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0)) != S_FALSE) break; Sleep(10); } ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#x.\n", hr); memset(data, 0xff, data_size); hr = ID3D11DeviceContext_GetData(context, query, data, data_size, 0); ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#x.\n", hr); } static void test_occlusion_query(void) { static const struct vec4 red = {1.0f, 0.0f, 0.0f, 1.0f}; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; D3D11_QUERY_DESC query_desc; ID3D11Asynchronous *query; unsigned int data_size, i; ID3D11Texture2D *texture; ID3D11Device *device; union { UINT64 uint; DWORD dword[2]; } data; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); query_desc.Query = D3D11_QUERY_OCCLUSION; query_desc.MiscFlags = 0; hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)&query); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); data_size = ID3D11Asynchronous_GetDataSize(query); ok(data_size == sizeof(data), "Got unexpected data size %u.\n", data_size); memset(&data, 0xff, sizeof(data)); hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data), 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ok(data.dword[0] == 0xffffffff && data.dword[1] == 0xffffffff, "Data was modified 0x%08x%08x.\n", data.dword[1], data.dword[0]); ID3D11DeviceContext_End(context, query); ID3D11DeviceContext_Begin(context, query); ID3D11DeviceContext_Begin(context, query); memset(&data, 0xff, sizeof(data)); hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data), 0); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ok(data.dword[0] == 0xffffffff && data.dword[1] == 0xffffffff, "Data was modified 0x%08x%08x.\n", data.dword[1], data.dword[0]); draw_color_quad(&test_context, &red); ID3D11DeviceContext_End(context, query); get_query_data(context, query, &data, sizeof(data)); ok(data.uint == 640 * 480, "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]); memset(&data, 0xff, sizeof(data)); hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(DWORD), 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(WORD), 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data) - 1, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data) + 1, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ok(data.dword[0] == 0xffffffff && data.dword[1] == 0xffffffff, "Data was modified 0x%08x%08x.\n", data.dword[1], data.dword[0]); memset(&data, 0xff, sizeof(data)); hr = ID3D11DeviceContext_GetData(context, query, &data, 0, 0); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(data.dword[0] == 0xffffffff && data.dword[1] == 0xffffffff, "Data was modified 0x%08x%08x.\n", data.dword[1], data.dword[0]); hr = ID3D11DeviceContext_GetData(context, query, NULL, sizeof(DWORD), 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, query, NULL, sizeof(data), 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_Begin(context, query); ID3D11DeviceContext_End(context, query); ID3D11DeviceContext_End(context, query); get_query_data(context, query, &data, sizeof(data)); ok(!data.uint, "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]); hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); texture_desc.Width = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; texture_desc.Height = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); set_viewport(context, 0.0f, 0.0f, texture_desc.Width, texture_desc.Height, 0.0f, 1.0f); ID3D11DeviceContext_Begin(context, query); for (i = 0; i < 100; i++) draw_color_quad(&test_context, &red); ID3D11DeviceContext_End(context, query); get_query_data(context, query, &data, sizeof(data)); ok((data.dword[0] == 0x90000000 && data.dword[1] == 0x1) || (data.dword[0] == 0xffffffff && !data.dword[1]) || broken(!data.uint), "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]); hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11Asynchronous_Release(query); /* The following test exercises a code path in wined3d. A wined3d context * associated with the query is destroyed when the swapchain is released. */ hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)&query); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); set_viewport(context, 0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ID3D11DeviceContext_Begin(context, query); draw_color_quad(&test_context, &red); ID3D11DeviceContext_End(context, query); ID3D11RenderTargetView_Release(test_context.backbuffer_rtv); ID3D11Texture2D_Release(test_context.backbuffer); IDXGISwapChain_Release(test_context.swapchain); test_context.swapchain = create_swapchain(device, test_context.window, NULL); hr = IDXGISwapChain_GetBuffer(test_context.swapchain, 0, &IID_ID3D11Texture2D, (void **)&test_context.backbuffer); ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)test_context.backbuffer, NULL, &test_context.backbuffer_rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, NULL); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); get_query_data(context, query, &data, sizeof(data)); /* This test occasionally succeeds with CSMT enabled because of a race condition. */ if (0) todo_wine ok(data.dword[0] == 0x1000 && !data.dword[1], "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]); ID3D11Asynchronous_Release(query); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_pipeline_statistics_query(void) { static const struct vec4 red = {1.0f, 0.0f, 0.0f, 1.0f}; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; D3D11_QUERY_DATA_PIPELINE_STATISTICS data; struct d3d11_test_context test_context; ID3D11DeviceContext *context; D3D11_QUERY_DESC query_desc; ID3D11Asynchronous *query; unsigned int data_size; ID3D11Device *device; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); query_desc.Query = D3D11_QUERY_PIPELINE_STATISTICS; query_desc.MiscFlags = 0; hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)&query); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); data_size = ID3D11Asynchronous_GetDataSize(query); ok(data_size == sizeof(data), "Got unexpected data size %u.\n", data_size); hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data), 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_End(context, query); ID3D11DeviceContext_Begin(context, query); ID3D11DeviceContext_Begin(context, query); memset(&data, 0xff, sizeof(data)); hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data), 0); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ok(data.IAVertices == ~(UINT64)0, "Data was modified.\n"); draw_quad(&test_context); ID3D11DeviceContext_End(context, query); get_query_data(context, query, &data, sizeof(data)); ok(data.IAVertices == 4, "Got unexpected IAVertices count: %u.\n", (unsigned int)data.IAVertices); ok(data.IAPrimitives == 2, "Got unexpected IAPrimitives count: %u.\n", (unsigned int)data.IAPrimitives); ok(data.VSInvocations == 4, "Got unexpected VSInvocations count: %u.\n", (unsigned int)data.VSInvocations); ok(!data.GSInvocations, "Got unexpected GSInvocations count: %u.\n", (unsigned int)data.GSInvocations); ok(!data.GSPrimitives, "Got unexpected GSPrimitives count: %u.\n", (unsigned int)data.GSPrimitives); ok(data.CInvocations == 2, "Got unexpected CInvocations count: %u.\n", (unsigned int)data.CInvocations); ok(data.CPrimitives == 2, "Got unexpected CPrimitives count: %u.\n", (unsigned int)data.CPrimitives); todo_wine ok(!data.PSInvocations, "Got unexpected PSInvocations count: %u.\n", (unsigned int)data.PSInvocations); ok(!data.HSInvocations, "Got unexpected HSInvocations count: %u.\n", (unsigned int)data.HSInvocations); ok(!data.DSInvocations, "Got unexpected DSInvocations count: %u.\n", (unsigned int)data.DSInvocations); ok(!data.CSInvocations, "Got unexpected CSInvocations count: %u.\n", (unsigned int)data.CSInvocations); ID3D11DeviceContext_Begin(context, query); draw_color_quad(&test_context, &red); ID3D11DeviceContext_End(context, query); get_query_data(context, query, &data, sizeof(data)); ok(data.IAVertices == 4, "Got unexpected IAVertices count: %u.\n", (unsigned int)data.IAVertices); ok(data.IAPrimitives == 2, "Got unexpected IAPrimitives count: %u.\n", (unsigned int)data.IAPrimitives); ok(data.VSInvocations == 4, "Got unexpected VSInvocations count: %u.\n", (unsigned int)data.VSInvocations); ok(!data.GSInvocations, "Got unexpected GSInvocations count: %u.\n", (unsigned int)data.GSInvocations); ok(!data.GSPrimitives, "Got unexpected GSPrimitives count: %u.\n", (unsigned int)data.GSPrimitives); ok(data.CInvocations == 2, "Got unexpected CInvocations count: %u.\n", (unsigned int)data.CInvocations); ok(data.CPrimitives == 2, "Got unexpected CPrimitives count: %u.\n", (unsigned int)data.CPrimitives); ok(data.PSInvocations >= 640 * 480, "Got unexpected PSInvocations count: %u.\n", (unsigned int)data.PSInvocations); ok(!data.HSInvocations, "Got unexpected HSInvocations count: %u.\n", (unsigned int)data.HSInvocations); ok(!data.DSInvocations, "Got unexpected DSInvocations count: %u.\n", (unsigned int)data.DSInvocations); ok(!data.CSInvocations, "Got unexpected CSInvocations count: %u.\n", (unsigned int)data.CSInvocations); ID3D11Asynchronous_Release(query); release_test_context(&test_context); } static void test_timestamp_query(void) { static const struct vec4 red = {1.0f, 0.0f, 0.0f, 1.0f}; ID3D11Asynchronous *timestamp_query, *timestamp_disjoint_query; D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint, prev_disjoint; struct d3d11_test_context test_context; ID3D11DeviceContext *context; D3D11_QUERY_DESC query_desc; unsigned int data_size; ID3D11Device *device; UINT64 timestamp; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; query_desc.Query = D3D11_QUERY_TIMESTAMP; query_desc.MiscFlags = 0; hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)×tamp_query); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); data_size = ID3D11Asynchronous_GetDataSize(timestamp_query); ok(data_size == sizeof(UINT64), "Got unexpected data size %u.\n", data_size); query_desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; query_desc.MiscFlags = 0; hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)×tamp_disjoint_query); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); data_size = ID3D11Asynchronous_GetDataSize(timestamp_disjoint_query); ok(data_size == sizeof(disjoint), "Got unexpected data size %u.\n", data_size); disjoint.Frequency = 0xdeadbeef; disjoint.Disjoint = 0xdeadbeef; hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, NULL, 0, 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, &disjoint, sizeof(disjoint), 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ok(disjoint.Frequency == 0xdeadbeef, "Frequency data was modified.\n"); ok(disjoint.Disjoint == 0xdeadbeef, "Disjoint data was modified.\n"); /* Test a TIMESTAMP_DISJOINT query. */ ID3D11DeviceContext_Begin(context, timestamp_disjoint_query); disjoint.Frequency = 0xdeadbeef; disjoint.Disjoint = 0xdeadbeef; hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, NULL, 0, 0); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, &disjoint, sizeof(disjoint), 0); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ok(disjoint.Frequency == 0xdeadbeef, "Frequency data was modified.\n"); ok(disjoint.Disjoint == 0xdeadbeef, "Disjoint data was modified.\n"); ID3D11DeviceContext_End(context, timestamp_disjoint_query); get_query_data(context, timestamp_disjoint_query, &disjoint, sizeof(disjoint)); ok(disjoint.Frequency != ~(UINT64)0, "Frequency data was not modified.\n"); ok(disjoint.Disjoint == TRUE || disjoint.Disjoint == FALSE, "Got unexpected disjoint %#x.\n", disjoint.Disjoint); prev_disjoint = disjoint; disjoint.Frequency = 0xdeadbeef; disjoint.Disjoint = 0xff; hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, &disjoint, sizeof(disjoint) - 1, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, &disjoint, sizeof(disjoint) + 1, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, &disjoint, sizeof(disjoint) / 2, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, &disjoint, sizeof(disjoint) * 2, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ok(disjoint.Frequency == 0xdeadbeef, "Frequency data was modified.\n"); ok(disjoint.Disjoint == 0xff, "Disjoint data was modified.\n"); hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, NULL, 0, 0); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, &disjoint, sizeof(disjoint), D3D11_ASYNC_GETDATA_DONOTFLUSH); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(disjoint.Frequency == prev_disjoint.Frequency, "Frequency data mismatch.\n"); ok(disjoint.Disjoint == prev_disjoint.Disjoint, "Disjoint data mismatch.\n"); memset(×tamp, 0xff, sizeof(timestamp)); hr = ID3D11DeviceContext_GetData(context, timestamp_query, NULL, 0, 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, timestamp_query, ×tamp, sizeof(timestamp), 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ok(timestamp == ~(UINT64)0, "Timestamp data was modified.\n"); /* Test a TIMESTAMP query inside a TIMESTAMP_DISJOINT query. */ ID3D11DeviceContext_Begin(context, timestamp_disjoint_query); memset(×tamp, 0xff, sizeof(timestamp)); hr = ID3D11DeviceContext_GetData(context, timestamp_query, ×tamp, sizeof(timestamp), 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ok(timestamp == ~(UINT64)0, "Timestamp data was modified.\n"); draw_color_quad(&test_context, &red); ID3D11DeviceContext_End(context, timestamp_query); get_query_data(context, timestamp_query, ×tamp, sizeof(timestamp)); timestamp = 0xdeadbeef; hr = ID3D11DeviceContext_GetData(context, timestamp_query, ×tamp, sizeof(timestamp) / 2, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ok(timestamp == 0xdeadbeef, "Timestamp was modified.\n"); hr = ID3D11DeviceContext_GetData(context, timestamp_query, ×tamp, sizeof(timestamp), 0); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(timestamp != 0xdeadbeef, "Timestamp was not modified.\n"); timestamp = 0xdeadbeef; hr = ID3D11DeviceContext_GetData(context, timestamp_query, ×tamp, sizeof(timestamp) - 1, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, timestamp_query, ×tamp, sizeof(timestamp) + 1, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, timestamp_query, ×tamp, sizeof(timestamp) / 2, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, timestamp_query, ×tamp, sizeof(timestamp) * 2, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ok(timestamp == 0xdeadbeef, "Timestamp was modified.\n"); ID3D11DeviceContext_End(context, timestamp_disjoint_query); get_query_data(context, timestamp_disjoint_query, &disjoint, sizeof(disjoint)); disjoint.Frequency = 0xdeadbeef; disjoint.Disjoint = 0xff; hr = ID3D11DeviceContext_GetData(context, timestamp_disjoint_query, &disjoint, sizeof(disjoint), 0); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(disjoint.Frequency != 0xdeadbeef, "Frequency data was not modified.\n"); ok(disjoint.Disjoint == TRUE || disjoint.Disjoint == FALSE, "Got unexpected disjoint %#x.\n", disjoint.Disjoint); /* It's not strictly necessary for the TIMESTAMP query to be inside a TIMESTAMP_DISJOINT query. */ ID3D11Asynchronous_Release(timestamp_query); query_desc.Query = D3D11_QUERY_TIMESTAMP; query_desc.MiscFlags = 0; hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)×tamp_query); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); draw_color_quad(&test_context, &red); ID3D11DeviceContext_End(context, timestamp_query); get_query_data(context, timestamp_query, ×tamp, sizeof(timestamp)); ID3D11Asynchronous_Release(timestamp_query); ID3D11Asynchronous_Release(timestamp_disjoint_query); release_test_context(&test_context); } static void test_so_statistics_query(void) { struct d3d11_test_context test_context; D3D11_QUERY_DATA_SO_STATISTICS data; ID3D11DeviceContext *context; unsigned int vertex_count[4]; D3D11_QUERY_DESC query_desc; ID3D11Buffer *so_buffer[4]; ID3D11Asynchronous *query; ID3D11GeometryShader *gs; ID3D11VertexShader *vs; unsigned int data_size; ID3D11Device *device; ID3D11Buffer *cb; unsigned int i; HRESULT hr; static const DWORD vs_code[] = { #if 0 float4 main(uint id : SV_VertexID) : custom { return (float4)id; } #endif 0x43425844, 0x8b0e47b9, 0x6efc9512, 0xd55ca6ff, 0x487c5ef2, 0x00000001, 0x000000d4, 0x00000003, 0x0000002c, 0x00000060, 0x00000090, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000006, 0x00000001, 0x00000000, 0x00000101, 0x565f5653, 0x65747265, 0x00444978, 0x4e47534f, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x74737563, 0xab006d6f, 0x52444853, 0x0000003c, 0x00010040, 0x0000000f, 0x04000060, 0x00101012, 0x00000000, 0x00000006, 0x03000065, 0x001020f2, 0x00000000, 0x05000056, 0x001020f2, 0x00000000, 0x00101006, 0x00000000, 0x0100003e, }; static const DWORD gs_code[] = { #if 0 struct vertex { float4 data : custom; }; uint4 vertex_count; [maxvertexcount(32)] void main(point vertex input[1], uint id : SV_PrimitiveID, inout PointStream output0, inout PointStream output1, inout PointStream output2, inout PointStream output3) { if (id < vertex_count.x) output0.Append(input[0]); if (id < vertex_count.y) output1.Append(input[0]); if (id < vertex_count.z) output2.Append(input[0]); if (id < vertex_count.w) output3.Append(input[0]); } #endif 0x43425844, 0xd616829d, 0x4355ce2a, 0xd71909e5, 0xdc916d4c, 0x00000001, 0x000002bc, 0x00000003, 0x0000002c, 0x00000084, 0x0000010c, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x0000003f, 0x00000000, 0x00000007, 0x00000001, 0xffffffff, 0x00000101, 0x74737563, 0x53006d6f, 0x72505f56, 0x74696d69, 0x49657669, 0xabab0044, 0x3547534f, 0x00000080, 0x00000004, 0x00000008, 0x00000000, 0x00000078, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000001, 0x00000078, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000002, 0x00000078, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000003, 0x00000078, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x74737563, 0xab006d6f, 0x58454853, 0x000001a8, 0x00020050, 0x0000006a, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0400005f, 0x002010f2, 0x00000001, 0x00000000, 0x0200005f, 0x0000b000, 0x02000068, 0x00000001, 0x0100085d, 0x0300008f, 0x00110000, 0x00000000, 0x0100085c, 0x03000065, 0x001020f2, 0x00000000, 0x0300008f, 0x00110000, 0x00000001, 0x0100085c, 0x03000065, 0x001020f2, 0x00000000, 0x0300008f, 0x00110000, 0x00000002, 0x0100085c, 0x03000065, 0x001020f2, 0x00000000, 0x0300008f, 0x00110000, 0x00000003, 0x0100085c, 0x03000065, 0x001020f2, 0x00000000, 0x0200005e, 0x00000020, 0x0700004f, 0x001000f2, 0x00000000, 0x0000b001, 0x00208e46, 0x00000000, 0x00000000, 0x0304001f, 0x0010000a, 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000000, 0x00000000, 0x03000075, 0x00110000, 0x00000000, 0x01000015, 0x0304001f, 0x0010001a, 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000000, 0x00000000, 0x03000075, 0x00110000, 0x00000001, 0x01000015, 0x0304001f, 0x0010002a, 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000000, 0x00000000, 0x03000075, 0x00110000, 0x00000002, 0x01000015, 0x0304001f, 0x0010003a, 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000000, 0x00000000, 0x03000075, 0x00110000, 0x00000003, 0x01000015, 0x0100003e, }; static const D3D11_SO_DECLARATION_ENTRY so_declaration[] = { {0, "custom", 0, 0, 4, 0}, {1, "custom", 0, 0, 4, 1}, {2, "custom", 0, 0, 4, 2}, {3, "custom", 0, 0, 4, 3}, }; static const unsigned int offset[4] = {0}; static const struct { D3D11_QUERY query; D3D_FEATURE_LEVEL feature_level; } tests[] = { {D3D11_QUERY_SO_STATISTICS, D3D_FEATURE_LEVEL_10_0}, {D3D11_QUERY_SO_STATISTICS_STREAM0, D3D_FEATURE_LEVEL_11_0}, {D3D11_QUERY_SO_STATISTICS_STREAM1, D3D_FEATURE_LEVEL_11_0}, {D3D11_QUERY_SO_STATISTICS_STREAM2, D3D_FEATURE_LEVEL_11_0}, {D3D11_QUERY_SO_STATISTICS_STREAM3, D3D_FEATURE_LEVEL_11_0}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; for (i = 0; i < ARRAY_SIZE(tests); ++i) { if (ID3D11Device_GetFeatureLevel(device) < tests[i].feature_level) { skip("Feature level %#x is required.\n", tests[i].feature_level); continue; } query_desc.Query = tests[i].query; query_desc.MiscFlags = 0; hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)&query); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); data_size = ID3D11Asynchronous_GetDataSize(query); ok(data_size == sizeof(data), "Got unexpected data size %u.\n", data_size); hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data), 0); ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_End(context, query); ID3D11DeviceContext_Begin(context, query); ID3D11DeviceContext_Begin(context, query); memset(&data, 0xff, sizeof(data)); hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data), 0); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ok(data.NumPrimitivesWritten == ~(UINT64)0, "Data was modified.\n"); ok(data.PrimitivesStorageNeeded == ~(UINT64)0, "Data was modified.\n"); draw_quad(&test_context); ID3D11DeviceContext_End(context, query); get_query_data(context, query, &data, sizeof(data)); ok(!data.NumPrimitivesWritten, "Got unexpected NumPrimitivesWritten: %u.\n", (unsigned int)data.NumPrimitivesWritten); todo_wine_if(query_desc.Query == D3D11_QUERY_SO_STATISTICS || query_desc.Query == D3D11_QUERY_SO_STATISTICS_STREAM0) ok(!data.PrimitivesStorageNeeded, "Got unexpected PrimitivesStorageNeeded: %u.\n", (unsigned int)data.PrimitivesStorageNeeded); ID3D11DeviceContext_Begin(context, query); draw_quad(&test_context); ID3D11DeviceContext_End(context, query); get_query_data(context, query, &data, sizeof(data)); ok(!data.NumPrimitivesWritten, "Got unexpected NumPrimitivesWritten: %u.\n", (unsigned int)data.NumPrimitivesWritten); todo_wine_if(query_desc.Query == D3D11_QUERY_SO_STATISTICS || query_desc.Query == D3D11_QUERY_SO_STATISTICS_STREAM0) ok(!data.PrimitivesStorageNeeded, "Got unexpected PrimitivesStorageNeeded: %u.\n", (unsigned int)data.PrimitivesStorageNeeded); ID3D11Asynchronous_Release(query); } if (ID3D11Device_GetFeatureLevel(device) < D3D_FEATURE_LEVEL_11_0) { skip("Vertex streams are not supported.\n"); goto done; } /* multiple vertex streams */ hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(hr == S_OK, "Failed to create vertex shader, hr %#x.\n", hr); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); hr = ID3D11Device_CreateGeometryShaderWithStreamOutput(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &gs); todo_wine ok(hr == S_OK, "Failed to create geometry shader with stream output, hr %#x.\n", hr); if (FAILED(hr)) { ID3D11VertexShader_Release(vs); goto done; } ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); for (i = 0; i < ARRAY_SIZE(vertex_count); ++i) vertex_count[i] = 5; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(vertex_count), vertex_count); ID3D11DeviceContext_GSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); query_desc.Query = D3D11_QUERY_SO_STATISTICS; query_desc.MiscFlags = 0; hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)&query); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_Begin(context, query); ID3D11DeviceContext_Draw(context, 5, 0); ID3D11DeviceContext_End(context, query); memset(&data, 0xff, sizeof(data)); get_query_data(context, query, &data, sizeof(data)); ok(!data.NumPrimitivesWritten, "Got unexpected primitives written %u.\n", (unsigned int)data.NumPrimitivesWritten); ok(data.PrimitivesStorageNeeded == 5, "Got unexpected primitives storage needed %u.\n", (unsigned int)data.PrimitivesStorageNeeded); for (i = 0; i < ARRAY_SIZE(so_buffer); ++i) so_buffer[i] = create_buffer(device, D3D11_BIND_STREAM_OUTPUT, sizeof(struct vec4) * 10, NULL); ID3D11DeviceContext_SOSetTargets(context, D3D11_SO_BUFFER_SLOT_COUNT, so_buffer, offset); ID3D11DeviceContext_Begin(context, query); ID3D11DeviceContext_Draw(context, 16, 0); ID3D11DeviceContext_End(context, query); memset(&data, 0xff, sizeof(data)); get_query_data(context, query, &data, sizeof(data)); ok(data.NumPrimitivesWritten == 5, "Got unexpected primitives written %u.\n", (unsigned int)data.NumPrimitivesWritten); ok(data.PrimitivesStorageNeeded == 5, "Got unexpected primitives storage needed %u.\n", (unsigned int)data.PrimitivesStorageNeeded); vertex_count[0] = 3; vertex_count[1] = 6; vertex_count[2] = 4; vertex_count[3] = 12; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, vertex_count, 0, 0); ID3D11DeviceContext_SOSetTargets(context, D3D11_SO_BUFFER_SLOT_COUNT, so_buffer, offset); ID3D11DeviceContext_Begin(context, query); ID3D11DeviceContext_Draw(context, 32, 0); ID3D11DeviceContext_End(context, query); memset(&data, 0xff, sizeof(data)); get_query_data(context, query, &data, sizeof(data)); ok(data.NumPrimitivesWritten == 3, "Got unexpected primitives written %u.\n", (unsigned int)data.NumPrimitivesWritten); ok(data.PrimitivesStorageNeeded == 3, "Got unexpected primitives storage needed %u.\n", (unsigned int)data.PrimitivesStorageNeeded); vertex_count[0] = 16; vertex_count[1] = 6; vertex_count[2] = 4; vertex_count[3] = 12; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, vertex_count, 0, 0); ID3D11DeviceContext_SOSetTargets(context, D3D11_SO_BUFFER_SLOT_COUNT, so_buffer, offset); ID3D11DeviceContext_Begin(context, query); ID3D11DeviceContext_Draw(context, 32, 0); ID3D11DeviceContext_End(context, query); memset(&data, 0xff, sizeof(data)); get_query_data(context, query, &data, sizeof(data)); ok(data.NumPrimitivesWritten == 10, "Got unexpected primitives written %u.\n", (unsigned int)data.NumPrimitivesWritten); ok(data.PrimitivesStorageNeeded == 16, "Got unexpected primitives storage needed %u.\n", (unsigned int)data.PrimitivesStorageNeeded); ID3D11Asynchronous_Release(query); for (i = 0; i < ARRAY_SIZE(so_buffer); ++i) ID3D11Buffer_Release(so_buffer[i]); ID3D11Buffer_Release(cb); ID3D11GeometryShader_Release(gs); ID3D11VertexShader_Release(vs); done: release_test_context(&test_context); } static void test_device_removed_reason(void) { ID3D11Device *device; ULONG refcount; HRESULT hr; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } hr = ID3D11Device_GetDeviceRemovedReason(device); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_GetDeviceRemovedReason(device); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_private_data(void) { ULONG refcount, expected_refcount; D3D11_TEXTURE2D_DESC texture_desc; ID3D10Texture2D *d3d10_texture; ID3D11Device *test_object; ID3D11Texture2D *texture; IDXGIDevice *dxgi_device; IDXGISurface *surface; ID3D11Device *device; IUnknown *ptr; HRESULT hr; UINT size; static const GUID test_guid = {0xfdb37466, 0x428f, 0x4edf, {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}}; static const GUID test_guid2 = {0x2e5afac2, 0x87b5, 0x4c10, {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}}; static const DWORD data[] = {1, 2, 3, 4}; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } test_object = create_device(NULL); texture_desc.Width = 512; texture_desc.Height = 512; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Texture2D_QueryInterface(texture, &IID_IDXGISurface, (void **)&surface); ok(SUCCEEDED(hr), "Failed to get IDXGISurface, hr %#x.\n", hr); hr = ID3D11Device_SetPrivateData(device, &test_guid, 0, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_SetPrivateDataInterface(device, &test_guid, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_SetPrivateData(device, &test_guid, ~0u, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_SetPrivateData(device, &test_guid, ~0u, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_SetPrivateDataInterface(device, &test_guid, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); size = sizeof(ptr) * 2; ptr = (IUnknown *)0xdeadbeef; hr = ID3D11Device_GetPrivateData(device, &test_guid, &size, &ptr); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(!ptr, "Got unexpected pointer %p.\n", ptr); ok(size == sizeof(IUnknown *), "Got unexpected size %u.\n", size); hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); ok(SUCCEEDED(hr), "Failed to get DXGI device, hr %#x.\n", hr); size = sizeof(ptr) * 2; ptr = (IUnknown *)0xdeadbeef; hr = IDXGIDevice_GetPrivateData(dxgi_device, &test_guid, &size, &ptr); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(!ptr, "Got unexpected pointer %p.\n", ptr); ok(size == sizeof(IUnknown *), "Got unexpected size %u.\n", size); IDXGIDevice_Release(dxgi_device); refcount = get_refcount(test_object); hr = ID3D11Device_SetPrivateDataInterface(device, &test_guid, (IUnknown *)test_object); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); expected_refcount = refcount + 1; refcount = get_refcount(test_object); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); hr = ID3D11Device_SetPrivateDataInterface(device, &test_guid, (IUnknown *)test_object); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); refcount = get_refcount(test_object); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); hr = ID3D11Device_SetPrivateDataInterface(device, &test_guid, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); --expected_refcount; refcount = get_refcount(test_object); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); hr = ID3D11Device_SetPrivateDataInterface(device, &test_guid, (IUnknown *)test_object); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); size = sizeof(data); hr = ID3D11Device_SetPrivateData(device, &test_guid, size, data); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); refcount = get_refcount(test_object); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); hr = ID3D11Device_SetPrivateData(device, &test_guid, 42, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_SetPrivateData(device, &test_guid, 42, NULL); ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_SetPrivateDataInterface(device, &test_guid, (IUnknown *)test_object); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ++expected_refcount; size = 2 * sizeof(ptr); ptr = NULL; hr = ID3D11Device_GetPrivateData(device, &test_guid, &size, &ptr); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(size == sizeof(test_object), "Got unexpected size %u.\n", size); ++expected_refcount; refcount = get_refcount(test_object); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); IUnknown_Release(ptr); --expected_refcount; ptr = (IUnknown *)0xdeadbeef; size = 1; hr = ID3D11Device_GetPrivateData(device, &test_guid, &size, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(size == sizeof(device), "Got unexpected size %u.\n", size); size = 2 * sizeof(ptr); hr = ID3D11Device_GetPrivateData(device, &test_guid, &size, NULL); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(size == sizeof(device), "Got unexpected size %u.\n", size); refcount = get_refcount(test_object); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); size = 1; hr = ID3D11Device_GetPrivateData(device, &test_guid, &size, &ptr); ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr); ok(size == sizeof(device), "Got unexpected size %u.\n", size); ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr); if (!enable_debug_layer) { hr = ID3D11Device_GetPrivateData(device, &test_guid2, NULL, NULL); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); size = 0xdeadbabe; hr = ID3D11Device_GetPrivateData(device, &test_guid2, &size, &ptr); ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr); ok(size == 0, "Got unexpected size %u.\n", size); ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr); hr = ID3D11Device_GetPrivateData(device, &test_guid, NULL, &ptr); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr); } hr = ID3D11Texture2D_SetPrivateDataInterface(texture, &test_guid, (IUnknown *)test_object); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ptr = NULL; size = sizeof(ptr); hr = IDXGISurface_GetPrivateData(surface, &test_guid, &size, &ptr); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(ptr == (IUnknown *)test_object, "Got unexpected ptr %p, expected %p.\n", ptr, test_object); IUnknown_Release(ptr); hr = ID3D11Texture2D_QueryInterface(texture, &IID_ID3D10Texture2D, (void **)&d3d10_texture); ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, "Texture should implement ID3D10Texture2D.\n"); if (SUCCEEDED(hr)) { ptr = NULL; size = sizeof(ptr); hr = ID3D10Texture2D_GetPrivateData(d3d10_texture, &test_guid, &size, &ptr); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(ptr == (IUnknown *)test_object, "Got unexpected ptr %p, expected %p.\n", ptr, test_object); IUnknown_Release(ptr); ID3D10Texture2D_Release(d3d10_texture); } IDXGISurface_Release(surface); ID3D11Texture2D_Release(texture); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); refcount = ID3D11Device_Release(test_object); ok(!refcount, "Test object has %u references left.\n", refcount); } static void test_state_refcounting(const D3D_FEATURE_LEVEL feature_level) { ID3D11RasterizerState *rasterizer_state, *tmp_rasterizer_state; ID3D11Predicate *predicate, *tmp_predicate; ID3D11SamplerState *sampler, *tmp_sampler; ID3D11ShaderResourceView *srv, *tmp_srv; ID3D11RenderTargetView *rtv, *tmp_rtv; D3D11_RASTERIZER_DESC rasterizer_desc; D3D11_TEXTURE2D_DESC texture_desc; D3D11_QUERY_DESC predicate_desc; D3D11_SAMPLER_DESC sampler_desc; struct device_desc device_desc; ID3D11DeviceContext *context; ID3D11Texture2D *texture; ID3D11Device *device; ULONG refcount; HRESULT hr; device_desc.feature_level = &feature_level; device_desc.flags = 0; if (!(device = create_device(&device_desc))) { skip("Failed to create device for feature level %#x.\n", feature_level); return; } ID3D11Device_GetImmediateContext(device, &context); /* ID3D11SamplerState */ memset(&sampler_desc, 0, sizeof(sampler_desc)); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sampler_desc.MaxLOD = FLT_MAX; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &tmp_sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); ok(tmp_sampler == sampler, "Got sampler %p, expected %p.\n", tmp_sampler, sampler); ID3D11SamplerState_Release(tmp_sampler); tmp_sampler = sampler; refcount = get_refcount(sampler); ok(refcount == 1, "Got refcount %u, expected 1.\n", refcount); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); refcount = ID3D11SamplerState_Release(sampler); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); sampler = NULL; ID3D11DeviceContext_PSGetSamplers(context, 0, 1, &sampler); ok(sampler == tmp_sampler, "Got sampler %p, expected %p.\n", sampler, tmp_sampler); refcount = ID3D11SamplerState_Release(sampler); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &tmp_sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); ok(tmp_sampler == sampler, "Got sampler %p, expected %p.\n", tmp_sampler, sampler); refcount = ID3D11SamplerState_Release(tmp_sampler); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); /* ID3D11RasterizerState */ memset(&rasterizer_desc, 0, sizeof(rasterizer_desc)); rasterizer_desc.FillMode = D3D11_FILL_SOLID; rasterizer_desc.CullMode = D3D11_CULL_BACK; rasterizer_desc.DepthClipEnable = TRUE; hr = ID3D11Device_CreateRasterizerState(device, &rasterizer_desc, &rasterizer_state); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ID3D11DeviceContext_RSSetState(context, rasterizer_state); refcount = ID3D11RasterizerState_Release(rasterizer_state); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); ID3D11DeviceContext_RSGetState(context, &tmp_rasterizer_state); ok(tmp_rasterizer_state == rasterizer_state, "Got rasterizer state %p, expected %p.\n", tmp_rasterizer_state, rasterizer_state); refcount = ID3D11RasterizerState_Release(tmp_rasterizer_state); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); /* ID3D11ShaderResourceView */ memset(&texture_desc, 0, sizeof(texture_desc)); texture_desc.Width = 32; texture_desc.Height = 32; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); ID3D11Texture2D_Release(texture); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); refcount = ID3D11ShaderResourceView_Release(srv); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); ID3D11DeviceContext_PSGetShaderResources(context, 0, 1, &tmp_srv); ok(tmp_srv == srv, "Got SRV %p, expected %p.\n", tmp_srv, srv); refcount = ID3D11ShaderResourceView_Release(tmp_srv); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); /* ID3D11RenderTargetView */ texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11Texture2D_Release(texture); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); refcount = ID3D11RenderTargetView_Release(rtv); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); ID3D11DeviceContext_OMGetRenderTargets(context, 1, &tmp_rtv, NULL); ok(tmp_rtv == rtv, "Got RTV %p, expected %p.\n", tmp_rtv, rtv); refcount = ID3D11RenderTargetView_Release(tmp_rtv); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); /* ID3D11Predicate */ if (feature_level >= D3D_FEATURE_LEVEL_10_0) { predicate_desc.Query = D3D11_QUERY_OCCLUSION_PREDICATE; predicate_desc.MiscFlags = 0; hr = ID3D11Device_CreatePredicate(device, &predicate_desc, &predicate); ok(SUCCEEDED(hr), "Failed to create predicate, hr %#x.\n", hr); ID3D11DeviceContext_SetPredication(context, predicate, TRUE); refcount = ID3D11Predicate_Release(predicate); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); ID3D11DeviceContext_GetPredication(context, &tmp_predicate, NULL); ok(tmp_predicate == predicate, "Got predicate %p, expected %p.\n", tmp_predicate, predicate); refcount = ID3D11Predicate_Release(tmp_predicate); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); } ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_device_context_state(void) { ID3DDeviceContextState *context_state, *previous_context_state; ID3D11SamplerState *sampler, *tmp_sampler; ID3D11DeviceContext1 *context = NULL; D3D11_SAMPLER_DESC sampler_desc; D3D_FEATURE_LEVEL feature_level; ID3D11Device *d3d11_device; ID3D11Device1 *device; ULONG refcount; HRESULT hr; if (!(d3d11_device = create_device(NULL))) { skip("Failed to create device.\n"); return; } hr = ID3D11Device_QueryInterface(d3d11_device, &IID_ID3D11Device1, (void **)&device); ID3D11Device_Release(d3d11_device); if (FAILED(hr)) { skip("ID3D11Device1 is not available.\n"); return; } check_interface(device, &IID_ID3D10Device, FALSE, FALSE); check_interface(device, &IID_ID3D10Device1, FALSE, FALSE); feature_level = ID3D11Device1_GetFeatureLevel(device); ID3D11Device1_GetImmediateContext1(device, &context); ok(!!context, "Failed to get immediate context.\n"); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 1.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 1.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = 16.0f; hr = ID3D11Device1_CreateSamplerState(device, &sampler_desc, &sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); ID3D11DeviceContext1_PSSetSamplers(context, 0, 1, &sampler); tmp_sampler = NULL; ID3D11DeviceContext1_PSGetSamplers(context, 0, 1, &tmp_sampler); ok(tmp_sampler == sampler, "Got sampler %p, expected %p.\n", tmp_sampler, sampler); ID3D11SamplerState_Release(tmp_sampler); feature_level = min(feature_level, D3D_FEATURE_LEVEL_10_1); hr = ID3D11Device1_CreateDeviceContextState(device, 0, &feature_level, 1, D3D11_SDK_VERSION, &IID_ID3D10Device, NULL, &context_state); todo_wine ok(SUCCEEDED(hr), "Failed to create device context state, hr %#x.\n", hr); if (FAILED(hr)) { ID3D11SamplerState_Release(sampler); ID3D11Device1_Release(device); return; } refcount = get_refcount(context_state); ok(refcount == 1, "Got refcount %u, expected 1.\n", refcount); /* Enable ID3D10Device behavior. */ previous_context_state = NULL; ID3D11DeviceContext1_SwapDeviceContextState(context, context_state, &previous_context_state); refcount = ID3DDeviceContextState_Release(context_state); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); ID3D11DeviceContext1_PSSetSamplers(context, 0, 1, &sampler); tmp_sampler = (ID3D11SamplerState *)0xdeadbeef; ID3D11DeviceContext1_PSGetSamplers(context, 0, 1, &tmp_sampler); ok(tmp_sampler == (ID3D11SamplerState *)0xdeadbeef, "Got unexpected sampler %p.\n", tmp_sampler); if (!enable_debug_layer) ID3D11DeviceContext1_PSSetSamplers(context, 0, 1, &tmp_sampler); check_interface(device, &IID_ID3D10Device, TRUE, FALSE); check_interface(device, &IID_ID3D10Device1, TRUE, FALSE); ID3D11DeviceContext1_SwapDeviceContextState(context, previous_context_state, &context_state); refcount = ID3DDeviceContextState_Release(context_state); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); refcount = ID3DDeviceContextState_Release(previous_context_state); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); /* ID3DDeviceContextState retains the previous state. */ tmp_sampler = NULL; ID3D11DeviceContext1_PSGetSamplers(context, 0, 1, &tmp_sampler); ok(tmp_sampler == sampler, "Got sampler %p, expected %p.\n", tmp_sampler, sampler); ID3D11SamplerState_Release(tmp_sampler); tmp_sampler = NULL; ID3D11DeviceContext1_PSSetSamplers(context, 0, 1, &tmp_sampler); tmp_sampler = (ID3D11SamplerState *)0xdeadbeef; ID3D11DeviceContext1_PSGetSamplers(context, 0, 1, &tmp_sampler); ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); ID3D11DeviceContext1_PSSetSamplers(context, 0, 1, &sampler); tmp_sampler = NULL; ID3D11DeviceContext1_PSGetSamplers(context, 0, 1, &tmp_sampler); ok(tmp_sampler == sampler, "Got sampler %p, expected %p.\n", tmp_sampler, sampler); ID3D11SamplerState_Release(tmp_sampler); check_interface(device, &IID_ID3D10Device, TRUE, FALSE); check_interface(device, &IID_ID3D10Device1, TRUE, FALSE); ID3D11SamplerState_Release(sampler); ID3D11DeviceContext1_Release(context); refcount = ID3D11Device1_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_blend(void) { ID3D11BlendState *src_blend, *dst_blend, *dst_blend_factor; struct d3d11_test_context test_context; ID3D11RenderTargetView *offscreen_rtv; D3D11_TEXTURE2D_DESC texture_desc; ID3D11InputLayout *input_layout; ID3D11DeviceContext *context; D3D11_BLEND_DESC blend_desc; unsigned int stride, offset; ID3D11Texture2D *offscreen; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *vb; DWORD color; HRESULT hr; static const DWORD vs_code[] = { #if 0 struct vs_out { float4 position : SV_POSITION; float4 color : COLOR; }; struct vs_out main(float4 position : POSITION, float4 color : COLOR) { struct vs_out o; o.position = position; o.color = color; return o; } #endif 0x43425844, 0x5c73b061, 0x5c71125f, 0x3f8b345f, 0xce04b9ab, 0x00000001, 0x00000140, 0x00000003, 0x0000002c, 0x0000007c, 0x000000d0, 0x4e475349, 0x00000048, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 struct vs_out { float4 position : SV_POSITION; float4 color : COLOR; }; float4 main(struct vs_out i) : SV_TARGET { return i.color; } #endif 0x43425844, 0xe2087fa6, 0xa35fbd95, 0x8e585b3f, 0x67890f54, 0x00000001, 0x000000f4, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const struct { struct vec3 position; DWORD diffuse; } quads[] = { /* quad1 */ {{-1.0f, -1.0f, 0.1f}, 0x4000ff00}, {{-1.0f, 0.0f, 0.1f}, 0x4000ff00}, {{ 1.0f, -1.0f, 0.1f}, 0x4000ff00}, {{ 1.0f, 0.0f, 0.1f}, 0x4000ff00}, /* quad2 */ {{-1.0f, 0.0f, 0.1f}, 0xc0ff0000}, {{-1.0f, 1.0f, 0.1f}, 0xc0ff0000}, {{ 1.0f, 0.0f, 0.1f}, 0xc0ff0000}, {{ 1.0f, 1.0f, 0.1f}, 0xc0ff0000}, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const float blend_factor[] = {0.3f, 0.4f, 0.8f, 0.9f}; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(quads), quads); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); memset(&blend_desc, 0, sizeof(blend_desc)); blend_desc.RenderTarget[0].BlendEnable = TRUE; blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &src_blend); ok(SUCCEEDED(hr), "Failed to create blend state, hr %#x.\n", hr); blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_DEST_ALPHA; blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_DEST_ALPHA; blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA; blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &dst_blend); ok(SUCCEEDED(hr), "Failed to create blend state, hr %#x.\n", hr); blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_BLEND_FACTOR; blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_BLEND_FACTOR; blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA; blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &dst_blend_factor); ok(SUCCEEDED(hr), "Failed to create blend state, hr %#x.\n", hr); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); stride = sizeof(*quads); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, &stride, &offset); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); ID3D11DeviceContext_OMSetBlendState(context, src_blend, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11DeviceContext_Draw(context, 4, 0); ID3D11DeviceContext_OMSetBlendState(context, dst_blend, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11DeviceContext_Draw(context, 4, 4); color = get_texture_color(test_context.backbuffer, 320, 360); ok(compare_color(color, 0x700040bf, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 320, 120); ok(compare_color(color, 0xa080007f, 1), "Got unexpected color 0x%08x.\n", color); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); ID3D11DeviceContext_OMSetBlendState(context, dst_blend_factor, blend_factor, D3D11_DEFAULT_SAMPLE_MASK); ID3D11DeviceContext_Draw(context, 4, 0); ID3D11DeviceContext_Draw(context, 4, 4); color = get_texture_color(test_context.backbuffer, 320, 360); ok(compare_color(color, 0x600066b3, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 320, 120); ok(compare_color(color, 0xa0cc00b3, 1), "Got unexpected color 0x%08x.\n", color); texture_desc.Width = 128; texture_desc.Height = 128; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_B8G8R8X8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; /* DXGI_FORMAT_B8G8R8X8_UNORM is not supported on all implementations. */ if (FAILED(ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &offscreen))) { skip("DXGI_FORMAT_B8G8R8X8_UNORM not supported.\n"); goto done; } hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)offscreen, NULL, &offscreen_rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &offscreen_rtv, NULL); set_viewport(context, 0.0f, 0.0f, 128.0f, 128.0f, 0.0f, 1.0f); ID3D11DeviceContext_ClearRenderTargetView(context, offscreen_rtv, red); ID3D11DeviceContext_OMSetBlendState(context, src_blend, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11DeviceContext_Draw(context, 4, 0); ID3D11DeviceContext_OMSetBlendState(context, dst_blend, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11DeviceContext_Draw(context, 4, 4); color = get_texture_color(offscreen, 64, 96) & 0x00ffffff; ok(compare_color(color, 0x00bf4000, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(offscreen, 64, 32) & 0x00ffffff; ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color); ID3D11RenderTargetView_Release(offscreen_rtv); ID3D11Texture2D_Release(offscreen); done: ID3D11BlendState_Release(dst_blend_factor); ID3D11BlendState_Release(dst_blend); ID3D11BlendState_Release(src_blend); ID3D11PixelShader_Release(ps); ID3D11VertexShader_Release(vs); ID3D11Buffer_Release(vb); ID3D11InputLayout_Release(input_layout); release_test_context(&test_context); } static void test_texture1d(void) { struct shader { const DWORD *code; size_t size; }; struct texture { UINT width; UINT miplevel_count; UINT array_size; DXGI_FORMAT format; D3D11_SUBRESOURCE_DATA data[3]; }; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; struct d3d11_test_context test_context; const struct texture *current_texture; D3D11_TEXTURE1D_DESC texture_desc; D3D11_SAMPLER_DESC sampler_desc; const struct shader *current_ps; D3D_FEATURE_LEVEL feature_level; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; ID3D11SamplerState *sampler; struct resource_readback rb; ID3D11Texture1D *texture; struct vec4 ps_constant; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, x; ID3D11Buffer *cb; DWORD color; HRESULT hr; static const DWORD ps_ld_code[] = { #if 0 Texture1D t; float miplevel; float4 main(float4 position : SV_POSITION) : SV_TARGET { float2 p; t.GetDimensions(miplevel, p.x, p.y); p.y = miplevel; p *= float2(position.x / 640.0f, 1.0f); return t.Load(int2(p)); } #endif 0x43425844, 0x7b0c6359, 0x598178f6, 0xef2ddbdb, 0x88fc794c, 0x00000001, 0x000001ac, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000010f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000110, 0x00000040, 0x00000044, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04001058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101012, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0600001c, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0700003d, 0x001000f2, 0x00000000, 0x0010000a, 0x00000000, 0x00107e46, 0x00000000, 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010100a, 0x00000000, 0x06000036, 0x001000e2, 0x00000000, 0x00208006, 0x00000000, 0x00000000, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3acccccd, 0x3f800000, 0x3f800000, 0x3f800000, 0x0500001b, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0700002d, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x0100003e, }; static const struct shader ps_ld = {ps_ld_code, sizeof(ps_ld_code)}; static const DWORD ps_ld_sint8_code[] = { #if 0 Texture1D t; float4 main(float4 position : SV_POSITION) : SV_TARGET { float2 p, s; int4 c; p = float2(position.x / 640.0f, 0.0f); t.GetDimensions(0, s.x, s.y); p *= s; c = t.Load(int2(p)); return (max(c / (float4)127, (float4)-1) + (float4)1) / 2.0f; } #endif 0x43425844, 0x65a13d1e, 0x8a0bfc92, 0xa2f2708a, 0x0bafafb6, 0x00000001, 0x00000234, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000010f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000198, 0x00000040, 0x00000066, 0x04001058, 0x00107000, 0x00000000, 0x00003333, 0x04002064, 0x00101012, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0700003d, 0x001000f2, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, 0x00000000, 0x07000038, 0x00100012, 0x00000001, 0x0010100a, 0x00000000, 0x00004001, 0x3acccccd, 0x08000036, 0x001000e2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07000038, 0x001000f2, 0x00000000, 0x00100fc6, 0x00000000, 0x00100e46, 0x00000001, 0x0500001b, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0700002d, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x0500002b, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3c010204, 0x3c010204, 0x3c010204, 0x3c010204, 0x0a000034, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0xbf800000, 0xbf800000, 0xbf800000, 0xbf800000, 0x0a000000, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x0a000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x0100003e, }; static const struct shader ps_ld_sint8 = {ps_ld_sint8_code, sizeof(ps_ld_sint8_code)}; static const DWORD ps_ld_uint8_code[] = { #if 0 Texture1D t; float4 main(float4 position : SV_POSITION) : SV_TARGET { float2 p, s; p = float2(position.x / 640.0f, 0.0f); t.GetDimensions(0, s.x, s.y); p *= s; return t.Load(int2(p)) / (float4)255; } #endif 0x43425844, 0x35186c1f, 0x55bad4fd, 0xb7c97a57, 0x99c060e7, 0x00000001, 0x000001bc, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000010f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000120, 0x00000040, 0x00000048, 0x04001058, 0x00107000, 0x00000000, 0x00004444, 0x04002064, 0x00101012, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0700003d, 0x001000f2, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, 0x00000000, 0x07000038, 0x00100012, 0x00000001, 0x0010100a, 0x00000000, 0x00004001, 0x3acccccd, 0x08000036, 0x001000e2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07000038, 0x001000f2, 0x00000000, 0x00100fc6, 0x00000000, 0x00100e46, 0x00000001, 0x0500001b, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0700002d, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x05000056, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0a000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3b808081, 0x3b808081, 0x3b808081, 0x3b808081, 0x0100003e, }; static const struct shader ps_ld_uint8 = {ps_ld_uint8_code, sizeof(ps_ld_uint8_code)}; static DWORD ps_ld_array_code[] = { #if 0 Texture1DArray t; float miplevel; float4 main(float4 position : SV_POSITION) : SV_TARGET { float3 p; t.GetDimensions(miplevel, p.x, p.y, p.z); p.y = 1; p.z = miplevel; p *= float3(position.x / 640.0f, 1.0f, 1.0f); return t.Load(int3(p)); } #endif 0x43425844, 0xbfccadc4, 0xc00ff13d, 0x2ba75365, 0xf747cbee, 0x00000001, 0x000001c0, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000010f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000124, 0x00000040, 0x00000049, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04003858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101012, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0600001c, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0700003d, 0x001000f2, 0x00000000, 0x0010000a, 0x00000000, 0x00107e46, 0x00000000, 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010100a, 0x00000000, 0x06000036, 0x001000c2, 0x00000000, 0x00208006, 0x00000000, 0x00000000, 0x0a000038, 0x00100072, 0x00000000, 0x00100386, 0x00000000, 0x00004002, 0x3acccccd, 0x3f800000, 0x3f800000, 0x00000000, 0x0500001b, 0x001000d2, 0x00000000, 0x00100906, 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0x00000001, 0x0700002d, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x0100003e, }; static const struct shader ps_ld_array = {ps_ld_array_code, sizeof(ps_ld_array_code)}; static const DWORD rgba_level_0[] = { 0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00, }; static const DWORD rgba_level_1[] = { 0xffffffff, 0xff0000ff, }; static const DWORD rgba_level_2[] = { 0xffff0000, }; static const DWORD srgb_data[] = { 0x00000000, 0xffffffff, 0xff000000, 0x7f7f7f7f, }; static const DWORD r32_uint[] = { 0, 1, 2, 3, }; static const DWORD r9g9b9e5_data[] = { 0x80000100, 0x80020000, 0x84000000, 0x84000100, }; static const DWORD array_data0[] = { 0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00, }; static const DWORD array_data1[] = { 0x00ffff00, 0xff000000, 0x00ff0000, 0x000000ff, }; static const DWORD array_data2[] = { 0x000000ff, 0xffff00ff, 0x0000ff00, 0xff000000, }; static const struct texture rgba_texture = { 4, 3, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { {rgba_level_0, 4 * sizeof(*rgba_level_0), 0}, {rgba_level_1, 2 * sizeof(*rgba_level_1), 0}, {rgba_level_2, sizeof(*rgba_level_2), 0}, } }; static const struct texture srgb_texture = {4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, {{srgb_data, 4 * sizeof(*srgb_data)}}}; static const struct texture sint8_texture = {4, 1, 1, DXGI_FORMAT_R8G8B8A8_SINT, {{rgba_level_0, 4 * sizeof(*rgba_level_0)}}}; static const struct texture uint8_texture = {4, 1, 1, DXGI_FORMAT_R8G8B8A8_UINT, {{rgba_level_0, 4 * sizeof(*rgba_level_0)}}}; static const struct texture r32u_typeless = {4, 1, 1, DXGI_FORMAT_R32_TYPELESS, {{r32_uint, 4 * sizeof(*r32_uint)}}}; static const struct texture r9g9b9e5_texture = {4, 1, 1, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, {{r9g9b9e5_data, 4 * sizeof(*r9g9b9e5_data)}}}; static const struct texture array_texture = {4, 1, 3, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, { {array_data0, 4 * sizeof(*array_data0)}, {array_data1, 4 * sizeof(*array_data1)}, {array_data2, 4 * sizeof(*array_data2)}, } }; static const DWORD level_1_colors[] = { 0xffffffff, 0xffffffff, 0xff0000ff, 0xff0000ff, }; static const DWORD level_2_colors[] = { 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, }; static const DWORD srgb_colors[] = { 0x00000001, 0xffffffff, 0xff000000, 0x7f363636, }; static const DWORD sint8_colors[] = { 0x7e80807e, 0x7e807e7e, 0x7e807e80, 0x7e7e7e80, }; static const DWORD r32u_colors[4] = { 0x01000000, 0x01000001, 0x01000002, 0x01000003, }; static const DWORD r9g9b9e5_colors[4] = { 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffff00ff, }; static const DWORD zero_colors[4] = {0}; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; static const struct texture_test { const struct shader *ps; const struct texture *texture; D3D11_FILTER filter; float lod_bias; float min_lod; float max_lod; float ps_constant; const DWORD *expected_colors; } texture_tests[] = { #define POINT D3D11_FILTER_MIN_MAG_MIP_POINT #define POINT_LINEAR D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR #define MIP_MAX D3D11_FLOAT32_MAX {&ps_ld, &rgba_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, rgba_level_0}, {&ps_ld, &rgba_texture, POINT, 0.0f, 0.0f, 0.0f, 1.0f, level_1_colors}, {&ps_ld, &rgba_texture, POINT, 0.0f, 0.0f, 0.0f, 2.0f, level_2_colors}, {&ps_ld, &rgba_texture, POINT, 0.0f, 0.0f, 0.0f, 3.0f, zero_colors}, {&ps_ld, &srgb_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, srgb_colors}, {&ps_ld, &r9g9b9e5_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, r9g9b9e5_colors}, {&ps_ld, NULL, POINT, 0.0f, 0.0f, 0.0f, 0.0f, zero_colors}, {&ps_ld, NULL, POINT, 0.0f, 0.0f, MIP_MAX, 0.0f, zero_colors}, {&ps_ld_sint8, &sint8_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, sint8_colors}, {&ps_ld_uint8, &uint8_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, rgba_level_0}, {&ps_ld_array, &array_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, array_data1}, }; #undef POINT #undef POINT_LINEAR #undef MIP_MAX static const struct srv_test { const struct shader *ps; const struct texture *texture; struct srv_desc srv_desc; float ps_constant; const DWORD *expected_colors; } srv_tests[] = { #define TEX_1D D3D11_SRV_DIMENSION_TEXTURE1D #define R32_UINT DXGI_FORMAT_R32_UINT {&ps_ld_uint8, &r32u_typeless, {R32_UINT, TEX_1D, 0, 1}, 0.0f, r32u_colors}, #undef TEX_1D #undef R32_UINT #undef FMT_UNKNOWN }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; feature_level = ID3D11Device_GetFeatureLevel(device); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(ps_constant), NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = D3D11_FLOAT32_MAX; ps = NULL; srv = NULL; sampler = NULL; texture = NULL; current_ps = NULL; current_texture = NULL; for (i = 0; i < ARRAY_SIZE(texture_tests); ++i) { const struct texture_test *test = &texture_tests[i]; if (current_ps != test->ps) { if (ps) ID3D11PixelShader_Release(ps); current_ps = test->ps; hr = ID3D11Device_CreatePixelShader(device, current_ps->code, current_ps->size, NULL, &ps); ok(SUCCEEDED(hr), "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); } if (current_texture != test->texture) { if (texture) ID3D11Texture1D_Release(texture); if (srv) ID3D11ShaderResourceView_Release(srv); current_texture = test->texture; if (current_texture) { texture_desc.Width = current_texture->width; texture_desc.MipLevels = current_texture->miplevel_count; texture_desc.ArraySize = current_texture->array_size; texture_desc.Format = current_texture->format; hr = ID3D11Device_CreateTexture1D(device, &texture_desc, current_texture->data, &texture); ok(SUCCEEDED(hr), "Test %u: Failed to create 1d texture, hr %#x.\n", i, hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(SUCCEEDED(hr), "Test %u: Failed to create shader resource view, hr %#x.\n", i, hr); } else { texture = NULL; srv = NULL; } ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); } if (!sampler || (sampler_desc.Filter != test->filter || sampler_desc.MipLODBias != test->lod_bias || sampler_desc.MinLOD != test->min_lod || sampler_desc.MaxLOD != test->max_lod)) { if (sampler) ID3D11SamplerState_Release(sampler); sampler_desc.Filter = test->filter; sampler_desc.MipLODBias = test->lod_bias; sampler_desc.MinLOD = test->min_lod; sampler_desc.MaxLOD = test->max_lod; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); ok(SUCCEEDED(hr), "Test %u: Failed to create sampler state, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); } ps_constant.x = test->ps_constant; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 80 + x * 160, 0, 0); ok(compare_color(color, test->expected_colors[x], 2), "Test %u: Got unexpected color 0x%08x at (%u).\n", i, color, x); } release_resource_readback(&rb); } if (srv) ID3D11ShaderResourceView_Release(srv); ID3D11SamplerState_Release(sampler); if (texture) ID3D11Texture1D_Release(texture); ID3D11PixelShader_Release(ps); if (is_warp_device(device) && feature_level < D3D_FEATURE_LEVEL_11_0) { win_skip("SRV tests are broken on WARP.\n"); ID3D11Buffer_Release(cb); release_test_context(&test_context); return; } sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.MipLODBias = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = D3D11_FLOAT32_MAX; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); ps = NULL; srv = NULL; texture = NULL; current_ps = NULL; current_texture = NULL; for (i = 0; i < ARRAY_SIZE(srv_tests); ++i) { const struct srv_test *test = &srv_tests[i]; if (current_ps != test->ps) { if (ps) ID3D11PixelShader_Release(ps); current_ps = test->ps; hr = ID3D11Device_CreatePixelShader(device, current_ps->code, current_ps->size, NULL, &ps); ok(SUCCEEDED(hr), "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); } if (current_texture != test->texture) { if (texture) ID3D11Texture1D_Release(texture); current_texture = test->texture; texture_desc.Width = current_texture->width; texture_desc.MipLevels = current_texture->miplevel_count; texture_desc.ArraySize = current_texture->array_size; texture_desc.Format = current_texture->format; hr = ID3D11Device_CreateTexture1D(device, &texture_desc, current_texture->data, &texture); ok(SUCCEEDED(hr), "Test %u: Failed to create 1d texture, hr %#x.\n", i, hr); } if (srv) ID3D11ShaderResourceView_Release(srv); get_srv_desc(&srv_desc, &test->srv_desc); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, &srv_desc, &srv); ok(SUCCEEDED(hr), "Test %u: Failed to create shader resource view, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); ps_constant.x = test->ps_constant; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 80 + x * 160, 0, 0); ok(compare_color(color, test->expected_colors[x], 1), "Test %u: Got unexpected color 0x%08x at (%u).\n", i, color, x); } release_resource_readback(&rb); } ID3D11PixelShader_Release(ps); ID3D11Texture1D_Release(texture); ID3D11ShaderResourceView_Release(srv); ID3D11SamplerState_Release(sampler); ID3D11Buffer_Release(cb); release_test_context(&test_context); } static void test_texture(void) { struct shader { const DWORD *code; size_t size; }; struct texture { UINT width; UINT height; UINT miplevel_count; UINT array_size; DXGI_FORMAT format; D3D11_SUBRESOURCE_DATA data[3]; }; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; struct d3d11_test_context test_context; const struct texture *current_texture; D3D11_TEXTURE2D_DESC texture_desc; D3D11_SAMPLER_DESC sampler_desc; const struct shader *current_ps; D3D_FEATURE_LEVEL feature_level; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; ID3D11SamplerState *sampler; struct resource_readback rb; ID3D11Texture2D *texture; struct vec4 ps_constant; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, x, y; ID3D11Buffer *cb; DWORD color; HRESULT hr; static const DWORD ps_ld_code[] = { #if 0 Texture2D t; float miplevel; float4 main(float4 position : SV_POSITION) : SV_TARGET { float3 p; t.GetDimensions(miplevel, p.x, p.y, p.z); p.z = miplevel; p *= float3(position.x / 640.0f, position.y / 480.0f, 1.0f); return t.Load(int3(p)); } #endif 0x43425844, 0xbdda6bdf, 0xc6ffcdf1, 0xa58596b3, 0x822383f0, 0x00000001, 0x000001ac, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000110, 0x00000040, 0x00000044, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0600001c, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0700003d, 0x001000f2, 0x00000000, 0x0010000a, 0x00000000, 0x00107e46, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00101046, 0x00000000, 0x06000036, 0x001000c2, 0x00000000, 0x00208006, 0x00000000, 0x00000000, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x3f800000, 0x3f800000, 0x0500001b, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0700002d, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x0100003e, }; static const struct shader ps_ld = {ps_ld_code, sizeof(ps_ld_code)}; static const DWORD ps_ld_sint8_code[] = { #if 0 Texture2D t; float4 main(float4 position : SV_POSITION) : SV_TARGET { float3 p, s; int4 c; p = float3(position.x / 640.0f, position.y / 480.0f, 0.0f); t.GetDimensions(0, s.x, s.y, s.z); p *= s; c = t.Load(int3(p)); return (max(c / (float4)127, (float4)-1) + (float4)1) / 2.0f; } #endif 0x43425844, 0xb3d0b0fc, 0x0e486f4a, 0xf67eec12, 0xfb9dd52f, 0x00000001, 0x00000240, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x000001a4, 0x00000040, 0x00000069, 0x04001858, 0x00107000, 0x00000000, 0x00003333, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0700003d, 0x001000f2, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, 0x00000000, 0x0a000038, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x08000036, 0x001000c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07000038, 0x001000f2, 0x00000000, 0x00100f46, 0x00000000, 0x00100e46, 0x00000001, 0x0500001b, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0700002d, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x0500002b, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3c010204, 0x3c010204, 0x3c010204, 0x3c010204, 0x0a000034, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0xbf800000, 0xbf800000, 0xbf800000, 0xbf800000, 0x0a000000, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x0a000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x0100003e, }; static const struct shader ps_ld_sint8 = {ps_ld_sint8_code, sizeof(ps_ld_sint8_code)}; static const DWORD ps_ld_uint8_code[] = { #if 0 Texture2D t; float4 main(float4 position : SV_POSITION) : SV_TARGET { float3 p, s; p = float3(position.x / 640.0f, position.y / 480.0f, 0.0f); t.GetDimensions(0, s.x, s.y, s.z); p *= s; return t.Load(int3(p)) / (float4)255; } #endif 0x43425844, 0xd09917eb, 0x4508a07e, 0xb0b7250a, 0x228c1f0e, 0x00000001, 0x000001c8, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x0000012c, 0x00000040, 0x0000004b, 0x04001858, 0x00107000, 0x00000000, 0x00004444, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0700003d, 0x001000f2, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, 0x00000000, 0x0a000038, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x08000036, 0x001000c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07000038, 0x001000f2, 0x00000000, 0x00100f46, 0x00000000, 0x00100e46, 0x00000001, 0x0500001b, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0700002d, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x05000056, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0a000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3b808081, 0x3b808081, 0x3b808081, 0x3b808081, 0x0100003e, }; static const struct shader ps_ld_uint8 = {ps_ld_uint8_code, sizeof(ps_ld_uint8_code)}; static const DWORD ps_sample_code[] = { #if 0 Texture2D t; SamplerState s; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; return t.Sample(s, p); } #endif 0x43425844, 0x1ce9b612, 0xc8176faa, 0xd37844af, 0xdb515605, 0x00000001, 0x00000134, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040, 0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, }; static const struct shader ps_sample = {ps_sample_code, sizeof(ps_sample_code)}; static const DWORD ps_sample_b_code[] = { #if 0 Texture2D t; SamplerState s; float bias; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; return t.SampleBias(s, p, bias); } #endif 0x43425844, 0xc39b0686, 0x8244a7fc, 0x14c0b97a, 0x2900b3b7, 0x00000001, 0x00000150, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000b4, 0x00000040, 0x0000002d, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x0c00004a, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; static const struct shader ps_sample_b = {ps_sample_b_code, sizeof(ps_sample_b_code)}; static const DWORD ps_sample_l_code[] = { #if 0 Texture2D t; SamplerState s; float level; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; return t.SampleLevel(s, p, level); } #endif 0x43425844, 0x61e05d85, 0x2a7300fb, 0x0a83706b, 0x889d1683, 0x00000001, 0x00000150, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000b4, 0x00000040, 0x0000002d, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x0c000048, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; static const struct shader ps_sample_l = {ps_sample_l_code, sizeof(ps_sample_l_code)}; static const DWORD ps_sample_2d_array_code[] = { #if 0 Texture2DArray t; SamplerState s; float layer; float4 main(float4 position : SV_POSITION) : SV_TARGET { float3 d; float3 p = float3(position.x / 640.0f, position.y / 480.0f, 1.0f); t.GetDimensions(d.x, d.y, d.z); d.z = layer; return t.Sample(s, p * d); } #endif 0x43425844, 0xa9457e44, 0xc0b3ef8e, 0x3d751ae8, 0x23fa4807, 0x00000001, 0x00000194, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x000000f8, 0x00000040, 0x0000003e, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, 0x04004058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0700003d, 0x001000f2, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, 0x00000000, 0x0a000038, 0x001000c2, 0x00000000, 0x00101406, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x3acccccd, 0x3b088889, 0x07000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00100ae6, 0x00000000, 0x06000036, 0x00100042, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100246, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, }; static const struct shader ps_sample_2d_array = {ps_sample_2d_array_code, sizeof(ps_sample_2d_array_code)}; static const DWORD red_data[] = { 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0x00000000, 0x00000000, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0x00000000, 0x00000000, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0x00000000, 0x00000000, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0x00000000, 0x00000000, }; static const DWORD green_data[] = { 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, }; static const DWORD blue_data[] = { 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0x00000000, }; static const DWORD rgba_level_0[] = { 0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00, 0xffff0000, 0xffff00ff, 0xff000000, 0xff7f7f7f, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, }; static const DWORD rgba_level_1[] = { 0xffffffff, 0xff0000ff, 0xff000000, 0xff00ff00, }; static const DWORD rgba_level_2[] = { 0xffff0000, }; static const DWORD srgb_data[] = { 0x00000000, 0xffffffff, 0xff000000, 0x7f7f7f7f, 0xff010203, 0xff102030, 0xff0a0b0c, 0xff8090a0, 0xffb1c4de, 0xfff0f1f2, 0xfffafdfe, 0xff5a560f, 0xffd5ff00, 0xffc8f99f, 0xffaa00aa, 0xffdd55bb, }; static const WORD r8g8_data[] = { 0x0000, 0xffff, 0x0000, 0x7fff, 0x0203, 0xff10, 0x0b0c, 0x8000, 0xc4de, 0xfff0, 0xfdfe, 0x5a6f, 0xff00, 0xffc8, 0x00aa, 0xdd5b, }; static const BYTE a8_data[] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, }; static const BYTE bc1_data[] = { 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, }; static const BYTE bc2_data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, }; static const BYTE bc3_data[] = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, }; static const BYTE bc4_data[] = { 0x10, 0x7f, 0x77, 0x39, 0x05, 0x00, 0x00, 0x00, 0x10, 0x7f, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x10, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x7f, 0xb6, 0x6d, 0xdb, 0xb6, 0x6d, 0xdb, }; static const BYTE bc5_data[] = { 0x10, 0x7f, 0x77, 0x39, 0x05, 0x00, 0x00, 0x00, 0x10, 0x7f, 0x77, 0x39, 0x05, 0x00, 0x00, 0x00, 0x10, 0x7f, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x10, 0x7f, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x10, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x7f, 0xb6, 0x6d, 0xdb, 0xb6, 0x6d, 0xdb, 0x10, 0x7f, 0xb6, 0x6d, 0xdb, 0xb6, 0x6d, 0xdb, }; static const BYTE bc6h_u_data[] = { 0xe3, 0x5e, 0x00, 0x00, 0x78, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x7b, 0x01, 0x00, 0xe0, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xee, 0x05, 0x00, 0x80, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xde, 0x7b, 0xef, 0x7d, 0xef, 0xbd, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const BYTE bc6h_s_data[] = { 0x63, 0x2f, 0x00, 0x00, 0xb8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0xbd, 0x00, 0x00, 0xe0, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xf6, 0x02, 0x00, 0x80, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xaf, 0xbd, 0xf6, 0xba, 0xe7, 0x9e, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const BYTE bc7_data[] = { 0x02, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const float r32_float[] = { 0.0f, 1.0f, 0.5f, 0.50f, 1.0f, 0.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.5f, 0.25f, 1.0f, 0.0f, 0.0f, 0.75f, }; static const DWORD r32_uint[] = { 0, 1, 2, 3, 100, 200, 255, 128, 40, 30, 20, 10, 250, 210, 155, 190, }; static const DWORD r9g9b9e5_data[] = { 0x80000100, 0x80020000, 0x84000000, 0x84000100, 0x78000100, 0x78020000, 0x7c000000, 0x78020100, 0x70000133, 0x70026600, 0x74cc0000, 0x74cc0133, 0x6800019a, 0x68033400, 0x6e680000, 0x6e6b359a, }; static const struct texture rgba_texture = { 4, 4, 3, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { {rgba_level_0, 4 * sizeof(*rgba_level_0), 0}, {rgba_level_1, 2 * sizeof(*rgba_level_1), 0}, {rgba_level_2, sizeof(*rgba_level_2), 0}, } }; static const struct texture srgb_texture = {4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, {{srgb_data, 4 * sizeof(*srgb_data)}}}; static const struct texture srgb_typeless = {4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_TYPELESS, {{srgb_data, 4 * sizeof(*srgb_data)}}}; static const struct texture a8_texture = {4, 4, 1, 1, DXGI_FORMAT_A8_UNORM, {{a8_data, 4 * sizeof(*a8_data)}}}; static const struct texture bc1_texture = {8, 8, 1, 1, DXGI_FORMAT_BC1_UNORM, {{bc1_data, 2 * 8}}}; static const struct texture bc2_texture = {8, 8, 1, 1, DXGI_FORMAT_BC2_UNORM, {{bc2_data, 2 * 16}}}; static const struct texture bc3_texture = {8, 8, 1, 1, DXGI_FORMAT_BC3_UNORM, {{bc3_data, 2 * 16}}}; static const struct texture bc4_texture = {8, 8, 1, 1, DXGI_FORMAT_BC4_UNORM, {{bc4_data, 2 * 8}}}; static const struct texture bc5_texture = {8, 8, 1, 1, DXGI_FORMAT_BC5_UNORM, {{bc5_data, 2 * 16}}}; static const struct texture bc6h_u_texture = {8, 8, 1, 1, DXGI_FORMAT_BC6H_UF16, {{bc6h_u_data, 2 * 16}}}; static const struct texture bc6h_s_texture = {8, 8, 1, 1, DXGI_FORMAT_BC6H_SF16, {{bc6h_s_data, 2 * 16}}}; static const struct texture bc7_texture = {8, 8, 1, 1, DXGI_FORMAT_BC7_UNORM, {{bc7_data, 2 * 16}}}; static const struct texture bc1_texture_srgb = {8, 8, 1, 1, DXGI_FORMAT_BC1_UNORM_SRGB, {{bc1_data, 2 * 8}}}; static const struct texture bc2_texture_srgb = {8, 8, 1, 1, DXGI_FORMAT_BC2_UNORM_SRGB, {{bc2_data, 2 * 16}}}; static const struct texture bc3_texture_srgb = {8, 8, 1, 1, DXGI_FORMAT_BC3_UNORM_SRGB, {{bc3_data, 2 * 16}}}; static const struct texture bc7_texture_srgb = {8, 8, 1, 1, DXGI_FORMAT_BC7_UNORM_SRGB, {{bc7_data, 2 * 16}}}; static const struct texture bc1_typeless = {8, 8, 1, 1, DXGI_FORMAT_BC1_TYPELESS, {{bc1_data, 2 * 8}}}; static const struct texture bc2_typeless = {8, 8, 1, 1, DXGI_FORMAT_BC2_TYPELESS, {{bc2_data, 2 * 16}}}; static const struct texture bc3_typeless = {8, 8, 1, 1, DXGI_FORMAT_BC3_TYPELESS, {{bc3_data, 2 * 16}}}; static const struct texture sint8_texture = {4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_SINT, {{rgba_level_0, 4 * sizeof(*rgba_level_0)}}}; static const struct texture uint8_texture = {4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UINT, {{rgba_level_0, 4 * sizeof(*rgba_level_0)}}}; static const struct texture array_2d_texture = { 4, 4, 1, 3, DXGI_FORMAT_R8G8B8A8_UNORM, { {red_data, 6 * sizeof(*red_data)}, {green_data, 4 * sizeof(*green_data)}, {blue_data, 5 * sizeof(*blue_data)}, } }; static const struct texture r32f_float = {4, 4, 1, 1, DXGI_FORMAT_R32_FLOAT, {{r32_float, 4 * sizeof(*r32_float)}}}; static const struct texture r32f_typeless = {4, 4, 1, 1, DXGI_FORMAT_R32_TYPELESS, {{r32_float, 4 * sizeof(*r32_float)}}}; static const struct texture r32u_typeless = {4, 4, 1, 1, DXGI_FORMAT_R32_TYPELESS, {{r32_uint, 4 * sizeof(*r32_uint)}}}; static const struct texture r8g8_snorm = {4, 4, 1, 1, DXGI_FORMAT_R8G8_SNORM, {{r8g8_data, 4 * sizeof(*r8g8_data)}}}; static const struct texture r9g9b9e5_texture = {4, 4, 1, 1, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, {{r9g9b9e5_data, 4 * sizeof(*r9g9b9e5_data)}}}; static const DWORD red_colors[] = { 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, }; static const DWORD blue_colors[] = { 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, }; static const DWORD level_1_colors[] = { 0xffffffff, 0xffffffff, 0xff0000ff, 0xff0000ff, 0xffffffff, 0xffffffff, 0xff0000ff, 0xff0000ff, 0xff000000, 0xff000000, 0xff00ff00, 0xff00ff00, 0xff000000, 0xff000000, 0xff00ff00, 0xff00ff00, }; static const DWORD lerp_1_2_colors[] = { 0xffff7f7f, 0xffff7f7f, 0xff7f007f, 0xff7f007f, 0xffff7f7f, 0xffff7f7f, 0xff7f007f, 0xff7f007f, 0xff7f0000, 0xff7f0000, 0xff7f7f00, 0xff7f7f00, 0xff7f0000, 0xff7f0000, 0xff7f7f00, 0xff7f7f00, }; static const DWORD level_2_colors[] = { 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, }; static const DWORD srgb_colors[] = { 0x00000001, 0xffffffff, 0xff000000, 0x7f363636, 0xff000000, 0xff010408, 0xff010101, 0xff37475a, 0xff708cba, 0xffdee0e2, 0xfff3fbfd, 0xff1a1801, 0xffa9ff00, 0xff93f159, 0xff670067, 0xffb8177f, }; static const DWORD a8_colors[] = { 0x00000000, 0x10000000, 0x20000000, 0x30000000, 0x40000000, 0x50000000, 0x60000000, 0x70000000, 0x80000000, 0x90000000, 0xa0000000, 0xb0000000, 0xc0000000, 0xd0000000, 0xe0000000, 0xf0000000, }; static const DWORD bc_colors[] = { 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xff00ff00, 0xffff0000, 0xffff0000, 0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000, 0xffffffff, 0xffffffff, }; static const DWORD bc4_colors[] = { 0xff000026, 0xff000010, 0xff00007f, 0xff00007f, 0xff000010, 0xff000010, 0xff00007f, 0xff00007f, 0xff0000ff, 0xff0000ff, 0xff000000, 0xff000000, 0xff0000ff, 0xff0000ff, 0xff000000, 0xff000000, }; static const DWORD bc5_colors[] = { 0xff002626, 0xff001010, 0xff007f7f, 0xff007f7f, 0xff001010, 0xff001010, 0xff007f7f, 0xff007f7f, 0xff00ffff, 0xff00ffff, 0xff000000, 0xff000000, 0xff00ffff, 0xff00ffff, 0xff000000, 0xff000000, }; static const DWORD bc7_colors[] = { 0xff0000fc, 0xff0000fc, 0xff00fc00, 0xff00fc00, 0xff0000fc, 0xff0000fc, 0xff00fc00, 0xff00fc00, 0xfffc0000, 0xfffc0000, 0xffffffff, 0xffffffff, 0xfffc0000, 0xfffc0000, 0xffffffff, 0xffffffff, }; static const DWORD sint8_colors[] = { 0x7e80807e, 0x7e807e7e, 0x7e807e80, 0x7e7e7e80, 0x7e7e8080, 0x7e7e7f7f, 0x7e808080, 0x7effffff, 0x7e7e7e7e, 0x7e7e7e7e, 0x7e7e7e7e, 0x7e808080, 0x7e7e7e7e, 0x7e7f7f7f, 0x7e7f7f7f, 0x7e7f7f7f, }; static const DWORD snorm_colors[] = { 0xff000000, 0xff000000, 0xff000000, 0xff00ff00, 0xff000406, 0xff000020, 0xff001618, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff00b5df, 0xff000000, 0xff000000, 0xff000000, 0xff0000b7, }; static const DWORD r32f_colors[] = { 0xff000000, 0xff0000ff, 0xff00007f, 0xff00007f, 0xff0000ff, 0xff000000, 0xff000000, 0xff0000bf, 0xff000000, 0xff0000ff, 0xff00007f, 0xff000040, 0xff0000ff, 0xff000000, 0xff000000, 0xff0000bf, }; static const DWORD r32u_colors[16] = { 0x01000000, 0x01000001, 0x01000002, 0x01000003, 0x01000064, 0x010000c8, 0x010000ff, 0x01000080, 0x01000028, 0x0100001e, 0x01000014, 0x0100000a, 0x010000fa, 0x010000d2, 0x0100009b, 0x010000be, }; static const DWORD r9g9b9e5_colors[16] = { 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffff00ff, 0xff00007f, 0xff007f00, 0xff7f0000, 0xff007f7f, 0xff00004c, 0xff004c00, 0xff4c0000, 0xff4c004c, 0xff000033, 0xff003300, 0xff330000, 0xff333333, }; static const DWORD zero_colors[4 * 4] = {0}; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; static const struct texture_test { const struct shader *ps; const struct texture *texture; D3D11_FILTER filter; float lod_bias; float min_lod; float max_lod; float ps_constant; const DWORD *expected_colors; } texture_tests[] = { #define POINT D3D11_FILTER_MIN_MAG_MIP_POINT #define POINT_LINEAR D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR #define MIP_MAX D3D11_FLOAT32_MAX {&ps_ld, &rgba_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, rgba_level_0}, {&ps_ld, &rgba_texture, POINT, 0.0f, 0.0f, 0.0f, 1.0f, level_1_colors}, {&ps_ld, &rgba_texture, POINT, 0.0f, 0.0f, 0.0f, 2.0f, level_2_colors}, {&ps_ld, &rgba_texture, POINT, 0.0f, 0.0f, 0.0f, 3.0f, zero_colors}, {&ps_ld, &srgb_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, srgb_colors}, {&ps_ld, &bc1_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_ld, &bc1_texture, POINT, 0.0f, 0.0f, 0.0f, 1.0f, zero_colors}, {&ps_ld, &bc2_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_ld, &bc2_texture, POINT, 0.0f, 0.0f, 0.0f, 1.0f, zero_colors}, {&ps_ld, &bc3_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_ld, &bc3_texture, POINT, 0.0f, 0.0f, 0.0f, 1.0f, zero_colors}, {&ps_ld, &bc1_texture_srgb, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_ld, &bc2_texture_srgb, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_ld, &bc3_texture_srgb, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_ld, &bc4_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc4_colors}, {&ps_ld, &bc5_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc5_colors}, {&ps_ld, &bc6h_u_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_ld, &bc6h_s_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_ld, &bc7_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc7_colors}, {&ps_ld, &bc7_texture_srgb, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc7_colors}, {&ps_ld, &r9g9b9e5_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, r9g9b9e5_colors}, {&ps_ld, NULL, POINT, 0.0f, 0.0f, 0.0f, 0.0f, zero_colors}, {&ps_ld, NULL, POINT, 0.0f, 0.0f, MIP_MAX, 0.0f, zero_colors}, {&ps_ld_sint8, &sint8_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, sint8_colors}, {&ps_ld_uint8, &uint8_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, rgba_level_0}, {&ps_sample, &bc1_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_sample, &bc2_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_sample, &bc3_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_sample, &bc4_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc4_colors}, {&ps_sample, &bc5_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc5_colors}, {&ps_sample, &bc6h_u_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_sample, &bc6h_s_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc_colors}, {&ps_sample, &bc7_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc7_colors}, {&ps_sample, &bc7_texture_srgb, POINT, 0.0f, 0.0f, 0.0f, 0.0f, bc7_colors}, {&ps_sample, &rgba_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, rgba_level_0}, {&ps_sample, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 0.0f, rgba_level_0}, {&ps_sample, &rgba_texture, POINT, 2.0f, 0.0f, MIP_MAX, 0.0f, rgba_level_0}, {&ps_sample, &rgba_texture, POINT, 8.0f, 0.0f, MIP_MAX, 0.0f, level_1_colors}, {&ps_sample, &srgb_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, srgb_colors}, {&ps_sample, &a8_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, a8_colors}, {&ps_sample, &r9g9b9e5_texture, POINT, 0.0f, 0.0f, 0.0f, 0.0f, r9g9b9e5_colors}, {&ps_sample, NULL, POINT, 0.0f, 0.0f, 0.0f, 0.0f, zero_colors}, {&ps_sample, NULL, POINT, 0.0f, 0.0f, MIP_MAX, 0.0f, zero_colors}, {&ps_sample_b, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 0.0f, rgba_level_0}, {&ps_sample_b, &rgba_texture, POINT, 8.0f, 0.0f, MIP_MAX, 0.0f, level_1_colors}, {&ps_sample_b, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 8.0f, level_1_colors}, {&ps_sample_b, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 8.4f, level_1_colors}, {&ps_sample_b, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 8.5f, level_2_colors}, {&ps_sample_b, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 9.0f, level_2_colors}, {&ps_sample_b, &rgba_texture, POINT, 0.0f, 0.0f, 2.0f, 1.0f, rgba_level_0}, {&ps_sample_b, &rgba_texture, POINT, 0.0f, 0.0f, 2.0f, 9.0f, level_2_colors}, {&ps_sample_b, &rgba_texture, POINT, 0.0f, 0.0f, 1.0f, 9.0f, level_1_colors}, {&ps_sample_b, &rgba_texture, POINT, 0.0f, 0.0f, 0.0f, 9.0f, rgba_level_0}, {&ps_sample_b, NULL, POINT, 0.0f, 0.0f, 0.0f, 0.0f, zero_colors}, {&ps_sample_b, NULL, POINT, 0.0f, 0.0f, 0.0f, 1.0f, zero_colors}, {&ps_sample_b, NULL, POINT, 0.0f, 0.0f, MIP_MAX, 0.0f, zero_colors}, {&ps_sample_b, NULL, POINT, 0.0f, 0.0f, MIP_MAX, 1.0f, zero_colors}, {&ps_sample_l, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, -1.0f, rgba_level_0}, {&ps_sample_l, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 0.0f, rgba_level_0}, {&ps_sample_l, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 0.4f, rgba_level_0}, {&ps_sample_l, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 0.5f, level_1_colors}, {&ps_sample_l, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 1.0f, level_1_colors}, {&ps_sample_l, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 1.4f, level_1_colors}, {&ps_sample_l, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 1.5f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 2.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 3.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT, 0.0f, 0.0f, MIP_MAX, 4.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 0.0f, 0.0f, MIP_MAX, 1.5f, lerp_1_2_colors}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 2.0f, 0.0f, MIP_MAX, -2.0f, rgba_level_0}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 2.0f, 0.0f, MIP_MAX, -1.0f, level_1_colors}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 2.0f, 0.0f, MIP_MAX, 0.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 2.0f, 0.0f, MIP_MAX, 1.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 2.0f, 0.0f, MIP_MAX, 1.5f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 2.0f, 2.0f, 2.0f, -9.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 2.0f, 2.0f, 2.0f, -1.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 2.0f, 2.0f, 2.0f, 0.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 2.0f, 2.0f, 2.0f, 1.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT_LINEAR, 2.0f, 2.0f, 2.0f, 9.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT, 2.0f, 2.0f, 2.0f, -9.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT, 2.0f, 2.0f, 2.0f, -1.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT, 2.0f, 2.0f, 2.0f, 0.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT, 2.0f, 2.0f, 2.0f, 1.0f, level_2_colors}, {&ps_sample_l, &rgba_texture, POINT, 2.0f, 2.0f, 2.0f, 9.0f, level_2_colors}, {&ps_sample_l, NULL, POINT, 2.0f, 2.0f, 0.0f, 0.0f, zero_colors}, {&ps_sample_l, NULL, POINT, 2.0f, 2.0f, 0.0f, 1.0f, zero_colors}, {&ps_sample_l, NULL, POINT, 2.0f, 2.0f, MIP_MAX, 0.0f, zero_colors}, {&ps_sample_l, NULL, POINT, 2.0f, 2.0f, MIP_MAX, 1.0f, zero_colors}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, -9.0f, red_colors}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, -1.0f, red_colors}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, 0.0f, red_colors}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, 0.4f, red_colors}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, 0.5f, red_colors}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, 1.0f, green_data}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, 1.4f, green_data}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, 2.0f, blue_colors}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, 2.1f, blue_colors}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, 3.0f, blue_colors}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, 3.1f, blue_colors}, {&ps_sample_2d_array, &array_2d_texture, POINT, 0.0f, 0.0f, MIP_MAX, 9.0f, blue_colors}, {&ps_sample_2d_array, NULL, POINT, 0.0f, 0.0f, 0.0f, 0.0f, zero_colors}, {&ps_sample_2d_array, NULL, POINT, 0.0f, 0.0f, 0.0f, 1.0f, zero_colors}, {&ps_sample_2d_array, NULL, POINT, 0.0f, 0.0f, 0.0f, 2.0f, zero_colors}, {&ps_sample_2d_array, NULL, POINT, 0.0f, 0.0f, MIP_MAX, 0.0f, zero_colors}, {&ps_sample_2d_array, NULL, POINT, 0.0f, 0.0f, MIP_MAX, 1.0f, zero_colors}, {&ps_sample_2d_array, NULL, POINT, 0.0f, 0.0f, MIP_MAX, 2.0f, zero_colors}, #undef POINT #undef POINT_LINEAR #undef MIP_MAX }; static const struct srv_test { const struct shader *ps; const struct texture *texture; struct srv_desc srv_desc; float ps_constant; const DWORD *expected_colors; } srv_tests[] = { #define TEX_2D D3D11_SRV_DIMENSION_TEXTURE2D #define TEX_2D_ARRAY D3D11_SRV_DIMENSION_TEXTURE2DARRAY #define BC1_UNORM DXGI_FORMAT_BC1_UNORM #define BC1_UNORM_SRGB DXGI_FORMAT_BC1_UNORM_SRGB #define BC2_UNORM DXGI_FORMAT_BC2_UNORM #define BC2_UNORM_SRGB DXGI_FORMAT_BC2_UNORM_SRGB #define BC3_UNORM DXGI_FORMAT_BC3_UNORM #define BC3_UNORM_SRGB DXGI_FORMAT_BC3_UNORM_SRGB #define R8G8B8A8_UNORM_SRGB DXGI_FORMAT_R8G8B8A8_UNORM_SRGB #define R8G8B8A8_UNORM DXGI_FORMAT_R8G8B8A8_UNORM #define R8G8_SNORM DXGI_FORMAT_R8G8_SNORM #define R32_FLOAT DXGI_FORMAT_R32_FLOAT #define R32_UINT DXGI_FORMAT_R32_UINT #define FMT_UNKNOWN DXGI_FORMAT_UNKNOWN {&ps_sample, &bc1_typeless, {BC1_UNORM, TEX_2D, 0, 1}, 0.0f, bc_colors}, {&ps_sample, &bc1_typeless, {BC1_UNORM_SRGB, TEX_2D, 0, 1}, 0.0f, bc_colors}, {&ps_sample, &bc2_typeless, {BC2_UNORM, TEX_2D, 0, 1}, 0.0f, bc_colors}, {&ps_sample, &bc2_typeless, {BC2_UNORM_SRGB, TEX_2D, 0, 1}, 0.0f, bc_colors}, {&ps_sample, &bc3_typeless, {BC3_UNORM, TEX_2D, 0, 1}, 0.0f, bc_colors}, {&ps_sample, &bc3_typeless, {BC3_UNORM_SRGB, TEX_2D, 0, 1}, 0.0f, bc_colors}, {&ps_sample, &srgb_typeless, {R8G8B8A8_UNORM_SRGB, TEX_2D, 0, 1}, 0.0f, srgb_colors}, {&ps_sample, &srgb_typeless, {R8G8B8A8_UNORM, TEX_2D, 0, 1}, 0.0f, srgb_data}, {&ps_sample, &r32f_typeless, {R32_FLOAT, TEX_2D, 0, 1}, 0.0f, r32f_colors}, {&ps_sample, &r32f_float, {R32_FLOAT, TEX_2D, 0, 1}, 0.0f, r32f_colors}, {&ps_sample, &r8g8_snorm, {R8G8_SNORM, TEX_2D, 0, 1}, 0.0f, snorm_colors}, {&ps_sample, &array_2d_texture, {FMT_UNKNOWN, TEX_2D, 0, 1}, 0.0f, red_colors}, {&ps_sample_2d_array, &array_2d_texture, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 1, 0, 1}, 0.0f, red_colors}, {&ps_sample_2d_array, &array_2d_texture, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 1, 1, 1}, 0.0f, green_data}, {&ps_sample_2d_array, &array_2d_texture, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 1, 2, 1}, 0.0f, blue_colors}, {&ps_ld_uint8, &r32u_typeless, {R32_UINT, TEX_2D, 0, 1}, 0.0f, r32u_colors}, #undef TEX_2D #undef TEX_2D_ARRAY #undef BC1_UNORM #undef BC1_UNORM_SRGB #undef BC2_UNORM #undef BC2_UNORM_SRGB #undef BC3_UNORM #undef BC3_UNORM_SRGB #undef R8G8B8A8_UNORM_SRGB #undef R8G8B8A8_UNORM #undef R8G8_SNORM #undef R32_FLOAT #undef R32_UINT #undef FMT_UNKNOWN }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; feature_level = ID3D11Device_GetFeatureLevel(device); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(ps_constant), NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = D3D11_FLOAT32_MAX; ps = NULL; srv = NULL; sampler = NULL; texture = NULL; current_ps = NULL; current_texture = NULL; for (i = 0; i < ARRAY_SIZE(texture_tests); ++i) { const struct texture_test *test = &texture_tests[i]; if (test->texture && (test->texture->format == DXGI_FORMAT_BC7_UNORM || test->texture->format == DXGI_FORMAT_BC7_UNORM_SRGB) && feature_level < D3D_FEATURE_LEVEL_11_0) { skip("Feature level >= 11.0 is required for BC7 tests.\n"); continue; } if (test->texture && (test->texture->format == DXGI_FORMAT_BC6H_UF16 || test->texture->format == DXGI_FORMAT_BC6H_SF16) && feature_level < D3D_FEATURE_LEVEL_11_0) { skip("Feature level >= 11.0 is required for BC6H tests.\n"); continue; } if (current_ps != test->ps) { if (ps) ID3D11PixelShader_Release(ps); current_ps = test->ps; hr = ID3D11Device_CreatePixelShader(device, current_ps->code, current_ps->size, NULL, &ps); ok(SUCCEEDED(hr), "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); } if (current_texture != test->texture) { if (texture) ID3D11Texture2D_Release(texture); if (srv) ID3D11ShaderResourceView_Release(srv); current_texture = test->texture; if (current_texture) { texture_desc.Width = current_texture->width; texture_desc.Height = current_texture->height; texture_desc.MipLevels = current_texture->miplevel_count; texture_desc.ArraySize = current_texture->array_size; texture_desc.Format = current_texture->format; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, current_texture->data, &texture); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(SUCCEEDED(hr), "Test %u: Failed to create shader resource view, hr %#x.\n", i, hr); } else { texture = NULL; srv = NULL; } ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); } if (!sampler || (sampler_desc.Filter != test->filter || sampler_desc.MipLODBias != test->lod_bias || sampler_desc.MinLOD != test->min_lod || sampler_desc.MaxLOD != test->max_lod)) { if (sampler) ID3D11SamplerState_Release(sampler); sampler_desc.Filter = test->filter; sampler_desc.MipLODBias = test->lod_bias; sampler_desc.MinLOD = test->min_lod; sampler_desc.MaxLOD = test->max_lod; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); ok(SUCCEEDED(hr), "Test %u: Failed to create sampler state, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); } ps_constant.x = test->ps_constant; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 80 + x * 160, 60 + y * 120, 0); ok(compare_color(color, test->expected_colors[y * 4 + x], 2), "Test %u: Got unexpected color 0x%08x at (%u, %u).\n", i, color, x, y); } } release_resource_readback(&rb); } if (srv) ID3D11ShaderResourceView_Release(srv); ID3D11SamplerState_Release(sampler); if (texture) ID3D11Texture2D_Release(texture); ID3D11PixelShader_Release(ps); if (is_warp_device(device) && feature_level < D3D_FEATURE_LEVEL_11_0) { win_skip("SRV tests are broken on WARP.\n"); ID3D11Buffer_Release(cb); release_test_context(&test_context); return; } sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.MipLODBias = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = D3D11_FLOAT32_MAX; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); ps = NULL; srv = NULL; texture = NULL; current_ps = NULL; current_texture = NULL; for (i = 0; i < ARRAY_SIZE(srv_tests); ++i) { const struct srv_test *test = &srv_tests[i]; if (current_ps != test->ps) { if (ps) ID3D11PixelShader_Release(ps); current_ps = test->ps; hr = ID3D11Device_CreatePixelShader(device, current_ps->code, current_ps->size, NULL, &ps); ok(SUCCEEDED(hr), "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); } if (current_texture != test->texture) { if (texture) ID3D11Texture2D_Release(texture); current_texture = test->texture; texture_desc.Width = current_texture->width; texture_desc.Height = current_texture->height; texture_desc.MipLevels = current_texture->miplevel_count; texture_desc.ArraySize = current_texture->array_size; texture_desc.Format = current_texture->format; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, current_texture->data, &texture); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); } if (srv) ID3D11ShaderResourceView_Release(srv); get_srv_desc(&srv_desc, &test->srv_desc); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, &srv_desc, &srv); ok(SUCCEEDED(hr), "Test %u: Failed to create shader resource view, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); ps_constant.x = test->ps_constant; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 80 + x * 160, 60 + y * 120, 0); ok(compare_color(color, test->expected_colors[y * 4 + x], 1), "Test %u: Got unexpected color 0x%08x at (%u, %u).\n", i, color, x, y); } } release_resource_readback(&rb); } ID3D11PixelShader_Release(ps); ID3D11Texture2D_Release(texture); ID3D11ShaderResourceView_Release(srv); ID3D11SamplerState_Release(sampler); ID3D11Buffer_Release(cb); release_test_context(&test_context); } static void test_cube_maps(void) { struct shader { const DWORD *code; size_t size; }; unsigned int i, j, sub_resource_idx, sub_resource_count; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; const struct shader *current_ps; D3D_FEATURE_LEVEL feature_level; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; ID3D11Texture2D *rtv_texture; ID3D11RenderTargetView *rtv; struct vec4 expected_result; ID3D11Resource *texture; ID3D11PixelShader *ps; ID3D11Device *device; float data[64 * 64]; ID3D11Buffer *cb; HRESULT hr; RECT rect; struct { unsigned int face; unsigned int level; unsigned int cube; unsigned int padding; } constant; static const DWORD ps_cube_code[] = { #if 0 TextureCube t; SamplerState s; uint face; uint level; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; float3 coord; switch (face) { case 0: coord = float3(1.0f, p.x, p.y); break; case 1: coord = float3(-1.0f, p.x, p.y); break; case 2: coord = float3(p.x, 1.0f, p.y); break; case 3: coord = float3(p.x, -1.0f, p.y); break; case 4: coord = float3(p.x, p.y, 1.0f); break; case 5: default: coord = float3(p.x, p.y, -1.0f); break; } return t.SampleLevel(s, coord, level); } #endif 0x43425844, 0x039aee18, 0xfd630453, 0xb884cf0f, 0x10100744, 0x00000001, 0x00000310, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040, 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, 0x04003058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0400004c, 0x0020800a, 0x00000000, 0x00000000, 0x03000006, 0x00004001, 0x00000000, 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0x3f800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x00000000, 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, 0x00004001, 0x00000001, 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0xbf800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x00000000, 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, 0x00004001, 0x00000002, 0x0a000038, 0x00100052, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0x3f800000, 0x01000002, 0x03000006, 0x00004001, 0x00000003, 0x0a000038, 0x00100052, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0xbf800000, 0x01000002, 0x03000006, 0x00004001, 0x00000004, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x01000002, 0x0100000a, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0xbf800000, 0x01000002, 0x01000017, 0x06000056, 0x00100082, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0b000048, 0x001020f2, 0x00000000, 0x00100246, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0010003a, 0x00000000, 0x0100003e, }; static const struct shader ps_cube = {ps_cube_code, sizeof(ps_cube_code)}; static const DWORD ps_cube_array_code[] = { #if 0 TextureCubeArray t; SamplerState s; uint face; uint level; uint cube; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; float3 coord; switch (face) { case 0: coord = float3(1.0f, p.x, p.y); break; case 1: coord = float3(-1.0f, p.x, p.y); break; case 2: coord = float3(p.x, 1.0f, p.y); break; case 3: coord = float3(p.x, -1.0f, p.y); break; case 4: coord = float3(p.x, p.y, 1.0f); break; case 5: default: coord = float3(p.x, p.y, -1.0f); break; } return t.SampleLevel(s, float4(coord, cube), level); } #endif 0x43425844, 0xb8d5b94a, 0xdb4be034, 0x183aed19, 0xad4af415, 0x00000001, 0x00000328, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000028c, 0x00000041, 0x000000a3, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, 0x04005058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0400004c, 0x0020800a, 0x00000000, 0x00000000, 0x03000006, 0x00004001, 0x00000000, 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0x3f800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x00000000, 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, 0x00004001, 0x00000001, 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0xbf800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x00000000, 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, 0x00004001, 0x00000002, 0x0a000038, 0x00100052, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0x3f800000, 0x01000002, 0x03000006, 0x00004001, 0x00000003, 0x0a000038, 0x00100052, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0xbf800000, 0x01000002, 0x03000006, 0x00004001, 0x00000004, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x01000002, 0x0100000a, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0xbf800000, 0x01000002, 0x01000017, 0x06000056, 0x00100032, 0x00000001, 0x00208a66, 0x00000000, 0x00000000, 0x05000036, 0x00100082, 0x00000000, 0x0010000a, 0x00000001, 0x0b000048, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0010001a, 0x00000001, 0x0100003e, }; static const struct shader ps_cube_array = {ps_cube_array_code, sizeof(ps_cube_array_code)}; static const struct ps_test { const struct shader *ps; unsigned int miplevel_count; unsigned int array_size; } ps_tests[] = { {&ps_cube, 1, 6}, {&ps_cube, 2, 6}, {&ps_cube, 3, 6}, {&ps_cube, 0, 6}, {&ps_cube_array, 1, 12}, {&ps_cube_array, 2, 12}, {&ps_cube_array, 3, 12}, {&ps_cube_array, 0, 12}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; feature_level = ID3D11Device_GetFeatureLevel(device); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rtv_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rtv_texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); memset(&constant, 0, sizeof(constant)); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constant), &constant); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ps = NULL; current_ps = NULL; for (i = 0; i < ARRAY_SIZE(ps_tests); ++i) { const struct ps_test *test = &ps_tests[i]; if (test->array_size / 6 > 1 && feature_level < D3D_FEATURE_LEVEL_10_1) { skip("Test %u: Cube map array textures require feature level 10_1.\n", i); continue; } if (current_ps != test->ps) { if (ps) ID3D11PixelShader_Release(ps); current_ps = test->ps; hr = ID3D11Device_CreatePixelShader(device, current_ps->code, current_ps->size, NULL, &ps); ok(SUCCEEDED(hr), "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); } if (!test->miplevel_count) { srv = NULL; ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); memset(&expected_result, 0, sizeof(expected_result)); memset(&constant, 0, sizeof(constant)); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); check_texture_vec4(rtv_texture, &expected_result, 0); constant.level = 1; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); check_texture_vec4(rtv_texture, &expected_result, 0); continue; } texture_desc.Width = 64; texture_desc.Height = 64; texture_desc.MipLevels = test->miplevel_count; texture_desc.ArraySize = test->array_size; texture_desc.Format = DXGI_FORMAT_R32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&texture); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); hr = ID3D11Device_CreateShaderResourceView(device, texture, NULL, &srv); ok(SUCCEEDED(hr), "Test %u: Failed to create shader resource view, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); sub_resource_count = texture_desc.MipLevels * texture_desc.ArraySize; for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) { for (j = 0; j < ARRAY_SIZE(data); ++j) data[j] = sub_resource_idx; ID3D11DeviceContext_UpdateSubresource(context, texture, sub_resource_idx, NULL, data, texture_desc.Width * sizeof(*data), 0); } expected_result.y = expected_result.z = 0.0f; expected_result.w = 1.0f; for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) { constant.face = (sub_resource_idx / texture_desc.MipLevels) % 6; constant.level = sub_resource_idx % texture_desc.MipLevels; constant.cube = (sub_resource_idx / texture_desc.MipLevels) / 6; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); expected_result.x = sub_resource_idx; /* Avoid testing values affected by seamless cube map filtering. */ SetRect(&rect, 100, 100, 540, 380); check_texture_sub_resource_vec4(rtv_texture, 0, &rect, &expected_result, 0); } ID3D11Resource_Release(texture); ID3D11ShaderResourceView_Release(srv); } ID3D11PixelShader_Release(ps); ID3D11Buffer_Release(cb); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(rtv_texture); release_test_context(&test_context); } static void test_depth_stencil_sampling(void) { ID3D11PixelShader *ps_cmp, *ps_depth, *ps_stencil, *ps_depth_stencil; ID3D11ShaderResourceView *depth_srv, *stencil_srv; ID3D11SamplerState *cmp_sampler, *sampler; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc; struct d3d11_test_context test_context; ID3D11Texture2D *texture, *rt_texture; D3D11_TEXTURE2D_DESC texture_desc; D3D11_SAMPLER_DESC sampler_desc; ID3D11DeviceContext *context; ID3D11DepthStencilView *dsv; ID3D11RenderTargetView *rtv; struct vec4 ps_constant; ID3D11Device *device; ID3D11Buffer *cb; unsigned int i; HRESULT hr; static const float black[] = {0.0f, 0.0f, 0.0f, 0.0f}; static const DWORD ps_compare_code[] = { #if 0 Texture2D t; SamplerComparisonState s; float ref; float4 main(float4 position : SV_Position) : SV_Target { return t.SampleCmp(s, float2(position.x / 640.0f, position.y / 480.0f), ref); } #endif 0x43425844, 0xc2e0d84e, 0x0522c395, 0x9ff41580, 0xd3ca29cc, 0x00000001, 0x00000164, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c8, 0x00000040, 0x00000032, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300085a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x0c000046, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00107006, 0x00000000, 0x00106000, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x0100003e, }; static const DWORD ps_sample_code[] = { #if 0 Texture2D t; SamplerState s; float4 main(float4 position : SV_Position) : SV_Target { return t.Sample(s, float2(position.x / 640.0f, position.y / 480.0f)); } #endif 0x43425844, 0x7472c092, 0x5548f00e, 0xf4e007f1, 0x5970429c, 0x00000001, 0x00000134, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040, 0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, }; static const DWORD ps_stencil_code[] = { #if 0 Texture2D t; float4 main(float4 position : SV_Position) : SV_Target { float2 s; t.GetDimensions(s.x, s.y); return t.Load(int3(float3(s.x * position.x / 640.0f, s.y * position.y / 480.0f, 0))).y; } #endif 0x43425844, 0x929fced8, 0x2cd93320, 0x0591ece3, 0xee50d04a, 0x00000001, 0x000001a0, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000104, 0x00000040, 0x00000041, 0x04001858, 0x00107000, 0x00000000, 0x00004444, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0700003d, 0x001000f2, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00101046, 0x00000000, 0x0a000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x0500001b, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x08000036, 0x001000c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0700002d, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x05000056, 0x001020f2, 0x00000000, 0x00100556, 0x00000000, 0x0100003e, }; static const DWORD ps_depth_stencil_code[] = { #if 0 SamplerState samp; Texture2D depth_tex; Texture2D stencil_tex; float main(float4 position: SV_Position) : SV_Target { float2 s, p; float depth, stencil; depth_tex.GetDimensions(s.x, s.y); p = float2(s.x * position.x / 640.0f, s.y * position.y / 480.0f); depth = depth_tex.Sample(samp, p).r; stencil = stencil_tex.Load(int3(float3(p.x, p.y, 0))).y; return depth + stencil; } #endif 0x43425844, 0x348f8377, 0x977d1ee0, 0x8cca4f35, 0xff5c5afc, 0x00000001, 0x000001fc, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000e01, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040, 0x00000058, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00004444, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000000, 0x02000068, 0x00000002, 0x0700003d, 0x001000f2, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00101046, 0x00000000, 0x0a000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x0500001b, 0x00100032, 0x00000001, 0x00100046, 0x00000000, 0x09000045, 0x001000f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000036, 0x001000c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0700002d, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00107e46, 0x00000001, 0x05000056, 0x00100022, 0x00000000, 0x0010001a, 0x00000001, 0x07000000, 0x00102012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0100003e, }; static const struct test { DXGI_FORMAT typeless_format; DXGI_FORMAT dsv_format; DXGI_FORMAT depth_view_format; DXGI_FORMAT stencil_view_format; } tests[] = { {DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_X32_TYPELESS_G8X24_UINT}, {DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_FLOAT}, {DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_X24_TYPELESS_G8_UINT}, {DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_R16_UNORM}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; if (is_amd_device(device)) { /* Reads from depth/stencil shader resource views return stale values on some AMD drivers. */ win_skip("Some AMD drivers have a bug affecting the test.\n"); release_test_context(&test_context); return; } sampler_desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_GREATER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = 0.0f; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &cmp_sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); texture_desc.Width = 640; texture_desc.Height = 480; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rt_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rt_texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); memset(&ps_constant, 0, sizeof(ps_constant)); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(ps_constant), &ps_constant); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); hr = ID3D11Device_CreatePixelShader(device, ps_compare_code, sizeof(ps_compare_code), NULL, &ps_cmp); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_sample_code, sizeof(ps_sample_code), NULL, &ps_depth); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_stencil_code, sizeof(ps_stencil_code), NULL, &ps_stencil); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_depth_stencil_code, sizeof(ps_depth_stencil_code), NULL, &ps_depth_stencil); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(tests); ++i) { texture_desc.Format = tests[i].typeless_format; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture for format %#x, hr %#x.\n", texture_desc.Format, hr); dsv_desc.Format = tests[i].dsv_format; dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; dsv_desc.Flags = 0; U(dsv_desc).Texture2D.MipSlice = 0; hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, &dsv_desc, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view for format %#x, hr %#x.\n", dsv_desc.Format, hr); srv_desc.Format = tests[i].depth_view_format; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; U(srv_desc).Texture2D.MostDetailedMip = 0; U(srv_desc).Texture2D.MipLevels = 1; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, &srv_desc, &depth_srv); ok(SUCCEEDED(hr), "Failed to create depth shader resource view for format %#x, hr %#x.\n", srv_desc.Format, hr); ID3D11DeviceContext_PSSetShader(context, ps_cmp, NULL, 0); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &depth_srv); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &cmp_sampler); ps_constant.x = 0.5f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 0.0f, 2); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.0f, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 1.0f, 2); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.5f, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 0.0f, 2); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.6f, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 0.0f, 2); ps_constant.x = 0.7f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 1.0f, 2); ID3D11DeviceContext_PSSetShader(context, ps_depth, NULL, 0); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 1.0f, 2); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.2f, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 0.2f, 2); if (!tests[i].stencil_view_format) { ID3D11DepthStencilView_Release(dsv); ID3D11ShaderResourceView_Release(depth_srv); ID3D11Texture2D_Release(texture); continue; } srv_desc.Format = tests[i].stencil_view_format; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, &srv_desc, &stencil_srv); if (hr == E_OUTOFMEMORY) { skip("Could not create SRV for format %#x.\n", srv_desc.Format); ID3D11DepthStencilView_Release(dsv); ID3D11ShaderResourceView_Release(depth_srv); ID3D11Texture2D_Release(texture); continue; } ok(SUCCEEDED(hr), "Failed to create stencil shader resource view for format %#x, hr %#x.\n", srv_desc.Format, hr); ID3D11DeviceContext_PSSetShader(context, ps_stencil, NULL, 0); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &stencil_srv); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_STENCIL, 0.0f, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 0.0f, 0); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_STENCIL, 0.0f, 100); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 100.0f, 0); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_STENCIL, 0.0f, 255); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 255.0f, 0); ID3D11DeviceContext_PSSetShader(context, ps_depth_stencil, NULL, 0); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &depth_srv); ID3D11DeviceContext_PSSetShaderResources(context, 1, 1, &stencil_srv); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 0.3f, 3); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 3.3f, 2); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 3); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 4.0f, 2); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 0.0f, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); check_texture_float(rt_texture, 0.0f, 2); ID3D11DepthStencilView_Release(dsv); ID3D11ShaderResourceView_Release(depth_srv); ID3D11ShaderResourceView_Release(stencil_srv); ID3D11Texture2D_Release(texture); } ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps_cmp); ID3D11PixelShader_Release(ps_depth); ID3D11PixelShader_Release(ps_depth_stencil); ID3D11PixelShader_Release(ps_stencil); ID3D11RenderTargetView_Release(rtv); ID3D11SamplerState_Release(cmp_sampler); ID3D11SamplerState_Release(sampler); ID3D11Texture2D_Release(rt_texture); release_test_context(&test_context); } static void test_sample_c_lz(void) { D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc; struct d3d11_test_context test_context; ID3D11Texture2D *texture, *rt_texture; D3D11_TEXTURE2D_DESC texture_desc; D3D11_SAMPLER_DESC sampler_desc; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; ID3D11DepthStencilView *dsv; ID3D11RenderTargetView *rtv; ID3D11SamplerState *sampler; struct vec4 ps_constant; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *cb; unsigned int i; HRESULT hr; RECT rect; static const float clear_color[] = {0.5f, 0.5f, 0.5f, 0.5f}; static const DWORD ps_array_code[] = { #if 0 Texture2DArray t; SamplerComparisonState s; float ref; float layer; float4 main(float4 position : SV_Position) : SV_Target { return t.SampleCmpLevelZero(s, float3(position.x / 640.0f, position.y / 480.0f, layer), ref); } #endif 0x43425844, 0xfe28b3c3, 0xdd7ef404, 0x8d5874a1, 0x984ff182, 0x00000001, 0x00000180, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000e4, 0x00000041, 0x00000039, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300085a, 0x00106000, 0x00000000, 0x04004058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x06000036, 0x00100042, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0c000047, 0x00100012, 0x00000000, 0x00100246, 0x00000000, 0x00107006, 0x00000000, 0x00106000, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x0100003e, }; static const DWORD ps_cube_code[] = { #if 0 TextureCube t; SamplerComparisonState s; float ref; float face; float4 main(float4 position : SV_Position) : SV_Target { float2 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; float3 coord; switch ((uint)face) { case 0: coord = float3(1.0f, p.x, p.y); break; case 1: coord = float3(-1.0f, p.x, p.y); break; case 2: coord = float3(p.x, 1.0f, p.y); break; case 3: coord = float3(p.x, -1.0f, p.y); break; case 4: coord = float3(p.x, p.y, 1.0f); break; case 5: default: coord = float3(p.x, p.y, -1.0f); break; } return t.SampleCmpLevelZero(s, coord, ref); } #endif 0x43425844, 0xde5655e5, 0x1b116fa1, 0xfce9e757, 0x41c28aac, 0x00000001, 0x00000328, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000028c, 0x00000041, 0x000000a3, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300085a, 0x00106000, 0x00000000, 0x04003058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0600001c, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0300004c, 0x0010000a, 0x00000000, 0x03000006, 0x00004001, 0x00000000, 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0x3f800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x00000000, 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, 0x00004001, 0x00000001, 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0xbf800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x00000000, 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, 0x00004001, 0x00000002, 0x0a000038, 0x00100052, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0x3f800000, 0x01000002, 0x03000006, 0x00004001, 0x00000003, 0x0a000038, 0x00100052, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0xbf800000, 0x01000002, 0x03000006, 0x00004001, 0x00000004, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x01000002, 0x0100000a, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0xbf800000, 0x01000002, 0x01000017, 0x0c000047, 0x00100012, 0x00000000, 0x00100246, 0x00000000, 0x00107006, 0x00000000, 0x00106000, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x0100003e, }; static const float depth_values[] = {1.0f, 0.0f, 0.5f, 0.6f, 0.4f, 0.1f}; static const struct { unsigned int layer; float d_ref; float expected; } tests[] = { {0, 0.5f, 0.0f}, {1, 0.5f, 1.0f}, {2, 0.5f, 0.0f}, {3, 0.5f, 0.0f}, {4, 0.5f, 1.0f}, {5, 0.5f, 1.0f}, {0, 0.0f, 0.0f}, {1, 0.0f, 0.0f}, {2, 0.0f, 0.0f}, {3, 0.0f, 0.0f}, {4, 0.0f, 0.0f}, {5, 0.0f, 0.0f}, {0, 1.0f, 0.0f}, {1, 1.0f, 1.0f}, {2, 1.0f, 1.0f}, {3, 1.0f, 1.0f}, {4, 1.0f, 1.0f}, {5, 1.0f, 1.0f}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; sampler_desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_GREATER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = 10.0f; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_R32_FLOAT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rt_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rt_texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); memset(&ps_constant, 0, sizeof(ps_constant)); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(ps_constant), &ps_constant); /* 2D array texture */ texture_desc.Width = 32; texture_desc.Height = 32; texture_desc.MipLevels = 2; texture_desc.ArraySize = ARRAY_SIZE(depth_values); texture_desc.Format = DXGI_FORMAT_R32_TYPELESS; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(depth_values); ++i) { dsv_desc.Format = DXGI_FORMAT_D32_FLOAT; dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; dsv_desc.Flags = 0; U(dsv_desc).Texture2DArray.MipSlice = 0; U(dsv_desc).Texture2DArray.FirstArraySlice = i; U(dsv_desc).Texture2DArray.ArraySize = 1; hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, &dsv_desc, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, depth_values[i], 0); ID3D11DepthStencilView_Release(dsv); U(dsv_desc).Texture2DArray.MipSlice = 1; hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, &dsv_desc, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); ID3D11DepthStencilView_Release(dsv); } srv_desc.Format = DXGI_FORMAT_R32_FLOAT; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; U(srv_desc).Texture2DArray.MostDetailedMip = 0; U(srv_desc).Texture2DArray.MipLevels = ~0u; U(srv_desc).Texture2DArray.FirstArraySlice = 0; U(srv_desc).Texture2DArray.ArraySize = ~0u; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, &srv_desc, &srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_array_code, sizeof(ps_array_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); for (i = 0; i < ARRAY_SIZE(tests); ++i) { ps_constant.x = tests[i].d_ref; ps_constant.y = tests[i].layer; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, clear_color); draw_quad(&test_context); check_texture_float(rt_texture, tests[i].expected, 2); } ID3D11Texture2D_Release(texture); ID3D11ShaderResourceView_Release(srv); ID3D11PixelShader_Release(ps); /* cube texture */ texture_desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(depth_values); ++i) { dsv_desc.Format = DXGI_FORMAT_D32_FLOAT; dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; dsv_desc.Flags = 0; U(dsv_desc).Texture2DArray.MipSlice = 0; U(dsv_desc).Texture2DArray.FirstArraySlice = i; U(dsv_desc).Texture2DArray.ArraySize = 1; hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, &dsv_desc, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, depth_values[i], 0); ID3D11DepthStencilView_Release(dsv); U(dsv_desc).Texture2DArray.MipSlice = 1; hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, &dsv_desc, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); ID3D11DepthStencilView_Release(dsv); } srv_desc.Format = DXGI_FORMAT_R32_FLOAT; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; U(srv_desc).TextureCube.MostDetailedMip = 0; U(srv_desc).TextureCube.MipLevels = ~0u; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, &srv_desc, &srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_cube_code, sizeof(ps_cube_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); for (i = 0; i < ARRAY_SIZE(tests); ++i) { ps_constant.x = tests[i].d_ref; ps_constant.y = tests[i].layer; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, clear_color); draw_quad(&test_context); /* Avoid testing values affected by seamless cube map filtering. */ SetRect(&rect, 100, 100, 540, 380); check_texture_sub_resource_float(rt_texture, 0, &rect, tests[i].expected, 2); } ID3D11Texture2D_Release(texture); ID3D11ShaderResourceView_Release(srv); ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps); ID3D11RenderTargetView_Release(rtv); ID3D11SamplerState_Release(sampler); ID3D11Texture2D_Release(rt_texture); release_test_context(&test_context); } static void test_multiple_render_targets(void) { ID3D11RenderTargetView *rtv[4], *tmp_rtv[4]; D3D11_TEXTURE2D_DESC texture_desc; ID3D11InputLayout *input_layout; unsigned int stride, offset, i; ID3D11DeviceContext *context; ID3D11Texture2D *rt[4]; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *vb; ULONG refcount; HRESULT hr; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const DWORD vs_code[] = { #if 0 float4 main(float4 position : POSITION) : SV_POSITION { return position; } #endif 0x43425844, 0xa7a2f22d, 0x83ff2560, 0xe61638bd, 0x87e3ce90, 0x00000001, 0x000000d8, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000003c, 0x00010040, 0x0000000f, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 struct output { float4 t1 : SV_TARGET0; float4 t2 : SV_Target1; float4 t3 : SV_TARGET2; float4 t4 : SV_Target3; }; output main(float4 position : SV_POSITION) { struct output o; o.t1 = (float4)1.0f; o.t2 = (float4)0.5f; o.t3 = (float4)0.2f; o.t4 = float4(0.0f, 0.2f, 0.5f, 1.0f); return o; } #endif 0x43425844, 0x8701ad18, 0xe3d5291d, 0x7b4288a6, 0x01917515, 0x00000001, 0x000001a8, 0x00000003, 0x0000002c, 0x00000060, 0x000000e4, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000007c, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000072, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000068, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x0000000f, 0x00000072, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x0000000f, 0x545f5653, 0x45475241, 0x56530054, 0x7261545f, 0x00746567, 0x52444853, 0x000000bc, 0x00000040, 0x0000002f, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000003, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x08000036, 0x001020f2, 0x00000002, 0x00004002, 0x3e4ccccd, 0x3e4ccccd, 0x3e4ccccd, 0x3e4ccccd, 0x08000036, 0x001020f2, 0x00000003, 0x00004002, 0x00000000, 0x3e4ccccd, 0x3f000000, 0x3f800000, 0x0100003e, }; static const struct vec2 quad[] = { {-1.0f, -1.0f}, {-1.0f, 1.0f}, { 1.0f, -1.0f}, { 1.0f, 1.0f}, }; static const float red[] = {1.0f, 0.0f, 0.0f, 1.0f}; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(quad), quad); texture_desc.Width = 640; texture_desc.Height = 480; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; for (i = 0; i < ARRAY_SIZE(rt); ++i) { hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rt[i]); ok(SUCCEEDED(hr), "Failed to create texture %u, hr %#x.\n", i, hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rt[i], NULL, &rtv[i]); ok(SUCCEEDED(hr), "Failed to create rendertarget view %u, hr %#x.\n", i, hr); } hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11Device_GetImmediateContext(device, &context); ID3D11DeviceContext_OMSetRenderTargets(context, 4, rtv, NULL); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); stride = sizeof(*quad); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, &stride, &offset); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); set_viewport(context, 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1.0f); for (i = 0; i < ARRAY_SIZE(rtv); ++i) ID3D11DeviceContext_ClearRenderTargetView(context, rtv[i], red); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(rt[0], 0xffffffff, 2); check_texture_color(rt[1], 0x7f7f7f7f, 2); check_texture_color(rt[2], 0x33333333, 2); check_texture_color(rt[3], 0xff7f3300, 2); for (i = 0; i < ARRAY_SIZE(rtv); ++i) ID3D11DeviceContext_ClearRenderTargetView(context, rtv[i], red); for (i = 0; i < ARRAY_SIZE(tmp_rtv); ++i) { memset(tmp_rtv, 0, sizeof(tmp_rtv)); tmp_rtv[i] = rtv[i]; ID3D11DeviceContext_OMSetRenderTargets(context, 4, tmp_rtv, NULL); ID3D11DeviceContext_Draw(context, 4, 0); } check_texture_color(rt[0], 0xffffffff, 2); check_texture_color(rt[1], 0x7f7f7f7f, 2); check_texture_color(rt[2], 0x33333333, 2); check_texture_color(rt[3], 0xff7f3300, 2); ID3D11Buffer_Release(vb); ID3D11PixelShader_Release(ps); ID3D11VertexShader_Release(vs); ID3D11InputLayout_Release(input_layout); for (i = 0; i < ARRAY_SIZE(rtv); ++i) { ID3D11RenderTargetView_Release(rtv[i]); ID3D11Texture2D_Release(rt[i]); } ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_render_target_views(void) { struct texture { UINT miplevel_count; UINT array_size; }; static const struct vec4 red = {1.0f, 0.0f, 0.0f, 1.0f}; static struct test { struct texture texture; struct rtv_desc rtv; DWORD expected_colors[4]; } tests[] = { {{2, 1}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2D, 0}, {0xff0000ff, 0x00000000}}, {{2, 1}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2D, 1}, {0x00000000, 0xff0000ff}}, {{2, 1}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 0, 0, 1}, {0xff0000ff, 0x00000000}}, {{2, 1}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 1, 0, 1}, {0x00000000, 0xff0000ff}}, {{1, 4}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2D, 0}, {0xff0000ff, 0x00000000, 0x00000000, 0x00000000}}, {{1, 4}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 0, 0, 1}, {0xff0000ff, 0x00000000, 0x00000000, 0x00000000}}, {{1, 4}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 0, 1, 1}, {0x00000000, 0xff0000ff, 0x00000000, 0x00000000}}, {{1, 4}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 0, 2, 1}, {0x00000000, 0x00000000, 0xff0000ff, 0x00000000}}, {{1, 4}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 0, 3, 1}, {0x00000000, 0x00000000, 0x00000000, 0xff0000ff}}, {{1, 4}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 0, 0, 4}, {0xff0000ff, 0x00000000, 0x00000000, 0x00000000}}, {{2, 2}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2D, 0}, {0xff0000ff, 0x00000000, 0x00000000, 0x00000000}}, {{2, 2}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 0, 0, 1}, {0xff0000ff, 0x00000000, 0x00000000, 0x00000000}}, {{2, 2}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 0, 1, 1}, {0x00000000, 0x00000000, 0xff0000ff, 0x00000000}}, {{2, 2}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 1, 0, 1}, {0x00000000, 0xff0000ff, 0x00000000, 0x00000000}}, {{2, 2}, {DXGI_FORMAT_UNKNOWN, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, 1, 1, 1}, {0x00000000, 0x00000000, 0x00000000, 0xff0000ff}}, }; #define FMT_UNKNOWN DXGI_FORMAT_UNKNOWN #define RGBA8_UNORM DXGI_FORMAT_R8G8B8A8_UNORM #define RGBA8_SRGB DXGI_FORMAT_R8G8B8A8_UNORM_SRGB #define RGBA8_UINT DXGI_FORMAT_R8G8B8A8_UINT #define RGBA8_TL DXGI_FORMAT_R8G8B8A8_TYPELESS #define DIM_UNKNOWN D3D11_RTV_DIMENSION_UNKNOWN #define TEX_1D D3D11_RTV_DIMENSION_TEXTURE1D #define TEX_1D_ARRAY D3D11_RTV_DIMENSION_TEXTURE1DARRAY #define TEX_2D D3D11_RTV_DIMENSION_TEXTURE2D #define TEX_2D_ARRAY D3D11_RTV_DIMENSION_TEXTURE2DARRAY #define TEX_3D D3D11_RTV_DIMENSION_TEXTURE3D static const struct { struct { D3D11_RTV_DIMENSION dimension; unsigned int miplevel_count; unsigned int depth_or_array_size; DXGI_FORMAT format; } texture; struct rtv_desc rtv_desc; } invalid_desc_tests[] = { {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, DIM_UNKNOWN}}, {{TEX_2D, 6, 4, RGBA8_UNORM}, {RGBA8_UNORM, DIM_UNKNOWN}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, ~0u}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_TL, TEX_2D, 0}}, {{TEX_2D, 1, 1, RGBA8_TL}, {FMT_UNKNOWN, TEX_2D, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 1, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 2}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 1, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UINT, TEX_2D, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UINT}, {RGBA8_UNORM, TEX_2D, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_SRGB, TEX_2D, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_SRGB}, {RGBA8_UNORM, TEX_2D, 0, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, 0}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 1, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_TL, TEX_3D, 0, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_TL, TEX_3D, 0, 0, 1}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, 9}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 3, 0, 2}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 2, 0, 4}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 1, 0, 8}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 8, ~0u}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 1, 4, ~0u}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 2, 2, ~0u}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 3, 1, ~0u}}, }; #undef FMT_UNKNOWN #undef RGBA8_UNORM #undef RGBA8_SRGB #undef RGBA8_UINT #undef RGBA8_TL #undef DIM_UNKNOWN #undef TEX_1D #undef TEX_1D_ARRAY #undef TEX_2D #undef TEX_2D_ARRAY #undef TEX_3D struct d3d11_test_context test_context; D3D11_RENDER_TARGET_VIEW_DESC rtv_desc; D3D11_TEXTURE3D_DESC texture3d_desc; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Texture3D *texture3d; ID3D11Texture2D *texture; ID3D11Resource *resource; ID3D11Device *device; unsigned int i, j, k; void *data; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 32; texture_desc.Height = 32; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; data = heap_alloc_zero(texture_desc.Width * texture_desc.Height * 4); ok(!!data, "Failed to allocate memory.\n"); for (i = 0; i < ARRAY_SIZE(tests); ++i) { const struct test *test = &tests[i]; unsigned int sub_resource_count; texture_desc.MipLevels = test->texture.miplevel_count; texture_desc.ArraySize = test->texture.array_size; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr); get_rtv_desc(&rtv_desc, &test->rtv); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, &rtv_desc, &rtv); ok(SUCCEEDED(hr), "Test %u: Failed to create render target view, hr %#x.\n", i, hr); for (j = 0; j < texture_desc.ArraySize; ++j) { for (k = 0; k < texture_desc.MipLevels; ++k) { unsigned int sub_resource_idx = j * texture_desc.MipLevels + k; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, sub_resource_idx, NULL, data, texture_desc.Width * 4, 0); } } check_texture_color(texture, 0, 0); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); draw_color_quad(&test_context, &red); sub_resource_count = texture_desc.MipLevels * texture_desc.ArraySize; assert(sub_resource_count <= ARRAY_SIZE(test->expected_colors)); for (j = 0; j < sub_resource_count; ++j) check_texture_sub_resource_color(texture, j, NULL, test->expected_colors[j], 1); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(texture); } texture3d_desc.Width = 32; texture3d_desc.Height = 32; texture3d_desc.Depth = 32; texture3d_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture3d_desc.Usage = D3D11_USAGE_DEFAULT; texture3d_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture3d_desc.CPUAccessFlags = 0; texture3d_desc.MiscFlags = 0; for (i = 0; i < ARRAY_SIZE(invalid_desc_tests); ++i) { assert(invalid_desc_tests[i].texture.dimension == D3D11_RTV_DIMENSION_TEXTURE2D || invalid_desc_tests[i].texture.dimension == D3D11_RTV_DIMENSION_TEXTURE3D); if (invalid_desc_tests[i].texture.dimension == D3D11_RTV_DIMENSION_TEXTURE2D) { texture_desc.MipLevels = invalid_desc_tests[i].texture.miplevel_count; texture_desc.ArraySize = invalid_desc_tests[i].texture.depth_or_array_size; texture_desc.Format = invalid_desc_tests[i].texture.format; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); resource = (ID3D11Resource *)texture; } else { texture3d_desc.MipLevels = invalid_desc_tests[i].texture.miplevel_count; texture3d_desc.Depth = invalid_desc_tests[i].texture.depth_or_array_size; texture3d_desc.Format = invalid_desc_tests[i].texture.format; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, &texture3d); ok(SUCCEEDED(hr), "Test %u: Failed to create 3d texture, hr %#x.\n", i, hr); resource = (ID3D11Resource *)texture3d; } get_rtv_desc(&rtv_desc, &invalid_desc_tests[i].rtv_desc); hr = ID3D11Device_CreateRenderTargetView(device, resource, &rtv_desc, &rtv); ok(hr == E_INVALIDARG, "Test %u: Got unexpected hr %#x.\n", i, hr); ID3D11Resource_Release(resource); } heap_free(data); release_test_context(&test_context); } static void test_layered_rendering(void) { struct { unsigned int layer_offset; unsigned int draw_id; unsigned int padding[2]; } constant; struct d3d11_test_context test_context; D3D11_RENDER_TARGET_VIEW_DESC rtv_desc; unsigned int i, sub_resource_count; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Texture2D *texture; ID3D11GeometryShader *gs; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *cb; HRESULT hr; BOOL warp; static const DWORD vs_code[] = { #if 0 uint layer_offset; void main(float4 position : POSITION, out float4 out_position : SV_POSITION, out uint layer : SV_RenderTargetArrayIndex) { out_position = position; layer = layer_offset; } #endif 0x43425844, 0x71f7b9cd, 0x2ab8c713, 0x53e77663, 0x54a9ba68, 0x00000001, 0x00000158, 0x00000004, 0x00000030, 0x00000064, 0x000000cc, 0x00000148, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x00000060, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000004, 0x00000001, 0x00000001, 0x00000e01, 0x505f5653, 0x5449534f, 0x004e4f49, 0x525f5653, 0x65646e65, 0x72615472, 0x41746567, 0x79617272, 0x65646e49, 0xabab0078, 0x52444853, 0x00000074, 0x00010040, 0x0000001d, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x04000067, 0x00102012, 0x00000001, 0x00000004, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x06000036, 0x00102012, 0x00000001, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, 0x30494653, 0x00000008, 0x00002000, 0x00000000, }; static const DWORD gs_5_code[] = { #if 0 uint layer_offset; struct gs_in { float4 pos : SV_Position; }; struct gs_out { float4 pos : SV_Position; uint layer : SV_RenderTargetArrayIndex; }; [instance(4)] [maxvertexcount(3)] void main(triangle gs_in vin[3], in uint instance_id : SV_GSInstanceID, inout TriangleStream vout) { gs_out o; o.layer = layer_offset + instance_id; for (uint i = 0; i < 3; ++i) { o.pos = vin[i].pos; vout.Append(o); } } #endif 0x43425844, 0xb52da162, 0x9a13d8ee, 0xf7c30b50, 0xe80bc2e7, 0x00000001, 0x00000218, 0x00000003, 0x0000002c, 0x00000060, 0x000000d0, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x3547534f, 0x00000068, 0x00000002, 0x00000008, 0x00000000, 0x00000040, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000000, 0x0000004c, 0x00000000, 0x00000004, 0x00000001, 0x00000001, 0x00000e01, 0x505f5653, 0x7469736f, 0x006e6f69, 0x525f5653, 0x65646e65, 0x72615472, 0x41746567, 0x79617272, 0x65646e49, 0xabab0078, 0x58454853, 0x00000140, 0x00020050, 0x00000050, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x05000061, 0x002010f2, 0x00000003, 0x00000000, 0x00000001, 0x0200005f, 0x00025000, 0x02000068, 0x00000001, 0x020000ce, 0x00000004, 0x0100185d, 0x0300008f, 0x00110000, 0x00000000, 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x04000067, 0x00102012, 0x00000001, 0x00000004, 0x0200005e, 0x00000003, 0x0700001e, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0002500a, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100042, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000003, 0x03040003, 0x0010002a, 0x00000000, 0x07000036, 0x001020f2, 0x00000000, 0x00a01e46, 0x0010001a, 0x00000000, 0x00000000, 0x05000036, 0x00102012, 0x00000001, 0x0010000a, 0x00000000, 0x03000075, 0x00110000, 0x00000000, 0x0700001e, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x0100003e, }; static const DWORD gs_4_code[] = { #if 0 uint layer_offset; struct gs_in { float4 pos : SV_Position; }; struct gs_out { float4 pos : SV_Position; uint layer : SV_RenderTargetArrayIndex; }; [maxvertexcount(12)] void main(triangle gs_in vin[3], inout TriangleStream vout) { gs_out o; for (uint instance_id = 0; instance_id < 4; ++instance_id) { o.layer = layer_offset + instance_id; for (uint i = 0; i < 3; ++i) { o.pos = vin[i].pos; vout.Append(o); } vout.RestartStrip(); } } #endif 0x43425844, 0x7eabd7c5, 0x8af1468e, 0xd585cade, 0xfe0d761d, 0x00000001, 0x00000250, 0x00000003, 0x0000002c, 0x00000060, 0x000000c8, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x00000060, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000004, 0x00000001, 0x00000001, 0x00000e01, 0x505f5653, 0x7469736f, 0x006e6f69, 0x525f5653, 0x65646e65, 0x72615472, 0x41746567, 0x79617272, 0x65646e49, 0xabab0078, 0x52444853, 0x00000180, 0x00020040, 0x00000060, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x05000061, 0x002010f2, 0x00000003, 0x00000000, 0x00000001, 0x02000068, 0x00000001, 0x0100185d, 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x04000067, 0x00102012, 0x00000001, 0x00000004, 0x0200005e, 0x0000000c, 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000004, 0x03040003, 0x0010001a, 0x00000000, 0x0800001e, 0x00100022, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0010000a, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100082, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000003, 0x03040003, 0x0010003a, 0x00000000, 0x07000036, 0x001020f2, 0x00000000, 0x00a01e46, 0x0010002a, 0x00000000, 0x00000000, 0x05000036, 0x00102012, 0x00000001, 0x0010001a, 0x00000000, 0x01000013, 0x0700001e, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x01000009, 0x0700001e, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 uint layer_offset; uint draw_id; float4 main(in float4 pos : SV_Position, in uint layer : SV_RenderTargetArrayIndex) : SV_Target { return float4(layer, draw_id, 0, 0); } #endif 0x43425844, 0x5fa6ae84, 0x3f893c81, 0xf15892d6, 0x142e2e6b, 0x00000001, 0x00000154, 0x00000003, 0x0000002c, 0x00000094, 0x000000c8, 0x4e475349, 0x00000060, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000004, 0x00000001, 0x00000001, 0x00000101, 0x505f5653, 0x7469736f, 0x006e6f69, 0x525f5653, 0x65646e65, 0x72615472, 0x41746567, 0x79617272, 0x65646e49, 0xabab0078, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000084, 0x00000040, 0x00000021, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04000864, 0x00101012, 0x00000001, 0x00000004, 0x03000065, 0x001020f2, 0x00000000, 0x05000056, 0x00102012, 0x00000000, 0x0010100a, 0x00000001, 0x06000056, 0x00102022, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0100003e, }; static const struct vec4 expected_values[] = { {0.0f, 0.0f}, {0.0f, 3.0f}, {3.0f, 11.0f}, {1.0f, 0.0f}, {1.0f, 3.0f}, {3.0f, 10.0f}, {2.0f, 0.0f}, {2.0f, 3.0f}, {3.0f, 9.0f}, {4.0f, 2.0f}, {3.0f, 3.0f}, {3.0f, 8.0f}, {4.0f, 1.0f}, {4.0f, 3.0f}, {3.0f, 7.0f}, {5.0f, 1.0f}, {5.0f, 3.0f}, {3.0f, 6.0f}, {6.0f, 1.0f}, {6.0f, 3.0f}, {3.0f, 5.0f}, {7.0f, 1.0f}, {7.0f, 3.0f}, {3.0f, 4.0f}, }; static const struct vec4 vs_expected_value = {1.0f, 42.0f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; warp = is_warp_device(device); memset(&constant, 0, sizeof(constant)); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constant), &constant); ID3D11DeviceContext_VSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_GSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); /* Geometry shader instancing seems broken on WARP. */ if (ID3D11Device_GetFeatureLevel(device) < D3D_FEATURE_LEVEL_11_0 || warp) { hr = ID3D11Device_CreateGeometryShader(device, gs_4_code, sizeof(gs_4_code), NULL, &gs); ok(SUCCEEDED(hr), "Failed to create geometry shader, hr %#x.\n", hr); } else { hr = ID3D11Device_CreateGeometryShader(device, gs_5_code, sizeof(gs_5_code), NULL, &gs); ok(SUCCEEDED(hr), "Failed to create geometry shader, hr %#x.\n", hr); } ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); texture_desc.Width = 32; texture_desc.Height = 32; texture_desc.MipLevels = 3; texture_desc.ArraySize = 8; texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); constant.layer_offset = 0; constant.draw_id = 0; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); constant.layer_offset = 4; constant.draw_id = 1; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); ID3D11RenderTargetView_Release(rtv); rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; rtv_desc.Format = texture_desc.Format; U(rtv_desc).Texture2DArray.MipSlice = 0; U(rtv_desc).Texture2DArray.FirstArraySlice = 3; U(rtv_desc).Texture2DArray.ArraySize = 1; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, &rtv_desc, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); constant.layer_offset = 1; constant.draw_id = 2; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); ID3D11RenderTargetView_Release(rtv); rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; U(rtv_desc).Texture2DArray.MipSlice = 1; U(rtv_desc).Texture2DArray.FirstArraySlice = 0; U(rtv_desc).Texture2DArray.ArraySize = ~0u; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, &rtv_desc, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); constant.layer_offset = 0; constant.draw_id = 3; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); constant.layer_offset = 4; constant.draw_id = 3; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); ID3D11RenderTargetView_Release(rtv); rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; U(rtv_desc).Texture2DArray.MipSlice = 2; U(rtv_desc).Texture2DArray.ArraySize = 1; for (i = 0; i < texture_desc.ArraySize; ++i) { U(rtv_desc).Texture2DArray.FirstArraySlice = texture_desc.ArraySize - 1 - i; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, &rtv_desc, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); constant.layer_offset = 0; constant.draw_id = 4 + i; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); ID3D11RenderTargetView_Release(rtv); } sub_resource_count = texture_desc.MipLevels * texture_desc.ArraySize; assert(ARRAY_SIZE(expected_values) == sub_resource_count); for (i = 0; i < sub_resource_count; ++i) { if (warp && (i == 3 || i == 4)) /* Broken on WARP. */ continue; check_texture_sub_resource_vec4(texture, i, NULL, &expected_values[i], 1); } /* layered rendering without GS */ if (!check_viewport_array_index_from_any_shader_support(device)) { hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); if (SUCCEEDED(hr)) ID3D11VertexShader_Release(vs); skip("Viewport array index not supported in vertex shaders.\n"); goto done; } ID3D11DeviceContext_GSSetShader(context, NULL, NULL, 0); constant.layer_offset = 1; constant.draw_id = 42; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; U(rtv_desc).Texture2DArray.MipSlice = 0; U(rtv_desc).Texture2DArray.FirstArraySlice = 0; U(rtv_desc).Texture2DArray.ArraySize = ~0u; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, &rtv_desc, &rtv); ok(hr == S_OK, "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); draw_quad_vs(&test_context, vs_code, sizeof(vs_code)); check_texture_sub_resource_vec4(texture, constant.layer_offset * texture_desc.MipLevels, NULL, &vs_expected_value, 1); ID3D11RenderTargetView_Release(rtv); done: ID3D11Texture2D_Release(texture); ID3D11Buffer_Release(cb); ID3D11GeometryShader_Release(gs); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_scissor(void) { struct d3d11_test_context test_context; ID3D11DeviceContext *immediate_context; D3D11_RASTERIZER_DESC rs_desc; ID3D11RasterizerState *rs; D3D11_RECT scissor_rect; ID3D11Device *device; DWORD color; HRESULT hr; static const float red[] = {1.0f, 0.0f, 0.0f, 1.0f}; static const struct vec4 green = {0.0f, 1.0f, 0.0f, 1.0f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; immediate_context = test_context.immediate_context; rs_desc.FillMode = D3D11_FILL_SOLID; rs_desc.CullMode = D3D11_CULL_BACK; rs_desc.FrontCounterClockwise = FALSE; rs_desc.DepthBias = 0; rs_desc.DepthBiasClamp = 0.0f; rs_desc.SlopeScaledDepthBias = 0.0f; rs_desc.DepthClipEnable = TRUE; rs_desc.ScissorEnable = TRUE; rs_desc.MultisampleEnable = FALSE; rs_desc.AntialiasedLineEnable = FALSE; hr = ID3D11Device_CreateRasterizerState(device, &rs_desc, &rs); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); SetRect(&scissor_rect, 160, 120, 480, 360); ID3D11DeviceContext_RSSetScissorRects(immediate_context, 1, &scissor_rect); ID3D11DeviceContext_ClearRenderTargetView(immediate_context, test_context.backbuffer_rtv, red); check_texture_color(test_context.backbuffer, 0xff0000ff, 1); draw_color_quad(&test_context, &green); color = get_texture_color(test_context.backbuffer, 320, 60); ok(compare_color(color, 0xff00ff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 80, 240); ok(compare_color(color, 0xff00ff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 320, 240); ok(compare_color(color, 0xff00ff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 560, 240); ok(compare_color(color, 0xff00ff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 320, 420); ok(compare_color(color, 0xff00ff00, 1), "Got unexpected color 0x%08x.\n", color); ID3D11DeviceContext_ClearRenderTargetView(immediate_context, test_context.backbuffer_rtv, red); ID3D11DeviceContext_RSSetState(immediate_context, rs); draw_color_quad(&test_context, &green); color = get_texture_color(test_context.backbuffer, 320, 60); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 80, 240); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 320, 240); ok(compare_color(color, 0xff00ff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 560, 240); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 320, 420); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); ID3D11RasterizerState_Release(rs); release_test_context(&test_context); } static void test_clear_state(void) { static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; #if 0 float4 main(float4 pos : POSITION) : POSITION { return pos; } #endif static const DWORD simple_vs[] = { 0x43425844, 0x66689e7c, 0x643f0971, 0xb7f67ff4, 0xabc48688, 0x00000001, 0x000000d4, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x52444853, 0x00000038, 0x00010040, 0x0000000e, 0x0300005f, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; #if 0 struct data { float4 position : SV_Position; }; struct patch_constant_data { float edges[3] : SV_TessFactor; float inside : SV_InsideTessFactor; }; void patch_constant(InputPatch input, out patch_constant_data output) { output.edges[0] = output.edges[1] = output.edges[2] = 1.0f; output.inside = 1.0f; } [domain("tri")] [outputcontrolpoints(3)] [partitioning("integer")] [outputtopology("triangle_ccw")] [patchconstantfunc("patch_constant")] data hs_main(InputPatch input, uint i : SV_OutputControlPointID) { return input[i]; } [domain("tri")] void ds_main(patch_constant_data input, float3 tess_coord : SV_DomainLocation, const OutputPatch patch, out data output) { output.position = tess_coord.x * patch[0].position + tess_coord.y * patch[1].position + tess_coord.z * patch[2].position; } #endif static const DWORD simple_hs[] = { 0x43425844, 0x42b5df25, 0xfd8aa2b1, 0xbe5490cb, 0xb595f8b1, 0x00000001, 0x0000020c, 0x00000004, 0x00000030, 0x00000064, 0x00000098, 0x0000012c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x47534350, 0x0000008c, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x0000000d, 0x00000003, 0x00000000, 0x00000e01, 0x00000068, 0x00000001, 0x0000000d, 0x00000003, 0x00000001, 0x00000e01, 0x00000068, 0x00000002, 0x0000000d, 0x00000003, 0x00000002, 0x00000e01, 0x00000076, 0x00000000, 0x0000000e, 0x00000003, 0x00000003, 0x00000e01, 0x545f5653, 0x46737365, 0x6f746361, 0x56530072, 0x736e495f, 0x54656469, 0x46737365, 0x6f746361, 0xabab0072, 0x58454853, 0x000000d8, 0x00030050, 0x00000036, 0x01000071, 0x01001893, 0x01001894, 0x01001095, 0x01000896, 0x01002097, 0x0100086a, 0x01000073, 0x02000099, 0x00000003, 0x0200005f, 0x00017000, 0x04000067, 0x00102012, 0x00000000, 0x00000011, 0x04000067, 0x00102012, 0x00000001, 0x00000012, 0x04000067, 0x00102012, 0x00000002, 0x00000013, 0x02000068, 0x00000001, 0x0400005b, 0x00102012, 0x00000000, 0x00000003, 0x04000036, 0x00100012, 0x00000000, 0x0001700a, 0x06000036, 0x00902012, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000003, 0x00000014, 0x05000036, 0x00102012, 0x00000003, 0x00004001, 0x3f800000, 0x0100003e, }; static const DWORD simple_ds[] = { 0x43425844, 0xb7e35b82, 0x1b930ff2, 0x48d3a0f2, 0x375219ed, 0x00000001, 0x000001e0, 0x00000004, 0x00000030, 0x00000064, 0x000000f8, 0x0000012c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x47534350, 0x0000008c, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x0000000d, 0x00000003, 0x00000000, 0x00000001, 0x00000068, 0x00000001, 0x0000000d, 0x00000003, 0x00000001, 0x00000001, 0x00000068, 0x00000002, 0x0000000d, 0x00000003, 0x00000002, 0x00000001, 0x00000076, 0x00000000, 0x0000000e, 0x00000003, 0x00000003, 0x00000001, 0x545f5653, 0x46737365, 0x6f746361, 0x56530072, 0x736e495f, 0x54656469, 0x46737365, 0x6f746361, 0xabab0072, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x58454853, 0x000000ac, 0x00040050, 0x0000002b, 0x01001893, 0x01001095, 0x0100086a, 0x0200005f, 0x0001c072, 0x0400005f, 0x002190f2, 0x00000003, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x02000068, 0x00000001, 0x07000038, 0x001000f2, 0x00000000, 0x0001c556, 0x00219e46, 0x00000001, 0x00000000, 0x09000032, 0x001000f2, 0x00000000, 0x0001c006, 0x00219e46, 0x00000000, 0x00000000, 0x00100e46, 0x00000000, 0x09000032, 0x001020f2, 0x00000000, 0x0001caa6, 0x00219e46, 0x00000002, 0x00000000, 0x00100e46, 0x00000000, 0x0100003e, }; #if 0 struct gs_out { float4 pos : SV_POSITION; }; [maxvertexcount(4)] void main(point float4 vin[1] : POSITION, inout TriangleStream vout) { float offset = 0.1 * vin[0].w; gs_out v; v.pos = float4(vin[0].x - offset, vin[0].y - offset, vin[0].z, vin[0].w); vout.Append(v); v.pos = float4(vin[0].x - offset, vin[0].y + offset, vin[0].z, vin[0].w); vout.Append(v); v.pos = float4(vin[0].x + offset, vin[0].y - offset, vin[0].z, vin[0].w); vout.Append(v); v.pos = float4(vin[0].x + offset, vin[0].y + offset, vin[0].z, vin[0].w); vout.Append(v); } #endif static const DWORD simple_gs[] = { 0x43425844, 0x000ee786, 0xc624c269, 0x885a5cbe, 0x444b3b1f, 0x00000001, 0x0000023c, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x000001a0, 0x00020040, 0x00000068, 0x0400005f, 0x002010f2, 0x00000001, 0x00000000, 0x02000068, 0x00000001, 0x0100085d, 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x0200005e, 0x00000004, 0x0f000032, 0x00100032, 0x00000000, 0x80201ff6, 0x00000041, 0x00000000, 0x00000000, 0x00004002, 0x3dcccccd, 0x3dcccccd, 0x00000000, 0x00000000, 0x00201046, 0x00000000, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0e000032, 0x00100052, 0x00000000, 0x00201ff6, 0x00000000, 0x00000000, 0x00004002, 0x3dcccccd, 0x00000000, 0x3dcccccd, 0x00000000, 0x00201106, 0x00000000, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010002a, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010001a, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x05000036, 0x00102032, 0x00000000, 0x00100086, 0x00000000, 0x06000036, 0x001020c2, 0x00000000, 0x00201ea6, 0x00000000, 0x00000000, 0x01000013, 0x0100003e, }; #if 0 float4 main(float4 color : COLOR) : SV_TARGET { return color; } #endif static const DWORD simple_ps[] = { 0x43425844, 0x08c2b568, 0x17d33120, 0xb7d82948, 0x13a570fb, 0x00000001, 0x000000d0, 0x00000003, 0x0000002c, 0x0000005c, 0x00000090, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; #if 0 [numthreads(1, 1, 1)] void main() { } #endif static const DWORD simple_cs[] = { 0x43425844, 0x1acc3ad0, 0x71c7b057, 0xc72c4306, 0xf432cb57, 0x00000001, 0x00000074, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000020, 0x00050050, 0x00000008, 0x0100086a, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x0100003e, }; D3D11_VIEWPORT tmp_viewport[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; ID3D11ShaderResourceView *tmp_srv[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; ID3D11ShaderResourceView *srv[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; ID3D11RenderTargetView *tmp_rtv[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; RECT tmp_rect[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; ID3D11SamplerState *tmp_sampler[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; ID3D11RenderTargetView *rtv[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; ID3D11Texture2D *rt_texture[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; ID3D11Buffer *cb[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; ID3D11Buffer *tmp_buffer[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; ID3D11SamplerState *sampler[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; ID3D11UnorderedAccessView *tmp_uav[D3D11_PS_CS_UAV_REGISTER_COUNT]; ID3D11UnorderedAccessView *cs_uav[D3D11_PS_CS_UAV_REGISTER_COUNT]; ID3D11Buffer *buffer[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; ID3D11Buffer *cs_uav_buffer[D3D11_PS_CS_UAV_REGISTER_COUNT]; UINT offset[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; UINT stride[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; ID3D11Buffer *so_buffer[D3D11_SO_BUFFER_SLOT_COUNT]; ID3D11InputLayout *tmp_input_layout, *input_layout; ID3D11DepthStencilState *tmp_ds_state, *ds_state; ID3D11BlendState *tmp_blend_state, *blend_state; ID3D11RasterizerState *tmp_rs_state, *rs_state; ID3D11Predicate *tmp_predicate, *predicate; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; ID3D11DepthStencilView *tmp_dsv, *dsv; ID3D11UnorderedAccessView *ps_uav; D3D11_PRIMITIVE_TOPOLOGY topology; D3D11_TEXTURE2D_DESC texture_desc; ID3D11GeometryShader *tmp_gs, *gs; ID3D11ComputeShader *tmp_cs, *cs; D3D11_DEPTH_STENCIL_DESC ds_desc; ID3D11VertexShader *tmp_vs, *vs; ID3D11DomainShader *tmp_ds, *ds; D3D11_SAMPLER_DESC sampler_desc; D3D11_QUERY_DESC predicate_desc; struct device_desc device_desc; ID3D11PixelShader *tmp_ps, *ps; ID3D11HullShader *tmp_hs, *hs; D3D11_RASTERIZER_DESC rs_desc; ID3D11DeviceContext *context; D3D11_BLEND_DESC blend_desc; ID3D11Texture2D *ds_texture; ID3D11Buffer *ps_uav_buffer; float blend_factor[4]; ID3D11Device *device; BOOL predicate_value; UINT instance_count; DXGI_FORMAT format; UINT sample_mask; UINT stencil_ref; ULONG refcount; UINT count, i; HRESULT hr; device_desc.feature_level = &feature_level; device_desc.flags = 0; if (!(device = create_device(&device_desc))) { skip("Failed to create device.\n"); return; } ID3D11Device_GetImmediateContext(device, &context); /* Verify the initial state after device creation. */ ID3D11DeviceContext_VSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_VSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_VSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } instance_count = 100; ID3D11DeviceContext_VSGetShader(context, &tmp_vs, NULL, &instance_count); ok(!tmp_vs, "Got unexpected vertex shader %p.\n", tmp_vs); ok(!instance_count, "Got unexpected instance count %u.\n", instance_count); ID3D11DeviceContext_HSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_HSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_HSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } instance_count = 100; ID3D11DeviceContext_HSGetShader(context, &tmp_hs, NULL, &instance_count); ok(!tmp_hs, "Got unexpected hull shader %p.\n", tmp_hs); ok(!instance_count, "Got unexpected instance count %u.\n", instance_count); ID3D11DeviceContext_DSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_DSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_DSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } instance_count = 100; ID3D11DeviceContext_DSGetShader(context, &tmp_ds, NULL, &instance_count); ok(!tmp_ds, "Got unexpected domain shader %p.\n", tmp_ds); ok(!instance_count, "Got unexpected instance count %u.\n", instance_count); ID3D11DeviceContext_GSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_GSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_GSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } instance_count = 100; ID3D11DeviceContext_GSGetShader(context, &tmp_gs, NULL, &instance_count); ok(!tmp_gs, "Got unexpected geometry shader %p.\n", tmp_gs); ok(!instance_count, "Got unexpected instance count %u.\n", instance_count); ID3D11DeviceContext_PSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_PSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_PSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } instance_count = 100; ID3D11DeviceContext_PSGetShader(context, &tmp_ps, NULL, &instance_count); ok(!tmp_ps, "Got unexpected pixel shader %p.\n", tmp_ps); ok(!instance_count, "Got unexpected instance count %u.\n", instance_count); ID3D11DeviceContext_CSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_CSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_CSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } instance_count = 100; ID3D11DeviceContext_CSGetShader(context, &tmp_cs, NULL, &instance_count); ok(!tmp_cs, "Got unexpected compute shader %p.\n", tmp_cs); ok(!instance_count, "Got unexpected instance count %u.\n", instance_count); ID3D11DeviceContext_CSGetUnorderedAccessViews(context, 0, D3D11_PS_CS_UAV_REGISTER_COUNT, tmp_uav); for (i = 0; i < D3D11_PS_CS_UAV_REGISTER_COUNT; ++i) { ok(!tmp_uav[i], "Got unexpected unordered access view %p in slot %u.\n", tmp_uav[i], i); } ID3D11DeviceContext_IAGetVertexBuffers(context, 0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, tmp_buffer, stride, offset); for (i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected vertex buffer %p in slot %u.\n", tmp_buffer[i], i); ok(!stride[i], "Got unexpected stride %u in slot %u.\n", stride[i], i); ok(!offset[i], "Got unexpected offset %u in slot %u.\n", offset[i], i); } ID3D11DeviceContext_IAGetIndexBuffer(context, tmp_buffer, &format, offset); ok(!tmp_buffer[0], "Got unexpected index buffer %p.\n", tmp_buffer[0]); ok(format == DXGI_FORMAT_UNKNOWN, "Got unexpected index buffer format %#x.\n", format); ok(!offset[0], "Got unexpected index buffer offset %u.\n", offset[0]); ID3D11DeviceContext_IAGetInputLayout(context, &tmp_input_layout); ok(!tmp_input_layout, "Got unexpected input layout %p.\n", tmp_input_layout); ID3D11DeviceContext_IAGetPrimitiveTopology(context, &topology); ok(topology == D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED, "Got unexpected primitive topology %#x.\n", topology); ID3D11DeviceContext_OMGetBlendState(context, &tmp_blend_state, blend_factor, &sample_mask); ok(!tmp_blend_state, "Got unexpected blend state %p.\n", tmp_blend_state); ok(blend_factor[0] == 1.0f && blend_factor[1] == 1.0f && blend_factor[2] == 1.0f && blend_factor[3] == 1.0f, "Got unexpected blend factor {%.8e, %.8e, %.8e, %.8e}.\n", blend_factor[0], blend_factor[1], blend_factor[2], blend_factor[3]); ok(sample_mask == D3D11_DEFAULT_SAMPLE_MASK, "Got unexpected sample mask %#x.\n", sample_mask); ID3D11DeviceContext_OMGetDepthStencilState(context, &tmp_ds_state, &stencil_ref); ok(!tmp_ds_state, "Got unexpected depth stencil state %p.\n", tmp_ds_state); ok(!stencil_ref, "Got unexpected stencil ref %u.\n", stencil_ref); ID3D11DeviceContext_OMGetRenderTargets(context, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, tmp_rtv, &tmp_dsv); for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) { ok(!tmp_rtv[i], "Got unexpected render target view %p in slot %u.\n", tmp_rtv[i], i); } ok(!tmp_dsv, "Got unexpected depth stencil view %p.\n", tmp_dsv); ID3D11DeviceContext_OMGetRenderTargetsAndUnorderedAccessViews(context, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, tmp_rtv, &tmp_dsv, 0, D3D11_PS_CS_UAV_REGISTER_COUNT, tmp_uav); for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) { ok(!tmp_rtv[i], "Got unexpected render target view %p in slot %u.\n", tmp_rtv[i], i); } ok(!tmp_dsv, "Got unexpected depth stencil view %p.\n", tmp_dsv); for (i = 0; i < D3D11_PS_CS_UAV_REGISTER_COUNT; ++i) { ok(!tmp_uav[i], "Got unexpected unordered access view %p in slot %u.\n", tmp_uav[i], i); } if (!enable_debug_layer) { ID3D11DeviceContext_RSGetScissorRects(context, &count, NULL); ok(!count, "Got unexpected scissor rect count %u.\n", count); } memset(tmp_rect, 0x55, sizeof(tmp_rect)); count = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ID3D11DeviceContext_RSGetScissorRects(context, &count, tmp_rect); for (i = 0; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ++i) { ok(!tmp_rect[i].left && !tmp_rect[i].top && !tmp_rect[i].right && !tmp_rect[i].bottom, "Got unexpected scissor rect %s in slot %u.\n", wine_dbgstr_rect(&tmp_rect[i]), i); } ID3D11DeviceContext_RSGetViewports(context, &count, NULL); ok(!count, "Got unexpected viewport count %u.\n", count); memset(tmp_viewport, 0x55, sizeof(tmp_viewport)); count = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ID3D11DeviceContext_RSGetViewports(context, &count, tmp_viewport); for (i = 0; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ++i) { ok(!tmp_viewport[i].TopLeftX && !tmp_viewport[i].TopLeftY && !tmp_viewport[i].Width && !tmp_viewport[i].Height && !tmp_viewport[i].MinDepth && !tmp_viewport[i].MaxDepth, "Got unexpected viewport {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e} in slot %u.\n", tmp_viewport[i].TopLeftX, tmp_viewport[i].TopLeftY, tmp_viewport[i].Width, tmp_viewport[i].Height, tmp_viewport[i].MinDepth, tmp_viewport[i].MaxDepth, i); } ID3D11DeviceContext_RSGetState(context, &tmp_rs_state); ok(!tmp_rs_state, "Got unexpected rasterizer state %p.\n", tmp_rs_state); ID3D11DeviceContext_SOGetTargets(context, D3D11_SO_BUFFER_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected stream output %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_GetPredication(context, &tmp_predicate, &predicate_value); ok(!tmp_predicate, "Got unexpected predicate %p.\n", tmp_predicate); ok(!predicate_value, "Got unexpected predicate value %#x.\n", predicate_value); /* Create resources. */ for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) cb[i] = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, 1024, NULL); for (i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; ++i) { buffer[i] = create_buffer(device, D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER | D3D11_BIND_SHADER_RESOURCE, 1024, NULL); stride[i] = (i + 1) * 4; offset[i] = (i + 1) * 16; } for (i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; ++i) so_buffer[i] = create_buffer(device, D3D11_BIND_STREAM_OUTPUT, 1024, NULL); srv_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; U(srv_desc).Buffer.ElementOffset = 0; U(srv_desc).Buffer.ElementWidth = 64; for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)buffer[i % D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT], &srv_desc, &srv[i]); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); } uav_desc.Format = DXGI_FORMAT_R32_UINT; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 8; U(uav_desc).Buffer.Flags = 0; for (i = 0; i < D3D11_PS_CS_UAV_REGISTER_COUNT; ++i) { cs_uav_buffer[i] = create_buffer(device, D3D11_BIND_UNORDERED_ACCESS, 32, NULL); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)cs_uav_buffer[i], &uav_desc, &cs_uav[i]); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); } ps_uav_buffer = create_buffer(device, D3D11_BIND_UNORDERED_ACCESS, 32, NULL); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)ps_uav_buffer, &uav_desc, &ps_uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 16; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = 16.0f; for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { sampler_desc.MinLOD = (float)i; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler[i]); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); } hr = ID3D11Device_CreateVertexShader(device, simple_vs, sizeof(simple_vs), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreateHullShader(device, simple_hs, sizeof(simple_hs), NULL, &hs); ok(SUCCEEDED(hr), "Failed to create hull shader, hr %#x.\n", hr); hr = ID3D11Device_CreateDomainShader(device, simple_ds, sizeof(simple_ds), NULL, &ds); ok(SUCCEEDED(hr), "Failed to create domain shader, hr %#x.\n", hr); hr = ID3D11Device_CreateGeometryShader(device, simple_gs, sizeof(simple_gs), NULL, &gs); ok(SUCCEEDED(hr), "Failed to create geometry shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, simple_ps, sizeof(simple_ps), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreateComputeShader(device, simple_cs, sizeof(simple_cs), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), simple_vs, sizeof(simple_vs), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); memset(&blend_desc, 0, sizeof(blend_desc)); blend_desc.AlphaToCoverageEnable = FALSE; blend_desc.IndependentBlendEnable = FALSE; blend_desc.RenderTarget[0].BlendEnable = TRUE; blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO; blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &blend_state); ok(SUCCEEDED(hr), "Failed to create blend state, hr %#x.\n", hr); ds_desc.DepthEnable = TRUE; ds_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; ds_desc.DepthFunc = D3D11_COMPARISON_LESS; ds_desc.StencilEnable = FALSE; ds_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; ds_desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; ds_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; ds_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; ds_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; ds_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; ds_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; ds_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; ds_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; ds_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; hr = ID3D11Device_CreateDepthStencilState(device, &ds_desc, &ds_state); ok(SUCCEEDED(hr), "Failed to create depthstencil state, hr %#x.\n", hr); texture_desc.Width = 512; texture_desc.Height = 512; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) { hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rt_texture[i]); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); } texture_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &ds_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) { hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rt_texture[i], NULL, &rtv[i]); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); } hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)ds_texture, NULL, &dsv); ok(SUCCEEDED(hr), "Failed to create depthstencil view, hr %#x.\n", hr); for (i = 0; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ++i) { SetRect(&tmp_rect[i], i, i * 2, i + 1, (i + 1) * 2); tmp_viewport[i].TopLeftX = i * 3; tmp_viewport[i].TopLeftY = i * 4; tmp_viewport[i].Width = 3; tmp_viewport[i].Height = 4; tmp_viewport[i].MinDepth = i * 0.01f; tmp_viewport[i].MaxDepth = (i + 1) * 0.01f; } rs_desc.FillMode = D3D11_FILL_SOLID; rs_desc.CullMode = D3D11_CULL_BACK; rs_desc.FrontCounterClockwise = FALSE; rs_desc.DepthBias = 0; rs_desc.DepthBiasClamp = 0.0f; rs_desc.SlopeScaledDepthBias = 0.0f; rs_desc.DepthClipEnable = TRUE; rs_desc.ScissorEnable = FALSE; rs_desc.MultisampleEnable = FALSE; rs_desc.AntialiasedLineEnable = FALSE; hr = ID3D11Device_CreateRasterizerState(device, &rs_desc, &rs_state); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); predicate_desc.Query = D3D11_QUERY_OCCLUSION_PREDICATE; predicate_desc.MiscFlags = 0; hr = ID3D11Device_CreatePredicate(device, &predicate_desc, &predicate); ok(SUCCEEDED(hr), "Failed to create predicate, hr %#x.\n", hr); /* Setup state. */ /* Some versions of Windows AMD drivers hang while the device is being * released, if the total number of used resource slots exceeds some limit. * Do not use all constant buffers slots in order to not trigger this * driver bug. */ ID3D11DeviceContext_VSSetConstantBuffers(context, 0, 1, &cb[0]); ID3D11DeviceContext_VSSetConstantBuffers(context, 7, 1, &cb[7]); ID3D11DeviceContext_VSSetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, srv); ID3D11DeviceContext_VSSetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, sampler); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_HSSetConstantBuffers(context, 0, 1, &cb[0]); ID3D11DeviceContext_HSSetConstantBuffers(context, 7, 1, &cb[7]); ID3D11DeviceContext_HSSetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, srv); ID3D11DeviceContext_HSSetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, sampler); ID3D11DeviceContext_HSSetShader(context, hs, NULL, 0); ID3D11DeviceContext_DSSetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, cb); ID3D11DeviceContext_DSSetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, srv); ID3D11DeviceContext_DSSetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, sampler); ID3D11DeviceContext_DSSetShader(context, ds, NULL, 0); ID3D11DeviceContext_GSSetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, cb); ID3D11DeviceContext_GSSetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, srv); ID3D11DeviceContext_GSSetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, sampler); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, cb); ID3D11DeviceContext_PSSetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, srv); ID3D11DeviceContext_PSSetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, sampler); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_CSSetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, cb); ID3D11DeviceContext_CSSetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, srv); ID3D11DeviceContext_CSSetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, sampler); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, D3D11_PS_CS_UAV_REGISTER_COUNT, cs_uav, NULL); ID3D11DeviceContext_IASetVertexBuffers(context, 0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, buffer, stride, offset); ID3D11DeviceContext_IASetIndexBuffer(context, buffer[0], DXGI_FORMAT_R32_UINT, offset[0]); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); blend_factor[0] = 0.1f; blend_factor[1] = 0.2f; blend_factor[2] = 0.3f; blend_factor[3] = 0.4f; ID3D11DeviceContext_OMSetBlendState(context, blend_state, blend_factor, 0xff00ff00); ID3D11DeviceContext_OMSetDepthStencilState(context, ds_state, 3); ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT - 1, rtv, dsv, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT - 1, 1, &ps_uav, NULL); ID3D11DeviceContext_RSSetScissorRects(context, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE, tmp_rect); ID3D11DeviceContext_RSSetViewports(context, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE, tmp_viewport); ID3D11DeviceContext_RSSetState(context, rs_state); ID3D11DeviceContext_SOSetTargets(context, D3D11_SO_BUFFER_SLOT_COUNT, so_buffer, offset); ID3D11DeviceContext_SetPredication(context, predicate, TRUE); /* Verify the set state. */ ID3D11DeviceContext_VSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ID3D11Buffer *expected_cb = i % 7 ? NULL : cb[i]; ok(tmp_buffer[i] == expected_cb, "Got unexpected constant buffer %p in slot %u, expected %p.\n", tmp_buffer[i], i, expected_cb); if (tmp_buffer[i]) ID3D11Buffer_Release(tmp_buffer[i]); } ID3D11DeviceContext_VSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(tmp_srv[i] == srv[i], "Got unexpected shader resource view %p in slot %u, expected %p.\n", tmp_srv[i], i, srv[i]); ID3D11ShaderResourceView_Release(tmp_srv[i]); } ID3D11DeviceContext_VSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(tmp_sampler[i] == sampler[i], "Got unexpected sampler %p in slot %u, expected %p.\n", tmp_sampler[i], i, sampler[i]); ID3D11SamplerState_Release(tmp_sampler[i]); } ID3D11DeviceContext_VSGetShader(context, &tmp_vs, NULL, 0); ok(tmp_vs == vs, "Got unexpected vertex shader %p, expected %p.\n", tmp_vs, vs); ID3D11VertexShader_Release(tmp_vs); ID3D11DeviceContext_HSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ID3D11Buffer *expected_cb = i % 7 ? NULL : cb[i]; ok(tmp_buffer[i] == expected_cb, "Got unexpected constant buffer %p in slot %u, expected %p.\n", tmp_buffer[i], i, expected_cb); if (tmp_buffer[i]) ID3D11Buffer_Release(tmp_buffer[i]); } ID3D11DeviceContext_HSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(tmp_srv[i] == srv[i], "Got unexpected shader resource view %p in slot %u, expected %p.\n", tmp_srv[i], i, srv[i]); ID3D11ShaderResourceView_Release(tmp_srv[i]); } ID3D11DeviceContext_HSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(tmp_sampler[i] == sampler[i], "Got unexpected sampler %p in slot %u, expected %p.\n", tmp_sampler[i], i, sampler[i]); ID3D11SamplerState_Release(tmp_sampler[i]); } ID3D11DeviceContext_HSGetShader(context, &tmp_hs, NULL, 0); ok(tmp_hs == hs, "Got unexpected hull shader %p, expected %p.\n", tmp_hs, hs); ID3D11HullShader_Release(tmp_hs); ID3D11DeviceContext_DSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(tmp_buffer[i] == cb[i], "Got unexpected constant buffer %p in slot %u, expected %p.\n", tmp_buffer[i], i, cb[i]); ID3D11Buffer_Release(tmp_buffer[i]); } ID3D11DeviceContext_DSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(tmp_srv[i] == srv[i], "Got unexpected shader resource view %p in slot %u, expected %p.\n", tmp_srv[i], i, srv[i]); ID3D11ShaderResourceView_Release(tmp_srv[i]); } ID3D11DeviceContext_DSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(tmp_sampler[i] == sampler[i], "Got unexpected sampler %p in slot %u, expected %p.\n", tmp_sampler[i], i, sampler[i]); ID3D11SamplerState_Release(tmp_sampler[i]); } ID3D11DeviceContext_DSGetShader(context, &tmp_ds, NULL, 0); ok(tmp_ds == ds, "Got unexpected domain shader %p, expected %p.\n", tmp_ds, ds); ID3D11DomainShader_Release(tmp_ds); ID3D11DeviceContext_GSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(tmp_buffer[i] == cb[i], "Got unexpected constant buffer %p in slot %u, expected %p.\n", tmp_buffer[i], i, cb[i]); ID3D11Buffer_Release(tmp_buffer[i]); } ID3D11DeviceContext_GSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(tmp_srv[i] == srv[i], "Got unexpected shader resource view %p in slot %u, expected %p.\n", tmp_srv[i], i, srv[i]); ID3D11ShaderResourceView_Release(tmp_srv[i]); } ID3D11DeviceContext_GSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(tmp_sampler[i] == sampler[i], "Got unexpected sampler %p in slot %u, expected %p.\n", tmp_sampler[i], i, sampler[i]); ID3D11SamplerState_Release(tmp_sampler[i]); } ID3D11DeviceContext_GSGetShader(context, &tmp_gs, NULL, 0); ok(tmp_gs == gs, "Got unexpected geometry shader %p, expected %p.\n", tmp_gs, gs); ID3D11GeometryShader_Release(tmp_gs); ID3D11DeviceContext_PSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(tmp_buffer[i] == cb[i], "Got unexpected constant buffer %p in slot %u, expected %p.\n", tmp_buffer[i], i, cb[i]); ID3D11Buffer_Release(tmp_buffer[i]); } ID3D11DeviceContext_PSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(tmp_srv[i] == srv[i], "Got unexpected shader resource view %p in slot %u, expected %p.\n", tmp_srv[i], i, srv[i]); ID3D11ShaderResourceView_Release(tmp_srv[i]); } ID3D11DeviceContext_PSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(tmp_sampler[i] == sampler[i], "Got unexpected sampler %p in slot %u, expected %p.\n", tmp_sampler[i], i, sampler[i]); ID3D11SamplerState_Release(tmp_sampler[i]); } ID3D11DeviceContext_PSGetShader(context, &tmp_ps, NULL, 0); ok(tmp_ps == ps, "Got unexpected pixel shader %p, expected %p.\n", tmp_ps, ps); ID3D11PixelShader_Release(tmp_ps); ID3D11DeviceContext_CSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(tmp_buffer[i] == cb[i], "Got unexpected constant buffer %p in slot %u, expected %p.\n", tmp_buffer[i], i, cb[i]); ID3D11Buffer_Release(tmp_buffer[i]); } ID3D11DeviceContext_CSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(tmp_srv[i] == srv[i], "Got unexpected shader resource view %p in slot %u, expected %p.\n", tmp_srv[i], i, srv[i]); ID3D11ShaderResourceView_Release(tmp_srv[i]); } ID3D11DeviceContext_CSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(tmp_sampler[i] == sampler[i], "Got unexpected sampler %p in slot %u, expected %p.\n", tmp_sampler[i], i, sampler[i]); ID3D11SamplerState_Release(tmp_sampler[i]); } ID3D11DeviceContext_CSGetShader(context, &tmp_cs, NULL, 0); ok(tmp_cs == cs, "Got unexpected compute shader %p, expected %p.\n", tmp_cs, cs); ID3D11ComputeShader_Release(tmp_cs); ID3D11DeviceContext_CSGetUnorderedAccessViews(context, 0, D3D11_PS_CS_UAV_REGISTER_COUNT, tmp_uav); for (i = 0; i < D3D11_PS_CS_UAV_REGISTER_COUNT; ++i) { ok(tmp_uav[i] == cs_uav[i], "Got unexpected unordered access view %p in slot %u, expected %p.\n", tmp_uav[i], i, cs_uav[i]); ID3D11UnorderedAccessView_Release(tmp_uav[i]); } ID3D11DeviceContext_IAGetVertexBuffers(context, 0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, tmp_buffer, stride, offset); for (i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; ++i) { todo_wine_if(i >= D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT) { ok(tmp_buffer[i] == buffer[i], "Got unexpected vertex buffer %p in slot %u, expected %p.\n", tmp_buffer[i], i, buffer[i]); ok(stride[i] == (i + 1) * 4, "Got unexpected stride %u in slot %u.\n", stride[i], i); ok(offset[i] == (i + 1) * 16, "Got unexpected offset %u in slot %u.\n", offset[i], i); } if (tmp_buffer[i]) ID3D11Buffer_Release(tmp_buffer[i]); } ID3D11DeviceContext_IAGetIndexBuffer(context, tmp_buffer, &format, offset); ok(tmp_buffer[0] == buffer[0], "Got unexpected index buffer %p, expected %p.\n", tmp_buffer[0], buffer[0]); ID3D11Buffer_Release(tmp_buffer[0]); ok(format == DXGI_FORMAT_R32_UINT, "Got unexpected index buffer format %#x.\n", format); ok(offset[0] == 16, "Got unexpected index buffer offset %u.\n", offset[0]); ID3D11DeviceContext_IAGetInputLayout(context, &tmp_input_layout); ok(tmp_input_layout == input_layout, "Got unexpected input layout %p, expected %p.\n", tmp_input_layout, input_layout); ID3D11InputLayout_Release(tmp_input_layout); ID3D11DeviceContext_IAGetPrimitiveTopology(context, &topology); ok(topology == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, "Got unexpected primitive topology %#x.\n", topology); ID3D11DeviceContext_OMGetBlendState(context, &tmp_blend_state, blend_factor, &sample_mask); ok(tmp_blend_state == blend_state, "Got unexpected blend state %p, expected %p.\n", tmp_blend_state, blend_state); ID3D11BlendState_Release(tmp_blend_state); ok(blend_factor[0] == 0.1f && blend_factor[1] == 0.2f && blend_factor[2] == 0.3f && blend_factor[3] == 0.4f, "Got unexpected blend factor {%.8e, %.8e, %.8e, %.8e}.\n", blend_factor[0], blend_factor[1], blend_factor[2], blend_factor[3]); ok(sample_mask == 0xff00ff00, "Got unexpected sample mask %#x.\n", sample_mask); ID3D11DeviceContext_OMGetDepthStencilState(context, &tmp_ds_state, &stencil_ref); ok(tmp_ds_state == ds_state, "Got unexpected depth stencil state %p, expected %p.\n", tmp_ds_state, ds_state); ID3D11DepthStencilState_Release(tmp_ds_state); ok(stencil_ref == 3, "Got unexpected stencil ref %u.\n", stencil_ref); ID3D11DeviceContext_OMGetRenderTargets(context, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, tmp_rtv, &tmp_dsv); for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT - 1; ++i) { ok(tmp_rtv[i] == rtv[i], "Got unexpected render target view %p in slot %u, expected %p.\n", tmp_rtv[i], i, rtv[i]); ID3D11RenderTargetView_Release(tmp_rtv[i]); } ok(!tmp_rtv[i], "Got unexpected render target view %p in slot %u.\n", tmp_rtv[i], i); ok(tmp_dsv == dsv, "Got unexpected depth stencil view %p, expected %p.\n", tmp_dsv, dsv); ID3D11DepthStencilView_Release(tmp_dsv); ID3D11DeviceContext_OMGetRenderTargetsAndUnorderedAccessViews(context, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, tmp_rtv, &tmp_dsv, 0, D3D11_PS_CS_UAV_REGISTER_COUNT, tmp_uav); for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT - 1; ++i) { ok(tmp_rtv[i] == rtv[i], "Got unexpected render target view %p in slot %u, expected %p.\n", tmp_rtv[i], i, rtv[i]); ID3D11RenderTargetView_Release(tmp_rtv[i]); } ok(!tmp_rtv[i], "Got unexpected render target view %p in slot %u.\n", tmp_rtv[i], i); ok(tmp_dsv == dsv, "Got unexpected depth stencil view %p, expected %p.\n", tmp_dsv, dsv); ID3D11DepthStencilView_Release(tmp_dsv); for (i = 0; i < D3D11_PS_CS_UAV_REGISTER_COUNT - 1; ++i) { ok(!tmp_uav[i], "Got unexpected unordered access view %p in slot %u.\n", tmp_uav[i], i); } ok(tmp_uav[i] == ps_uav, "Got unexpected unordered access view %p in slot %u, expected %p.\n", tmp_uav[i], i, ps_uav); ID3D11UnorderedAccessView_Release(tmp_uav[i]); ID3D11DeviceContext_RSGetScissorRects(context, &count, NULL); ok(count == D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE, "Got unexpected scissor rect count %u.\n", count); memset(tmp_rect, 0x55, sizeof(tmp_rect)); ID3D11DeviceContext_RSGetScissorRects(context, &count, tmp_rect); for (i = 0; i < count; ++i) { ok(tmp_rect[i].left == i && tmp_rect[i].top == i * 2 && tmp_rect[i].right == i + 1 && tmp_rect[i].bottom == (i + 1) * 2, "Got unexpected scissor rect %s in slot %u.\n", wine_dbgstr_rect(&tmp_rect[i]), i); } ID3D11DeviceContext_RSGetViewports(context, &count, NULL); ok(count == D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE, "Got unexpected viewport count %u.\n", count); memset(tmp_viewport, 0x55, sizeof(tmp_viewport)); ID3D11DeviceContext_RSGetViewports(context, &count, tmp_viewport); for (i = 0; i < count; ++i) { ok(tmp_viewport[i].TopLeftX == i * 3 && tmp_viewport[i].TopLeftY == i * 4 && tmp_viewport[i].Width == 3 && tmp_viewport[i].Height == 4 && compare_float(tmp_viewport[i].MinDepth, i * 0.01f, 16) && compare_float(tmp_viewport[i].MaxDepth, (i + 1) * 0.01f, 16), "Got unexpected viewport {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e} in slot %u.\n", tmp_viewport[i].TopLeftX, tmp_viewport[i].TopLeftY, tmp_viewport[i].Width, tmp_viewport[i].Height, tmp_viewport[i].MinDepth, tmp_viewport[i].MaxDepth, i); } ID3D11DeviceContext_RSGetState(context, &tmp_rs_state); ok(tmp_rs_state == rs_state, "Got unexpected rasterizer state %p, expected %p.\n", tmp_rs_state, rs_state); ID3D11RasterizerState_Release(tmp_rs_state); ID3D11DeviceContext_SOGetTargets(context, D3D11_SO_BUFFER_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; ++i) { ok(tmp_buffer[i] == so_buffer[i], "Got unexpected stream output %p in slot %u, expected %p.\n", tmp_buffer[i], i, so_buffer[i]); ID3D11Buffer_Release(tmp_buffer[i]); } ID3D11DeviceContext_GetPredication(context, &tmp_predicate, &predicate_value); ok(tmp_predicate == predicate, "Got unexpected predicate %p, expected %p.\n", tmp_predicate, predicate); ID3D11Predicate_Release(tmp_predicate); ok(predicate_value, "Got unexpected predicate value %#x.\n", predicate_value); /* Verify ClearState(). */ ID3D11DeviceContext_ClearState(context); ID3D11DeviceContext_VSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_VSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_VSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } ID3D11DeviceContext_VSGetShader(context, &tmp_vs, NULL, 0); ok(!tmp_vs, "Got unexpected vertex shader %p.\n", tmp_vs); ID3D11DeviceContext_HSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_HSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_HSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } ID3D11DeviceContext_HSGetShader(context, &tmp_hs, NULL, 0); ok(!tmp_hs, "Got unexpected hull shader %p.\n", tmp_hs); ID3D11DeviceContext_DSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_DSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_DSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } ID3D11DeviceContext_DSGetShader(context, &tmp_ds, NULL, 0); ok(!tmp_ds, "Got unexpected domain shader %p.\n", tmp_ds); ID3D11DeviceContext_GSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_GSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_GSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } ID3D11DeviceContext_GSGetShader(context, &tmp_gs, NULL, 0); ok(!tmp_gs, "Got unexpected geometry shader %p.\n", tmp_gs); ID3D11DeviceContext_PSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_PSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_PSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } ID3D11DeviceContext_PSGetShader(context, &tmp_ps, NULL, 0); ok(!tmp_ps, "Got unexpected pixel shader %p.\n", tmp_ps); ID3D11DeviceContext_CSGetConstantBuffers(context, 0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected constant buffer %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_CSGetShaderResources(context, 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, tmp_srv); for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_srv[i], "Got unexpected shader resource view %p in slot %u.\n", tmp_srv[i], i); } ID3D11DeviceContext_CSGetSamplers(context, 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, tmp_sampler); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ok(!tmp_sampler[i], "Got unexpected sampler %p in slot %u.\n", tmp_sampler[i], i); } ID3D11DeviceContext_CSGetShader(context, &tmp_cs, NULL, 0); ok(!tmp_cs, "Got unexpected compute shader %p.\n", tmp_cs); ID3D11DeviceContext_CSGetUnorderedAccessViews(context, 0, D3D11_PS_CS_UAV_REGISTER_COUNT, tmp_uav); for (i = 0; i < D3D11_PS_CS_UAV_REGISTER_COUNT; ++i) { ok(!tmp_uav[i], "Got unexpected unordered access view %p in slot %u.\n", tmp_uav[i], i); } ID3D11DeviceContext_IAGetVertexBuffers(context, 0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, tmp_buffer, stride, offset); for (i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected vertex buffer %p in slot %u.\n", tmp_buffer[i], i); ok(!stride[i], "Got unexpected stride %u in slot %u.\n", stride[i], i); ok(!offset[i], "Got unexpected offset %u in slot %u.\n", offset[i], i); } ID3D11DeviceContext_IAGetIndexBuffer(context, tmp_buffer, &format, offset); ok(!tmp_buffer[0], "Got unexpected index buffer %p.\n", tmp_buffer[0]); ok(format == DXGI_FORMAT_UNKNOWN, "Got unexpected index buffer format %#x.\n", format); ok(!offset[0], "Got unexpected index buffer offset %u.\n", offset[0]); ID3D11DeviceContext_IAGetInputLayout(context, &tmp_input_layout); ok(!tmp_input_layout, "Got unexpected input layout %p.\n", tmp_input_layout); ID3D11DeviceContext_IAGetPrimitiveTopology(context, &topology); ok(topology == D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED, "Got unexpected primitive topology %#x.\n", topology); ID3D11DeviceContext_OMGetBlendState(context, &tmp_blend_state, blend_factor, &sample_mask); ok(!tmp_blend_state, "Got unexpected blend state %p.\n", tmp_blend_state); ok(blend_factor[0] == 1.0f && blend_factor[1] == 1.0f && blend_factor[2] == 1.0f && blend_factor[3] == 1.0f, "Got unexpected blend factor {%.8e, %.8e, %.8e, %.8e}.\n", blend_factor[0], blend_factor[1], blend_factor[2], blend_factor[3]); ok(sample_mask == D3D11_DEFAULT_SAMPLE_MASK, "Got unexpected sample mask %#x.\n", sample_mask); ID3D11DeviceContext_OMGetDepthStencilState(context, &tmp_ds_state, &stencil_ref); ok(!tmp_ds_state, "Got unexpected depth stencil state %p.\n", tmp_ds_state); ok(!stencil_ref, "Got unexpected stencil ref %u.\n", stencil_ref); ID3D11DeviceContext_OMGetRenderTargets(context, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, tmp_rtv, &tmp_dsv); for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) { ok(!tmp_rtv[i], "Got unexpected render target view %p in slot %u.\n", tmp_rtv[i], i); } ok(!tmp_dsv, "Got unexpected depth stencil view %p.\n", tmp_dsv); ID3D11DeviceContext_OMGetRenderTargetsAndUnorderedAccessViews(context, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, tmp_rtv, &tmp_dsv, 0, D3D11_PS_CS_UAV_REGISTER_COUNT, tmp_uav); for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) { ok(!tmp_rtv[i], "Got unexpected render target view %p in slot %u.\n", tmp_rtv[i], i); } ok(!tmp_dsv, "Got unexpected depth stencil view %p.\n", tmp_dsv); for (i = 0; i < D3D11_PS_CS_UAV_REGISTER_COUNT; ++i) { ok(!tmp_uav[i], "Got unexpected unordered access view %p in slot %u.\n", tmp_uav[i], i); } ID3D11DeviceContext_RSGetScissorRects(context, &count, NULL); ok(!count, "Got unexpected scissor rect count %u.\n", count); memset(tmp_rect, 0x55, sizeof(tmp_rect)); count = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ID3D11DeviceContext_RSGetScissorRects(context, &count, tmp_rect); for (i = 0; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ++i) { ok(!tmp_rect[i].left && !tmp_rect[i].top && !tmp_rect[i].right && !tmp_rect[i].bottom, "Got unexpected scissor rect %s in slot %u.\n", wine_dbgstr_rect(&tmp_rect[i]), i); } ID3D11DeviceContext_RSGetViewports(context, &count, NULL); ok(!count, "Got unexpected viewport count %u.\n", count); memset(tmp_viewport, 0x55, sizeof(tmp_viewport)); count = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ID3D11DeviceContext_RSGetViewports(context, &count, tmp_viewport); for (i = 0; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ++i) { ok(!tmp_viewport[i].TopLeftX && !tmp_viewport[i].TopLeftY && !tmp_viewport[i].Width && !tmp_viewport[i].Height && !tmp_viewport[i].MinDepth && !tmp_viewport[i].MaxDepth, "Got unexpected viewport {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e} in slot %u.\n", tmp_viewport[i].TopLeftX, tmp_viewport[i].TopLeftY, tmp_viewport[i].Width, tmp_viewport[i].Height, tmp_viewport[i].MinDepth, tmp_viewport[i].MaxDepth, i); } ID3D11DeviceContext_RSGetState(context, &tmp_rs_state); ok(!tmp_rs_state, "Got unexpected rasterizer state %p.\n", tmp_rs_state); ID3D11DeviceContext_SOGetTargets(context, D3D11_SO_BUFFER_SLOT_COUNT, tmp_buffer); for (i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; ++i) { ok(!tmp_buffer[i], "Got unexpected stream output %p in slot %u.\n", tmp_buffer[i], i); } ID3D11DeviceContext_GetPredication(context, &tmp_predicate, &predicate_value); ok(!tmp_predicate, "Got unexpected predicate %p.\n", tmp_predicate); ok(!predicate_value, "Got unexpected predicate value %#x.\n", predicate_value); /* Cleanup. */ ID3D11Predicate_Release(predicate); ID3D11RasterizerState_Release(rs_state); ID3D11DepthStencilView_Release(dsv); ID3D11Texture2D_Release(ds_texture); for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) { ID3D11RenderTargetView_Release(rtv[i]); ID3D11Texture2D_Release(rt_texture[i]); } ID3D11DepthStencilState_Release(ds_state); ID3D11BlendState_Release(blend_state); ID3D11InputLayout_Release(input_layout); ID3D11VertexShader_Release(vs); ID3D11HullShader_Release(hs); ID3D11DomainShader_Release(ds); ID3D11GeometryShader_Release(gs); ID3D11PixelShader_Release(ps); ID3D11ComputeShader_Release(cs); for (i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) { ID3D11SamplerState_Release(sampler[i]); } for (i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i) { ID3D11ShaderResourceView_Release(srv[i]); } for (i = 0; i < D3D11_PS_CS_UAV_REGISTER_COUNT; ++i) { ID3D11UnorderedAccessView_Release(cs_uav[i]); ID3D11Buffer_Release(cs_uav_buffer[i]); } ID3D11UnorderedAccessView_Release(ps_uav); ID3D11Buffer_Release(ps_uav_buffer); for (i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; ++i) { ID3D11Buffer_Release(so_buffer[i]); } for (i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; ++i) { ID3D11Buffer_Release(buffer[i]); } for (i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; ++i) { ID3D11Buffer_Release(cb[i]); } ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_il_append_aligned(void) { struct d3d11_test_context test_context; ID3D11InputLayout *input_layout; ID3D11DeviceContext *context; unsigned int stride, offset; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *vb[3]; DWORD color; HRESULT hr; /* Semantic names are case-insensitive. */ static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"CoLoR", 2, DXGI_FORMAT_R32G32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 2}, {"ColoR", 3, DXGI_FORMAT_R32G32_FLOAT, 2, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1}, {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"ColoR", 0, DXGI_FORMAT_R32G32_FLOAT, 2, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1}, {"cOLOr", 1, DXGI_FORMAT_R32G32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 2}, }; static const DWORD vs_code[] = { #if 0 struct vs_in { float4 position : POSITION; float2 color_xy : COLOR0; float2 color_zw : COLOR1; unsigned int instance_id : SV_INSTANCEID; }; struct vs_out { float4 position : SV_POSITION; float2 color_xy : COLOR0; float2 color_zw : COLOR1; }; struct vs_out main(struct vs_in i) { struct vs_out o; o.position = i.position; o.position.x += i.instance_id * 0.5; o.color_xy = i.color_xy; o.color_zw = i.color_zw; return o; } #endif 0x43425844, 0x52e3bf46, 0x6300403d, 0x624cffe4, 0xa4fc0013, 0x00000001, 0x00000214, 0x00000003, 0x0000002c, 0x000000bc, 0x00000128, 0x4e475349, 0x00000088, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000071, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000071, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000303, 0x00000077, 0x00000000, 0x00000008, 0x00000001, 0x00000003, 0x00000101, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0x5300524f, 0x4e495f56, 0x4e415453, 0x44494543, 0xababab00, 0x4e47534f, 0x00000064, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000c03, 0x0000005c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000030c, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x000000e4, 0x00010040, 0x00000039, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x04000060, 0x00101012, 0x00000003, 0x00000008, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102032, 0x00000001, 0x03000065, 0x001020c2, 0x00000001, 0x02000068, 0x00000001, 0x05000056, 0x00100012, 0x00000000, 0x0010100a, 0x00000003, 0x09000032, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f000000, 0x0010100a, 0x00000000, 0x05000036, 0x001020e2, 0x00000000, 0x00101e56, 0x00000000, 0x05000036, 0x00102032, 0x00000001, 0x00101046, 0x00000001, 0x05000036, 0x001020c2, 0x00000001, 0x00101406, 0x00000002, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 struct vs_out { float4 position : SV_POSITION; float2 color_xy : COLOR0; float2 color_zw : COLOR1; }; float4 main(struct vs_out i) : SV_TARGET { return float4(i.color_xy.xy, i.color_zw.xy); } #endif 0x43425844, 0x64e48a09, 0xaa484d46, 0xe40a6e78, 0x9885edf3, 0x00000001, 0x00000118, 0x00000003, 0x0000002c, 0x00000098, 0x000000cc, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x0000005c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x00000c0c, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000044, 0x00000040, 0x00000011, 0x03001062, 0x00101032, 0x00000001, 0x03001062, 0x001010c2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const struct { struct vec4 position; } stream0[] = { {{-1.0f, -1.0f, 0.0f, 1.0f}}, {{-1.0f, 1.0f, 0.0f, 1.0f}}, {{-0.5f, -1.0f, 0.0f, 1.0f}}, {{-0.5f, 1.0f, 0.0f, 1.0f}}, }; static const struct { struct vec2 color2; struct vec2 color1; } stream1[] = { {{0.5f, 0.5f}, {0.0f, 1.0f}}, {{0.5f, 0.5f}, {1.0f, 1.0f}}, }; static const struct { struct vec2 color3; struct vec2 color0; } stream2[] = { {{0.5f, 0.5f}, {1.0f, 0.0f}}, {{0.5f, 0.5f}, {0.0f, 1.0f}}, {{0.5f, 0.5f}, {0.0f, 0.0f}}, {{0.5f, 0.5f}, {1.0f, 0.0f}}, }; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); vb[0] = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(stream0), stream0); vb[1] = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(stream1), stream1); vb[2] = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(stream2), stream2); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); offset = 0; stride = sizeof(*stream0); ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb[0], &stride, &offset); stride = sizeof(*stream1); ID3D11DeviceContext_IASetVertexBuffers(context, 1, 1, &vb[1], &stride, &offset); stride = sizeof(*stream2); ID3D11DeviceContext_IASetVertexBuffers(context, 2, 1, &vb[2], &stride, &offset); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); ID3D11DeviceContext_DrawInstanced(context, 4, 4, 0, 0); color = get_texture_color(test_context.backbuffer, 80, 240); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 240, 240); ok(compare_color(color, 0xff00ff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 400, 240); ok(compare_color(color, 0xffff0000, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 560, 240); ok(compare_color(color, 0xffff00ff, 1), "Got unexpected color 0x%08x.\n", color); ID3D11PixelShader_Release(ps); ID3D11VertexShader_Release(vs); ID3D11Buffer_Release(vb[2]); ID3D11Buffer_Release(vb[1]); ID3D11Buffer_Release(vb[0]); ID3D11InputLayout_Release(input_layout); release_test_context(&test_context); } static void test_instance_id(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11InputLayout *input_layout; ID3D11RenderTargetView *rtvs[2]; ID3D11Texture2D *render_target; ID3D11DeviceContext *context; struct resource_readback rb; unsigned int stride, offset; ID3D11Buffer *args_buffer; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *vb[2]; unsigned int i; HRESULT hr; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"color", 0, DXGI_FORMAT_R8_UNORM, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1}, {"v_offset", 0, DXGI_FORMAT_R32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1}, }; static const DWORD vs_code[] = { #if 0 struct vs_in { float4 position : Position; float color : Color; float v_offset : V_Offset; uint instance_id : SV_InstanceId; }; struct vs_out { float4 position : SV_Position; float color : Color; uint instance_id : InstanceId; }; void main(vs_in i, out vs_out o) { o.position = i.position; o.position.x += i.v_offset; o.color = i.color; o.instance_id = i.instance_id; } #endif 0x43425844, 0xcde3cfbf, 0xe2e3d090, 0xe2eb1038, 0x7e5ad1cf, 0x00000001, 0x00000204, 0x00000003, 0x0000002c, 0x000000c4, 0x0000013c, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000071, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000101, 0x00000077, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000101, 0x00000080, 0x00000000, 0x00000008, 0x00000001, 0x00000003, 0x00000101, 0x69736f50, 0x6e6f6974, 0x6c6f4300, 0x5600726f, 0x66664f5f, 0x00746573, 0x495f5653, 0x6174736e, 0x4965636e, 0xabab0064, 0x4e47534f, 0x00000070, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000e01, 0x00000062, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000e01, 0x505f5653, 0x7469736f, 0x006e6f69, 0x6f6c6f43, 0x6e490072, 0x6e617473, 0x64496563, 0xababab00, 0x52444853, 0x000000c0, 0x00010040, 0x00000030, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x00101012, 0x00000001, 0x0300005f, 0x00101012, 0x00000002, 0x04000060, 0x00101012, 0x00000003, 0x00000008, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000001, 0x03000065, 0x00102012, 0x00000002, 0x07000000, 0x00102012, 0x00000000, 0x0010100a, 0x00000000, 0x0010100a, 0x00000002, 0x05000036, 0x001020e2, 0x00000000, 0x00101e56, 0x00000000, 0x05000036, 0x00102012, 0x00000001, 0x0010100a, 0x00000001, 0x05000036, 0x00102012, 0x00000002, 0x0010100a, 0x00000003, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 struct vs_out { float4 position : SV_Position; float color : Color; uint instance_id : InstanceId; }; void main(vs_out i, out float4 o0 : SV_Target0, out uint4 o1 : SV_Target1) { o0 = float4(i.color, i.color, i.color, 1.0f); o1 = i.instance_id; } #endif 0x43425844, 0xda0ad0bb, 0x4743f5f5, 0xfbc6d0b1, 0x7c8e7df5, 0x00000001, 0x00000170, 0x00000003, 0x0000002c, 0x000000a4, 0x000000f0, 0x4e475349, 0x00000070, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000101, 0x00000062, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000101, 0x505f5653, 0x7469736f, 0x006e6f69, 0x6f6c6f43, 0x6e490072, 0x6e617473, 0x64496563, 0xababab00, 0x4e47534f, 0x00000044, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000038, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000078, 0x00000040, 0x0000001e, 0x03001062, 0x00101012, 0x00000001, 0x03000862, 0x00101012, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x00102072, 0x00000000, 0x00101006, 0x00000001, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x3f800000, 0x05000036, 0x001020f2, 0x00000001, 0x00101006, 0x00000002, 0x0100003e, }; static const struct vec4 stream0[] = { {-1.00f, 0.0f, 0.0f, 1.0f}, {-1.00f, 1.0f, 0.0f, 1.0f}, {-0.75f, 0.0f, 0.0f, 1.0f}, {-0.75f, 1.0f, 0.0f, 1.0f}, /* indirect draws data */ {-1.00f, -1.0f, 0.0f, 1.0f}, {-1.00f, 0.0f, 0.0f, 1.0f}, {-0.75f, -1.0f, 0.0f, 1.0f}, {-0.75f, 0.0f, 0.0f, 1.0f}, }; static const struct { BYTE color; float v_offset; } stream1[] = { {0xf0, 0.00f}, {0x80, 0.25f}, {0x10, 0.50f}, {0x40, 0.75f}, {0xaa, 1.00f}, {0xbb, 1.25f}, {0xcc, 1.50f}, {0x90, 1.75f}, }; static const D3D11_DRAW_INSTANCED_INDIRECT_ARGS argument_data[] = { {4, 4, 4, 0}, {4, 4, 4, 4}, }; static const struct { RECT rect; unsigned int color; unsigned int instance_id; } expected_results[] = { {{ 0, 0, 80, 240}, 0xfff0f0f0, 0}, {{ 80, 0, 160, 240}, 0xff808080, 1}, {{160, 0, 240, 240}, 0xff101010, 2}, {{240, 0, 320, 240}, 0xff404040, 3}, {{320, 0, 400, 240}, 0xffaaaaaa, 0}, {{400, 0, 480, 240}, 0xffbbbbbb, 1}, {{480, 0, 560, 240}, 0xffcccccc, 2}, {{560, 0, 640, 240}, 0xff909090, 3}, /* indirect draws results */ {{ 0, 240, 80, 480}, 0xfff0f0f0, 0}, {{ 80, 240, 160, 480}, 0xff808080, 1}, {{160, 240, 240, 480}, 0xff101010, 2}, {{240, 240, 320, 480}, 0xff404040, 3}, {{320, 240, 400, 480}, 0xffaaaaaa, 0}, {{400, 240, 480, 480}, 0xffbbbbbb, 1}, {{480, 240, 560, 480}, 0xffcccccc, 2}, {{560, 240, 640, 480}, 0xff909090, 3}, }; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; rtvs[0] = test_context.backbuffer_rtv; ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_R32_UINT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &render_target); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)render_target, NULL, &rtvs[1]); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); vb[0] = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(stream0), stream0); vb[1] = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(stream1), stream1); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); offset = 0; stride = sizeof(*stream0); ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb[0], &stride, &offset); stride = sizeof(*stream1); ID3D11DeviceContext_IASetVertexBuffers(context, 1, 1, &vb[1], &stride, &offset); ID3D11DeviceContext_ClearRenderTargetView(context, rtvs[0], white); ID3D11DeviceContext_ClearRenderTargetView(context, rtvs[1], white); ID3D11DeviceContext_OMSetRenderTargets(context, ARRAY_SIZE(rtvs), rtvs, NULL); ID3D11DeviceContext_DrawInstanced(context, 4, 4, 0, 0); ID3D11DeviceContext_DrawInstanced(context, 4, 4, 0, 4); args_buffer = create_buffer_misc(device, 0, D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS, sizeof(argument_data), argument_data); ID3D11DeviceContext_DrawInstancedIndirect(context, args_buffer, 0); ID3D11DeviceContext_DrawInstancedIndirect(context, args_buffer, sizeof(*argument_data)); get_texture_readback(test_context.backbuffer, 0, &rb); for (i = 0; i < ARRAY_SIZE(expected_results); ++i) check_readback_data_color(&rb, &expected_results[i].rect, expected_results[i].color, 1); release_resource_readback(&rb); get_texture_readback(render_target, 0, &rb); for (i = 0; i < ARRAY_SIZE(expected_results); ++i) check_readback_data_color(&rb, &expected_results[i].rect, expected_results[i].instance_id, 0); release_resource_readback(&rb); ID3D11Buffer_Release(vb[0]); ID3D11Buffer_Release(vb[1]); ID3D11Buffer_Release(args_buffer); ID3D11RenderTargetView_Release(rtvs[1]); ID3D11Texture2D_Release(render_target); ID3D11VertexShader_Release(vs); ID3D11PixelShader_Release(ps); ID3D11InputLayout_Release(input_layout); release_test_context(&test_context); } static void test_vertex_id(void) { static const DWORD vs_code[] = { #if 0 uint4 main(uint id : ID, uint instance_id : SV_InstanceID, uint vertex_id : SV_VertexID) : OUTPUT { return uint4(id, instance_id, vertex_id, 0); } #endif 0x43425844, 0x5625197b, 0x588ccf8f, 0x48694905, 0x961d19ca, 0x00000001, 0x00000170, 0x00000003, 0x0000002c, 0x000000a4, 0x000000d4, 0x4e475349, 0x00000070, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000101, 0x00000053, 0x00000000, 0x00000008, 0x00000001, 0x00000001, 0x00000101, 0x00000061, 0x00000000, 0x00000006, 0x00000001, 0x00000002, 0x00000101, 0x53004449, 0x6e495f56, 0x6e617473, 0x44496563, 0x5f565300, 0x74726556, 0x44497865, 0xababab00, 0x4e47534f, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x5054554f, 0xab005455, 0x52444853, 0x00000094, 0x00010040, 0x00000025, 0x0300005f, 0x00101012, 0x00000000, 0x04000060, 0x00101012, 0x00000001, 0x00000008, 0x04000060, 0x00101012, 0x00000002, 0x00000006, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x00102012, 0x00000000, 0x0010100a, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010100a, 0x00000001, 0x05000036, 0x00102042, 0x00000000, 0x0010100a, 0x00000002, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x00000000, 0x0100003e, }; D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"ID", 0, DXGI_FORMAT_R32_UINT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const D3D11_SO_DECLARATION_ENTRY so_declaration[] = { {0, "OUTPUT", 0, 0, 4, 0}, }; static const unsigned int vertices[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 6, 7, }; static const unsigned int indices[] = { 6, 7, 8, 0, 1, 2, }; struct uvec4 expected_values[] = { {0, 0, 0}, {1, 0, 1}, {2, 0, 2}, {0, 1, 0}, {1, 1, 1}, {2, 1, 2}, {3, 0, 0}, {4, 0, 1}, {5, 0, 2}, {6, 0, 6}, {7, 0, 7}, {8, 0, 8}, {6, 1, 6}, {7, 1, 7}, {8, 1, 8}, {5, 0, 0}, {6, 0, 1}, {7, 0, 2}, }; BOOL found_values[ARRAY_SIZE(expected_values)] = {0}; BOOL used_values[ARRAY_SIZE(expected_values)] = {0}; struct d3d11_test_context test_context; D3D11_QUERY_DATA_SO_STATISTICS data; ID3D11Buffer *vb, *ib, *so_buffer; ID3D11InputLayout *input_layout; ID3D11DeviceContext *context; D3D11_QUERY_DESC query_desc; struct resource_readback rb; unsigned int stride, offset; ID3D11Asynchronous *query; ID3D11GeometryShader *gs; ID3D11VertexShader *vs; ID3D11Device *device; unsigned int count; unsigned int i, j; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; query_desc.Query = D3D11_QUERY_SO_STATISTICS; query_desc.MiscFlags = 0; hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)&query); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(hr == S_OK, "Failed to create input layout, hr %#x.\n", hr); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(hr == S_OK, "Failed to create vertex shader, hr %#x.\n", hr); stride = 16; hr = ID3D11Device_CreateGeometryShaderWithStreamOutput(device, vs_code, sizeof(vs_code), so_declaration, ARRAY_SIZE(so_declaration), &stride, 1, 0, NULL, &gs); ok(hr == S_OK, "Failed to create geometry shader with stream output, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(vertices), vertices); ib = create_buffer(device, D3D11_BIND_INDEX_BUFFER, sizeof(indices), indices); so_buffer = create_buffer(device, D3D11_BIND_STREAM_OUTPUT, 1024, NULL); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); ID3D11DeviceContext_IASetIndexBuffer(context, ib, DXGI_FORMAT_R32_UINT, 0); offset = 0; stride = sizeof(*vertices); ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, &stride, &offset); offset = 0; ID3D11DeviceContext_SOSetTargets(context, 1, &so_buffer, &offset); ID3D11DeviceContext_Begin(context, query); ID3D11DeviceContext_DrawInstanced(context, 3, 2, 0, 0); ID3D11DeviceContext_DrawInstanced(context, 3, 1, 3, 16); ID3D11DeviceContext_DrawIndexedInstanced(context, 3, 2, 0, 0, 0); ID3D11DeviceContext_DrawIndexedInstanced(context, 3, 1, 3, 9, 7); ID3D11DeviceContext_End(context, query); get_query_data(context, query, &data, sizeof(data)); count = data.NumPrimitivesWritten; ok(count == ARRAY_SIZE(expected_values), "Got unexpected value %u.\n", count); count = min(count, ARRAY_SIZE(used_values)); get_buffer_readback(so_buffer, &rb); for (i = 0; i < ARRAY_SIZE(expected_values); ++i) { for (j = 0; j < count; ++j) { if (!used_values[j] && compare_uvec4(get_readback_uvec4(&rb, j, 0), &expected_values[i])) { found_values[i] = TRUE; used_values[j] = TRUE; break; } } } for (i = 0; i < count; ++i) { const struct uvec4 *v = get_readback_uvec4(&rb, i, 0); ok(used_values[i], "Found unexpected value {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n", v->x, v->y, v->z, v->w); } release_resource_readback(&rb); for (i = 0; i < ARRAY_SIZE(expected_values); ++i) { ok(found_values[i], "Failed to find value {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n", expected_values[i].x, expected_values[i].y, expected_values[i].z, expected_values[i].w); } ID3D11Asynchronous_Release(query); ID3D11Buffer_Release(so_buffer); ID3D11Buffer_Release(vb); ID3D11Buffer_Release(ib); ID3D11GeometryShader_Release(gs); ID3D11VertexShader_Release(vs); ID3D11InputLayout_Release(input_layout); release_test_context(&test_context); } static void test_fragment_coords(void) { struct d3d11_test_context test_context; ID3D11PixelShader *ps, *ps_frac; ID3D11DeviceContext *context; ID3D11Device *device; ID3D11Buffer *ps_cb; DWORD color; HRESULT hr; static const DWORD ps_code[] = { #if 0 float2 cutoff; float4 main(float4 position : SV_POSITION) : SV_TARGET { float4 ret = float4(0.0, 0.0, 0.0, 1.0); if (position.x > cutoff.x) ret.y = 1.0; if (position.y > cutoff.y) ret.z = 1.0; return ret; } #endif 0x43425844, 0x49fc9e51, 0x8068867d, 0xf20cfa39, 0xb8099e6b, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x000000a8, 0x00000040, 0x0000002a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x08000031, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0a000001, 0x00102062, 0x00000000, 0x00100106, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x08000036, 0x00102092, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, }; static const DWORD ps_frac_code[] = { #if 0 float4 main(float4 position : SV_POSITION) : SV_TARGET { return float4(frac(position.xy), 0.0, 1.0); } #endif 0x43425844, 0x86d9d78a, 0x190b72c2, 0x50841fd6, 0xdc24022e, 0x00000001, 0x000000f8, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x0000005c, 0x00000040, 0x00000017, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x0500001a, 0x00102032, 0x00000000, 0x00101046, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, }; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; struct vec4 cutoff = {320.0f, 240.0f, 0.0f, 0.0f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; ps_cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(cutoff), &cutoff); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_frac_code, sizeof(ps_frac_code), NULL, &ps_frac); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &ps_cb); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); draw_quad(&test_context); color = get_texture_color(test_context.backbuffer, 319, 239); ok(compare_color(color, 0xff000000, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 320, 239); ok(compare_color(color, 0xff00ff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 319, 240); ok(compare_color(color, 0xffff0000, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 320, 240); ok(compare_color(color, 0xffffff00, 1), "Got unexpected color 0x%08x.\n", color); ID3D11Buffer_Release(ps_cb); cutoff.x = 16.0f; cutoff.y = 16.0f; ps_cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(cutoff), &cutoff); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &ps_cb); draw_quad(&test_context); color = get_texture_color(test_context.backbuffer, 14, 14); ok(compare_color(color, 0xff000000, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 18, 14); ok(compare_color(color, 0xff00ff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 14, 18); ok(compare_color(color, 0xffff0000, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(test_context.backbuffer, 18, 18); ok(compare_color(color, 0xffffff00, 1), "Got unexpected color 0x%08x.\n", color); ID3D11DeviceContext_PSSetShader(context, ps_frac, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); ID3D11DeviceContext_Draw(context, 4, 0); color = get_texture_color(test_context.backbuffer, 14, 14); ok(compare_color(color, 0xff008080, 1), "Got unexpected color 0x%08x.\n", color); ID3D11Buffer_Release(ps_cb); ID3D11PixelShader_Release(ps_frac); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_initial_texture_data(void) { ID3D11Texture2D *texture, *staging_texture; struct d3d11_test_context test_context; D3D11_SUBRESOURCE_DATA resource_data; D3D11_TEXTURE2D_DESC texture_desc; ID3D11SamplerState *sampler_state; ID3D11ShaderResourceView *ps_srv; D3D11_SAMPLER_DESC sampler_desc; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, j; DWORD color; HRESULT hr; static const DWORD ps_code[] = { #if 0 Texture2D t; SamplerState s; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; return t.Sample(s, p); } #endif 0x43425844, 0x1ce9b612, 0xc8176faa, 0xd37844af, 0xdb515605, 0x00000001, 0x00000134, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040, 0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, }; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; static const DWORD bitmap_data[] = { 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff00ff00, 0xff0000ff, 0xff00ffff, 0x00000000, 0xffffff00, 0xffff0000, 0xffff00ff, 0x00000000, 0xff000000, 0xff7f7f7f, 0xffffffff, 0x00000000, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 4; texture_desc.Height = 4; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_STAGING; texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; texture_desc.BindFlags = 0; texture_desc.MiscFlags = 0; resource_data.pSysMem = bitmap_data; resource_data.SysMemPitch = texture_desc.Width * sizeof(*bitmap_data); resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &staging_texture); ok(hr == S_OK, "Failed to create 2d texture, hr %#x.\n", hr); texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.CPUAccessFlags = 0; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Failed to create 2d texture, hr %#x.\n", hr); ID3D11DeviceContext_CopyResource(context, (ID3D11Resource *)texture, (ID3D11Resource *)staging_texture); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &ps_srv); ok(hr == S_OK, "Failed to create shader resource view, hr %#x.\n", hr); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = 0.0f; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler_state); ok(hr == S_OK, "Failed to create sampler state, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &ps_srv); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler_state); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { color = get_readback_color(&rb, 80 + j * 160, 60 + i * 120, 0); ok(compare_color(color, bitmap_data[j + i * 4], 1), "Got color 0x%08x at (%u, %u), expected 0x%08x.\n", color, j, i, bitmap_data[j + i * 4]); } } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); ID3D11SamplerState_Release(sampler_state); ID3D11ShaderResourceView_Release(ps_srv); ID3D11Texture2D_Release(staging_texture); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_update_subresource(void) { struct d3d11_test_context test_context; D3D11_SUBRESOURCE_DATA resource_data; D3D11_TEXTURE2D_DESC texture_desc; ID3D11SamplerState *sampler_state; ID3D11ShaderResourceView *ps_srv; D3D11_SAMPLER_DESC sampler_desc; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, j; D3D11_BOX box; DWORD color; HRESULT hr; static const DWORD ps_code[] = { #if 0 Texture2D t; SamplerState s; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; return t.Sample(s, p); } #endif 0x43425844, 0x1ce9b612, 0xc8176faa, 0xd37844af, 0xdb515605, 0x00000001, 0x00000134, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040, 0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, }; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; static const DWORD initial_data[16] = {0}; static const DWORD bitmap_data[] = { 0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00, 0xffff0000, 0xffff00ff, 0xff000000, 0xff7f7f7f, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, }; static const DWORD expected_colors[] = { 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff00ff00, 0xff0000ff, 0xff00ffff, 0x00000000, 0xffffff00, 0xffff0000, 0xffff00ff, 0x00000000, 0xff000000, 0xff7f7f7f, 0xffffffff, 0x00000000, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 4; texture_desc.Height = 4; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; resource_data.pSysMem = initial_data; resource_data.SysMemPitch = texture_desc.Width * sizeof(*initial_data); resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &texture); ok(SUCCEEDED(hr), "Failed to create 2d texture, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &ps_srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = 0.0f; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler_state); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &ps_srv); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler_state); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); check_texture_color(test_context.backbuffer, 0x7f0000ff, 1); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0x00000000, 0); set_box(&box, 1, 1, 0, 3, 3, 1); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, 0, &box, bitmap_data, 4 * sizeof(*bitmap_data), 0); set_box(&box, 0, 3, 0, 3, 4, 1); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, 0, &box, &bitmap_data[6], 4 * sizeof(*bitmap_data), 0); set_box(&box, 0, 0, 0, 4, 1, 1); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, 0, &box, &bitmap_data[10], 4 * sizeof(*bitmap_data), 0); set_box(&box, 0, 1, 0, 1, 3, 1); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, 0, &box, &bitmap_data[2], sizeof(*bitmap_data), 0); set_box(&box, 4, 4, 0, 3, 1, 1); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, 0, &box, bitmap_data, sizeof(*bitmap_data), 0); set_box(&box, 0, 0, 0, 4, 4, 0); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, 0, &box, bitmap_data, 4 * sizeof(*bitmap_data), 0); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { color = get_readback_color(&rb, 80 + j * 160, 60 + i * 120, 0); ok(compare_color(color, expected_colors[j + i * 4], 1), "Got color 0x%08x at (%u, %u), expected 0x%08x.\n", color, j, i, expected_colors[j + i * 4]); } } release_resource_readback(&rb); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, 0, NULL, bitmap_data, 4 * sizeof(*bitmap_data), 0); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { color = get_readback_color(&rb, 80 + j * 160, 60 + i * 120, 0); ok(compare_color(color, bitmap_data[j + i * 4], 1), "Got color 0x%08x at (%u, %u), expected 0x%08x.\n", color, j, i, bitmap_data[j + i * 4]); } } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); ID3D11SamplerState_Release(sampler_state); ID3D11ShaderResourceView_Release(ps_srv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_copy_subresource_region(void) { ID3D11Texture2D *dst_texture, *src_texture; struct d3d11_test_context test_context; ID3D11Buffer *dst_buffer, *src_buffer; D3D11_SUBRESOURCE_DATA resource_data; D3D11_TEXTURE2D_DESC texture_desc; ID3D11SamplerState *sampler_state; ID3D11ShaderResourceView *ps_srv; D3D11_SAMPLER_DESC sampler_desc; ID3D11DeviceContext1 *context1; ID3D11DeviceContext *context; struct vec4 float_colors[16]; struct resource_readback rb; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, j; D3D11_BOX box; DWORD color; HRESULT hr; static const DWORD ps_code[] = { #if 0 Texture2D t; SamplerState s; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; return t.Sample(s, p); } #endif 0x43425844, 0x1ce9b612, 0xc8176faa, 0xd37844af, 0xdb515605, 0x00000001, 0x00000134, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040, 0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, }; static const DWORD ps_buffer_code[] = { #if 0 float4 buffer[16]; float4 main(float4 position : SV_POSITION) : SV_TARGET { float2 p = (float2)4; p *= float2(position.x / 640.0f, position.y / 480.0f); return buffer[(int)p.y * 4 + (int)p.x]; } #endif 0x43425844, 0x57e7139f, 0x4f0c9e52, 0x598b77e3, 0x5a239132, 0x00000001, 0x0000016c, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x000000d0, 0x00000040, 0x00000034, 0x04000859, 0x00208e46, 0x00000000, 0x00000010, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101516, 0x00000000, 0x00004002, 0x3c088889, 0x3bcccccd, 0x00000000, 0x00000000, 0x0500001b, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x07000029, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000002, 0x0700001e, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010001a, 0x00000000, 0x07000036, 0x001020f2, 0x00000000, 0x04208e46, 0x00000000, 0x0010000a, 0x00000000, 0x0100003e, }; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; static const DWORD initial_data[16] = {0}; static const DWORD bitmap_data[] = { 0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00, 0xffff0000, 0xffff00ff, 0xff000000, 0xff7f7f7f, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, }; static const DWORD expected_colors[] = { 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffff00, 0xff0000ff, 0xff00ffff, 0x00000000, 0xff7f7f7f, 0xffff0000, 0xffff00ff, 0xff7f7f7f, 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 4; texture_desc.Height = 4; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; resource_data.pSysMem = initial_data; resource_data.SysMemPitch = texture_desc.Width * sizeof(*initial_data); resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &dst_texture); ok(SUCCEEDED(hr), "Failed to create 2d texture, hr %#x.\n", hr); texture_desc.Usage = D3D11_USAGE_IMMUTABLE; resource_data.pSysMem = bitmap_data; resource_data.SysMemPitch = texture_desc.Width * sizeof(*bitmap_data); resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &src_texture); ok(SUCCEEDED(hr), "Failed to create 2d texture, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)dst_texture, NULL, &ps_srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = 0.0f; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler_state); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &ps_srv); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler_state); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 1, 1, 0, NULL, 0, &box); ID3D11DeviceContext_CopySubresourceRegion(context, NULL, 0, 1, 1, 0, (ID3D11Resource *)src_texture, 0, &box); set_box(&box, 0, 0, 0, 2, 2, 1); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 1, 1, 0, (ID3D11Resource *)src_texture, 0, &box); set_box(&box, 1, 2, 0, 4, 3, 1); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 0, 3, 0, (ID3D11Resource *)src_texture, 0, &box); set_box(&box, 0, 3, 0, 4, 4, 1); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 0, 0, 0, (ID3D11Resource *)src_texture, 0, &box); set_box(&box, 3, 0, 0, 4, 2, 1); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 0, 1, 0, (ID3D11Resource *)src_texture, 0, &box); set_box(&box, 3, 1, 0, 4, 2, 1); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 3, 2, 0, (ID3D11Resource *)src_texture, 0, &box); set_box(&box, 0, 0, 0, 4, 4, 0); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 0, 0, 0, (ID3D11Resource *)src_texture, 0, &box); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { color = get_readback_color(&rb, 80 + j * 160, 60 + i * 120, 0); ok(compare_color(color, expected_colors[j + i * 4], 1), "Got color 0x%08x at (%u, %u), expected 0x%08x.\n", color, j, i, expected_colors[j + i * 4]); } } release_resource_readback(&rb); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 0, 0, 0, (ID3D11Resource *)src_texture, 0, NULL); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { color = get_readback_color(&rb, 80 + j * 160, 60 + i * 120, 0); ok(compare_color(color, bitmap_data[j + i * 4], 1), "Got color 0x%08x at (%u, %u), expected 0x%08x.\n", color, j, i, bitmap_data[j + i * 4]); } } release_resource_readback(&rb); hr = ID3D11DeviceContext_QueryInterface(context, &IID_ID3D11DeviceContext1, (void **)&context1); ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, "Failed to query ID3D11DeviceContext1, hr %#x.\n", hr); if (SUCCEEDED(hr)) { ID3D11DeviceContext1_ClearRenderTargetView(context1, test_context.backbuffer_rtv, red); check_texture_color(test_context.backbuffer, 0x800000ff, 2); memset(float_colors, 0, sizeof(float_colors)); for (i = 0; i < texture_desc.Width; ++i) ((unsigned int *)float_colors)[i] = 0x45454545; ID3D11DeviceContext1_UpdateSubresource1(context1, (ID3D11Resource *)dst_texture, 0, NULL, float_colors, 0, 0, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0x45454545, 1); ID3D11DeviceContext1_CopySubresourceRegion1(context1, (ID3D11Resource *)dst_texture, 0, 0, 0, 0, (ID3D11Resource *)src_texture, 0, NULL, 0); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { color = get_readback_color(&rb, 80 + j * 160, 60 + i * 120, 0); ok(compare_color(color, bitmap_data[j + i * 4], 1), "Got color 0x%08x at (%u, %u), expected 0x%08x.\n", color, j, i, bitmap_data[j + i * 4]); } } release_resource_readback(&rb); ID3D11DeviceContext1_Release(context1); } ID3D11PixelShader_Release(ps); hr = ID3D11Device_CreatePixelShader(device, ps_buffer_code, sizeof(ps_buffer_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11ShaderResourceView_Release(ps_srv); ps_srv = NULL; ID3D11SamplerState_Release(sampler_state); sampler_state = NULL; ID3D11Texture2D_Release(dst_texture); ID3D11Texture2D_Release(src_texture); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &ps_srv); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler_state); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); memset(float_colors, 0, sizeof(float_colors)); dst_buffer = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(float_colors), float_colors); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &dst_buffer); src_buffer = create_buffer(device, 0, 256 * sizeof(*float_colors), NULL); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { float_colors[j + i * 4].x = ((bitmap_data[j + i * 4] >> 0) & 0xff) / 255.0f; float_colors[j + i * 4].y = ((bitmap_data[j + i * 4] >> 8) & 0xff) / 255.0f; float_colors[j + i * 4].z = ((bitmap_data[j + i * 4] >> 16) & 0xff) / 255.0f; float_colors[j + i * 4].w = ((bitmap_data[j + i * 4] >> 24) & 0xff) / 255.0f; } } set_box(&box, 0, 0, 0, sizeof(float_colors), 1, 1); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)src_buffer, 0, &box, float_colors, 0, 0); set_box(&box, 0, 0, 0, sizeof(float_colors), 0, 1); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_buffer, 0, 0, 0, 0, (ID3D11Resource *)src_buffer, 0, &box); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0x00000000, 0); set_box(&box, 0, 0, 0, sizeof(float_colors), 1, 0); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_buffer, 0, 0, 0, 0, (ID3D11Resource *)src_buffer, 0, &box); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0x00000000, 0); set_box(&box, 0, 0, 0, sizeof(float_colors), 0, 0); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_buffer, 0, 0, 0, 0, (ID3D11Resource *)src_buffer, 0, &box); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0x00000000, 0); set_box(&box, 0, 0, 0, sizeof(float_colors), 1, 1); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_buffer, 0, 0, 0, 0, (ID3D11Resource *)src_buffer, 0, &box); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { color = get_readback_color(&rb, 80 + j * 160, 60 + i * 120, 0); ok(compare_color(color, bitmap_data[j + i * 4], 1), "Got color 0x%08x at (%u, %u), expected 0x%08x.\n", color, j, i, bitmap_data[j + i * 4]); } } release_resource_readback(&rb); ID3D11Buffer_Release(dst_buffer); ID3D11Buffer_Release(src_buffer); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_copy_subresource_region_1d(void) { D3D11_SUBRESOURCE_DATA resource_data[4]; struct d3d11_test_context test_context; D3D11_TEXTURE1D_DESC texture1d_desc; D3D11_TEXTURE2D_DESC texture2d_desc; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Texture1D *texture1d; ID3D11Texture2D *texture2d; ID3D11Device *device; unsigned int i, j; D3D11_BOX box; DWORD color; HRESULT hr; static const DWORD bitmap_data[] = { 0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00, 0xffff0000, 0xffff00ff, 0xff000000, 0xff7f7f7f, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture1d_desc.Width = 4; texture1d_desc.MipLevels = 1; texture1d_desc.ArraySize = 4; texture1d_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture1d_desc.Usage = D3D11_USAGE_DEFAULT; texture1d_desc.BindFlags = 0; texture1d_desc.CPUAccessFlags = 0; texture1d_desc.MiscFlags = 0; for (i = 0; i < ARRAY_SIZE(resource_data); ++i) { resource_data[i].pSysMem = &bitmap_data[4 * i]; resource_data[i].SysMemPitch = texture1d_desc.Width * sizeof(bitmap_data); resource_data[i].SysMemSlicePitch = 0; } hr = ID3D11Device_CreateTexture1D(device, &texture1d_desc, resource_data, &texture1d); ok(hr == S_OK, "Failed to create 1d texture, hr %#x.\n", hr); texture2d_desc.Width = 4; texture2d_desc.Height = 4; texture2d_desc.MipLevels = 1; texture2d_desc.ArraySize = 1; texture2d_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture2d_desc.SampleDesc.Count = 1; texture2d_desc.SampleDesc.Quality = 0; texture2d_desc.Usage = D3D11_USAGE_DEFAULT; texture2d_desc.BindFlags = 0; texture2d_desc.CPUAccessFlags = 0; texture2d_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, NULL, &texture2d); ok(hr == S_OK, "Failed to create 2d texture, hr %#x.\n", hr); set_box(&box, 0, 0, 0, 4, 1, 1); for (i = 0; i < ARRAY_SIZE(resource_data); ++i) { ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)texture2d, 0, 0, i, 0, (ID3D11Resource *)texture1d, i, &box); } get_texture_readback(texture2d, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { color = get_readback_color(&rb, j, i, 0); ok(compare_color(color, bitmap_data[j + i * 4], 1), "Got color 0x%08x at (%u, %u), expected 0x%08x.\n", color, j, i, bitmap_data[j + i * 4]); } } release_resource_readback(&rb); get_texture1d_readback(texture1d, 0, &rb); for (i = 0; i < texture1d_desc.Width; ++i) { color = get_readback_color(&rb, i, 0, 0); ok(compare_color(color, bitmap_data[i], 1), "Got color 0x%08x at %u, expected 0x%08x.\n", color, i, bitmap_data[i]); } release_resource_readback(&rb); ID3D11Texture1D_Release(texture1d); ID3D11Texture2D_Release(texture2d); release_test_context(&test_context); } static void test_copy_subresource_region_3d(void) { ID3D11ShaderResourceView *dst_srv, *src_srv; ID3D11Texture3D *dst_texture, *src_texture; D3D11_SUBRESOURCE_DATA resource_data[4]; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture2d_desc; D3D11_TEXTURE3D_DESC texture3d_desc; ID3D11SamplerState *sampler_state; D3D11_SAMPLER_DESC sampler_desc; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Texture2D *texture2d; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, j; DWORD data[4][16]; D3D11_BOX box; DWORD color; HRESULT hr; static const DWORD ps_code[] = { #if 0 Texture3D t; SamplerState s; float4 main(float4 position : SV_POSITION) : SV_Target { return t.Sample(s, position.xyz / float3(640, 480, 1)); } #endif 0x43425844, 0x27b15ae8, 0xbebf46f7, 0x6cd88d8d, 0x5118de51, 0x00000001, 0x00000134, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000070f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040, 0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04002858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101072, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100072, 0x00000000, 0x00101246, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x3f800000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100246, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, }; static const DWORD bitmap_data[] = { 0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00, 0xffff0000, 0xffff00ff, 0xff000000, 0xff7f7f7f, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture3d_desc.Width = 4; texture3d_desc.Height = 4; texture3d_desc.Depth = 4; texture3d_desc.MipLevels = 1; texture3d_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture3d_desc.Usage = D3D11_USAGE_DEFAULT; texture3d_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture3d_desc.CPUAccessFlags = 0; texture3d_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, &src_texture); ok(hr == S_OK, "Failed to create 3d texture, hr %#x.\n", hr); hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, &dst_texture); ok(hr == S_OK, "Failed to create 3d texture, hr %#x.\n", hr); texture2d_desc.Width = 4; texture2d_desc.Height = 4; texture2d_desc.MipLevels = 1; texture2d_desc.ArraySize = 4; texture2d_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture2d_desc.SampleDesc.Count = 1; texture2d_desc.SampleDesc.Quality = 0; texture2d_desc.Usage = D3D11_USAGE_IMMUTABLE; texture2d_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture2d_desc.CPUAccessFlags = 0; texture2d_desc.MiscFlags = 0; for (i = 0; i < ARRAY_SIZE(*data); ++i) { data[0][i] = 0xff0000ff; data[1][i] = bitmap_data[i]; data[2][i] = 0xff00ff00; data[3][i] = 0xffff00ff; } for (i = 0; i < ARRAY_SIZE(resource_data); ++i) { resource_data[i].pSysMem = data[i]; resource_data[i].SysMemPitch = texture2d_desc.Width * sizeof(data[0][0]); resource_data[i].SysMemSlicePitch = 0; } hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, resource_data, &texture2d); ok(hr == S_OK, "Failed to create 2d texture, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)src_texture, NULL, &src_srv); ok(hr == S_OK, "Failed to create shader resource view, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)dst_texture, NULL, &dst_srv); ok(hr == S_OK, "Failed to create shader resource view, hr %#x.\n", hr); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = 0.0f; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler_state); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &src_srv); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler_state); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); set_box(&box, 0, 0, 0, 4, 4, 1); for (i = 0; i < ARRAY_SIZE(resource_data); ++i) { ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)src_texture, 0, 0, 0, i, (ID3D11Resource *)texture2d, i, &box); } draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff0000ff, 1); draw_quad_z(&test_context, 0.25f); get_texture_readback(test_context.backbuffer, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { color = get_readback_color(&rb, 80 + j * 160, 60 + i * 120, 0); ok(compare_color(color, bitmap_data[j + i * 4], 1), "Got color 0x%08x at (%u, %u), expected 0x%08x.\n", color, j, i, bitmap_data[j + i * 4]); } } release_resource_readback(&rb); draw_quad_z(&test_context, 0.5f); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); draw_quad_z(&test_context, 1.0f); check_texture_color(test_context.backbuffer, 0xffff00ff, 1); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &dst_srv); set_box(&box, 0, 0, 0, 4, 4, 2); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 0, 0, 2, (ID3D11Resource *)src_texture, 0, &box); set_box(&box, 0, 0, 2, 4, 4, 4); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 0, 0, 0, (ID3D11Resource *)src_texture, 0, &box); set_box(&box, 0, 0, 0, 4, 4, 1); for (i = 0; i < ARRAY_SIZE(resource_data); ++i) { ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)src_texture, 0, 0, 0, i, (ID3D11Resource *)texture2d, i, &box); } draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); draw_quad_z(&test_context, 0.25f); check_texture_color(test_context.backbuffer, 0xffff00ff, 1); draw_quad_z(&test_context, 0.5f); check_texture_color(test_context.backbuffer, 0xff0000ff, 1); draw_quad_z(&test_context, 1.0f); get_texture_readback(test_context.backbuffer, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { color = get_readback_color(&rb, 80 + j * 160, 60 + i * 120, 0); ok(compare_color(color, bitmap_data[j + i * 4], 1), "Got color 0x%08x at (%u, %u), expected 0x%08x.\n", color, j, i, bitmap_data[j + i * 4]); } } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); ID3D11SamplerState_Release(sampler_state); ID3D11ShaderResourceView_Release(dst_srv); ID3D11ShaderResourceView_Release(src_srv); ID3D11Texture2D_Release(texture2d); ID3D11Texture3D_Release(dst_texture); ID3D11Texture3D_Release(src_texture); release_test_context(&test_context); } static void test_resource_map(void) { D3D11_MAPPED_SUBRESOURCE mapped_subresource; D3D11_TEXTURE3D_DESC texture3d_desc; D3D11_TEXTURE2D_DESC texture2d_desc; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; ID3D11Texture3D *texture3d; ID3D11Texture2D *texture2d; ID3D11Buffer *buffer; ID3D11Device *device; ULONG refcount; HRESULT hr; DWORD data; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } ID3D11Device_GetImmediateContext(device, &context); buffer_desc.ByteWidth = 1024; buffer_desc.Usage = D3D11_USAGE_STAGING; buffer_desc.BindFlags = 0; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; buffer_desc.MiscFlags = 0; buffer_desc.StructureByteStride = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)buffer, 1, D3D11_MAP_READ, 0, &mapped_subresource); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); memset(&mapped_subresource, 0, sizeof(mapped_subresource)); hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)buffer, 0, D3D11_MAP_WRITE, 0, &mapped_subresource); ok(SUCCEEDED(hr), "Failed to map buffer, hr %#x.\n", hr); ok(mapped_subresource.RowPitch == 1024, "Got unexpected row pitch %u.\n", mapped_subresource.RowPitch); ok(mapped_subresource.DepthPitch == 1024, "Got unexpected depth pitch %u.\n", mapped_subresource.DepthPitch); *((DWORD *)mapped_subresource.pData) = 0xdeadbeef; ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)buffer, 0); memset(&mapped_subresource, 0, sizeof(mapped_subresource)); hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)buffer, 0, D3D11_MAP_READ, 0, &mapped_subresource); ok(SUCCEEDED(hr), "Failed to map buffer, hr %#x.\n", hr); ok(mapped_subresource.RowPitch == 1024, "Got unexpected row pitch %u.\n", mapped_subresource.RowPitch); ok(mapped_subresource.DepthPitch == 1024, "Got unexpected depth pitch %u.\n", mapped_subresource.DepthPitch); data = *((DWORD *)mapped_subresource.pData); ok(data == 0xdeadbeef, "Got unexpected data %#x.\n", data); ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)buffer, 0); refcount = ID3D11Buffer_Release(buffer); ok(!refcount, "Buffer has %u references left.\n", refcount); texture2d_desc.Width = 512; texture2d_desc.Height = 512; texture2d_desc.MipLevels = 1; texture2d_desc.ArraySize = 1; texture2d_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture2d_desc.SampleDesc.Count = 1; texture2d_desc.SampleDesc.Quality = 0; texture2d_desc.Usage = D3D11_USAGE_STAGING; texture2d_desc.BindFlags = 0; texture2d_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; texture2d_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, NULL, &texture2d); ok(SUCCEEDED(hr), "Failed to create 2d texture, hr %#x.\n", hr); hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)texture2d, 1, D3D11_MAP_READ, 0, &mapped_subresource); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); memset(&mapped_subresource, 0, sizeof(mapped_subresource)); hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)texture2d, 0, D3D11_MAP_WRITE, 0, &mapped_subresource); ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr); ok(mapped_subresource.RowPitch == 4 * 512, "Got unexpected row pitch %u.\n", mapped_subresource.RowPitch); ok(mapped_subresource.DepthPitch == 4 * 512 * 512, "Got unexpected depth pitch %u.\n", mapped_subresource.DepthPitch); *((DWORD *)mapped_subresource.pData) = 0xdeadbeef; ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)texture2d, 0); memset(&mapped_subresource, 0, sizeof(mapped_subresource)); hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)texture2d, 0, D3D11_MAP_READ, 0, &mapped_subresource); ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr); ok(mapped_subresource.RowPitch == 4 * 512, "Got unexpected row pitch %u.\n", mapped_subresource.RowPitch); ok(mapped_subresource.DepthPitch == 4 * 512 * 512, "Got unexpected depth pitch %u.\n", mapped_subresource.DepthPitch); data = *((DWORD *)mapped_subresource.pData); ok(data == 0xdeadbeef, "Got unexpected data %#x.\n", data); ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)texture2d, 0); refcount = ID3D11Texture2D_Release(texture2d); ok(!refcount, "2D texture has %u references left.\n", refcount); texture3d_desc.Width = 64; texture3d_desc.Height = 64; texture3d_desc.Depth = 64; texture3d_desc.MipLevels = 1; texture3d_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture3d_desc.Usage = D3D11_USAGE_STAGING; texture3d_desc.BindFlags = 0; texture3d_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; texture3d_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, &texture3d); ok(SUCCEEDED(hr), "Failed to create 3d texture, hr %#x.\n", hr); hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)texture3d, 1, D3D11_MAP_READ, 0, &mapped_subresource); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); memset(&mapped_subresource, 0, sizeof(mapped_subresource)); hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)texture3d, 0, D3D11_MAP_WRITE, 0, &mapped_subresource); ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr); ok(mapped_subresource.RowPitch == 4 * 64, "Got unexpected row pitch %u.\n", mapped_subresource.RowPitch); ok(mapped_subresource.DepthPitch == 4 * 64 * 64, "Got unexpected depth pitch %u.\n", mapped_subresource.DepthPitch); *((DWORD *)mapped_subresource.pData) = 0xdeadbeef; ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)texture3d, 0); memset(&mapped_subresource, 0, sizeof(mapped_subresource)); hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)texture3d, 0, D3D11_MAP_READ, 0, &mapped_subresource); ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr); ok(mapped_subresource.RowPitch == 4 * 64, "Got unexpected row pitch %u.\n", mapped_subresource.RowPitch); ok(mapped_subresource.DepthPitch == 4 * 64 * 64, "Got unexpected depth pitch %u.\n", mapped_subresource.DepthPitch); data = *((DWORD *)mapped_subresource.pData); ok(data == 0xdeadbeef, "Got unexpected data %#x.\n", data); ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)texture3d, 0); refcount = ID3D11Texture3D_Release(texture3d); ok(!refcount, "3D texture has %u references left.\n", refcount); ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } #define check_resource_cpu_access(a, b, c, d, e) check_resource_cpu_access_(__LINE__, a, b, c, d, e) static void check_resource_cpu_access_(unsigned int line, ID3D11DeviceContext *context, ID3D11Resource *resource, D3D11_USAGE usage, UINT bind_flags, UINT cpu_access) { BOOL cpu_write = cpu_access & D3D11_CPU_ACCESS_WRITE; BOOL cpu_read = cpu_access & D3D11_CPU_ACCESS_READ; BOOL dynamic = usage == D3D11_USAGE_DYNAMIC; D3D11_MAPPED_SUBRESOURCE map_desc; HRESULT hr, expected_hr; ID3D11Device *device; expected_hr = cpu_read ? S_OK : E_INVALIDARG; hr = ID3D11DeviceContext_Map(context, resource, 0, D3D11_MAP_READ, 0, &map_desc); ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for READ.\n", hr); if (SUCCEEDED(hr)) ID3D11DeviceContext_Unmap(context, resource, 0); /* WRITE_DISCARD and WRITE_NO_OVERWRITE are the only allowed options for dynamic resources. */ expected_hr = !dynamic && cpu_write ? S_OK : E_INVALIDARG; hr = ID3D11DeviceContext_Map(context, resource, 0, D3D11_MAP_WRITE, 0, &map_desc); todo_wine_if(dynamic && cpu_write) ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for WRITE.\n", hr); if (SUCCEEDED(hr)) ID3D11DeviceContext_Unmap(context, resource, 0); expected_hr = cpu_read && cpu_write ? S_OK : E_INVALIDARG; hr = ID3D11DeviceContext_Map(context, resource, 0, D3D11_MAP_READ_WRITE, 0, &map_desc); ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for READ_WRITE.\n", hr); if (SUCCEEDED(hr)) ID3D11DeviceContext_Unmap(context, resource, 0); expected_hr = dynamic ? S_OK : E_INVALIDARG; hr = ID3D11DeviceContext_Map(context, resource, 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc); todo_wine_if(!dynamic && cpu_write) ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for WRITE_DISCARD.\n", hr); if (SUCCEEDED(hr)) ID3D11DeviceContext_Unmap(context, resource, 0); if (!dynamic) return; ID3D11DeviceContext_GetDevice(context, &device); /* WRITE_NO_OVERWRITE is supported only for buffers. */ expected_hr = is_buffer(resource) ? S_OK : E_INVALIDARG; hr = ID3D11DeviceContext_Map(context, resource, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map_desc); /* D3D11.1 is required for constant and shader buffers. */ todo_wine_if(expected_hr != S_OK) ok_(__FILE__, line)(hr == expected_hr || broken(bind_flags & (D3D11_BIND_CONSTANT_BUFFER | D3D11_BIND_SHADER_RESOURCE)), "Got hr %#x for WRITE_NO_OVERWRITE.\n", hr); if (SUCCEEDED(hr)) ID3D11DeviceContext_Unmap(context, resource, 0); ID3D11Device_Release(device); } static void test_resource_access(const D3D_FEATURE_LEVEL feature_level) { D3D11_TEXTURE2D_DESC texture_desc; struct device_desc device_desc; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; D3D11_SUBRESOURCE_DATA data; ID3D11Resource *resource; BOOL required_cpu_access; BOOL cpu_write, cpu_read; HRESULT hr, expected_hr; UINT allowed_cpu_access; BOOL broken_validation; ID3D11Device *device; unsigned int i; ULONG refcount; static const struct { D3D11_USAGE usage; UINT bind_flags; BOOL is_valid; UINT allowed_cpu_access; } tests[] = { /* Default resources cannot be written by CPU. */ {D3D11_USAGE_DEFAULT, D3D11_BIND_VERTEX_BUFFER, TRUE, 0}, {D3D11_USAGE_DEFAULT, D3D11_BIND_INDEX_BUFFER, TRUE, 0}, {D3D11_USAGE_DEFAULT, D3D11_BIND_CONSTANT_BUFFER, TRUE, 0}, {D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, TRUE, 0}, {D3D11_USAGE_DEFAULT, D3D11_BIND_STREAM_OUTPUT, TRUE, 0}, {D3D11_USAGE_DEFAULT, D3D11_BIND_RENDER_TARGET, TRUE, 0}, {D3D11_USAGE_DEFAULT, D3D11_BIND_DEPTH_STENCIL, TRUE, 0}, {D3D11_USAGE_DEFAULT, D3D11_BIND_UNORDERED_ACCESS, TRUE, 0}, /* Immutable resources cannot be written by CPU and GPU. */ {D3D11_USAGE_IMMUTABLE, 0, FALSE, 0}, {D3D11_USAGE_IMMUTABLE, D3D11_BIND_VERTEX_BUFFER, TRUE, 0}, {D3D11_USAGE_IMMUTABLE, D3D11_BIND_INDEX_BUFFER, TRUE, 0}, {D3D11_USAGE_IMMUTABLE, D3D11_BIND_CONSTANT_BUFFER, TRUE, 0}, {D3D11_USAGE_IMMUTABLE, D3D11_BIND_SHADER_RESOURCE, TRUE, 0}, {D3D11_USAGE_IMMUTABLE, D3D11_BIND_STREAM_OUTPUT, FALSE, 0}, {D3D11_USAGE_IMMUTABLE, D3D11_BIND_RENDER_TARGET, FALSE, 0}, {D3D11_USAGE_IMMUTABLE, D3D11_BIND_DEPTH_STENCIL, FALSE, 0}, {D3D11_USAGE_IMMUTABLE, D3D11_BIND_UNORDERED_ACCESS, FALSE, 0}, /* Dynamic resources cannot be written by GPU. */ {D3D11_USAGE_DYNAMIC, 0, FALSE, D3D11_CPU_ACCESS_WRITE}, {D3D11_USAGE_DYNAMIC, D3D11_BIND_VERTEX_BUFFER, TRUE, D3D11_CPU_ACCESS_WRITE}, {D3D11_USAGE_DYNAMIC, D3D11_BIND_INDEX_BUFFER, TRUE, D3D11_CPU_ACCESS_WRITE}, {D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, TRUE, D3D11_CPU_ACCESS_WRITE}, {D3D11_USAGE_DYNAMIC, D3D11_BIND_SHADER_RESOURCE, TRUE, D3D11_CPU_ACCESS_WRITE}, {D3D11_USAGE_DYNAMIC, D3D11_BIND_STREAM_OUTPUT, FALSE, D3D11_CPU_ACCESS_WRITE}, {D3D11_USAGE_DYNAMIC, D3D11_BIND_RENDER_TARGET, FALSE, D3D11_CPU_ACCESS_WRITE}, {D3D11_USAGE_DYNAMIC, D3D11_BIND_DEPTH_STENCIL, FALSE, D3D11_CPU_ACCESS_WRITE}, {D3D11_USAGE_DYNAMIC, D3D11_BIND_UNORDERED_ACCESS, FALSE, D3D11_CPU_ACCESS_WRITE}, /* Staging resources support only data transfer. */ {D3D11_USAGE_STAGING, 0, TRUE, D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ}, {D3D11_USAGE_STAGING, D3D11_BIND_VERTEX_BUFFER, FALSE, 0}, {D3D11_USAGE_STAGING, D3D11_BIND_INDEX_BUFFER, FALSE, 0}, {D3D11_USAGE_STAGING, D3D11_BIND_CONSTANT_BUFFER, FALSE, 0}, {D3D11_USAGE_STAGING, D3D11_BIND_SHADER_RESOURCE, FALSE, 0}, {D3D11_USAGE_STAGING, D3D11_BIND_STREAM_OUTPUT, FALSE, 0}, {D3D11_USAGE_STAGING, D3D11_BIND_RENDER_TARGET, FALSE, 0}, {D3D11_USAGE_STAGING, D3D11_BIND_DEPTH_STENCIL, FALSE, 0}, {D3D11_USAGE_STAGING, D3D11_BIND_UNORDERED_ACCESS, FALSE, 0}, }; device_desc.feature_level = &feature_level; device_desc.flags = 0; if (!(device = create_device(&device_desc))) { skip("Failed to create device for feature level %#x.\n", feature_level); return; } ID3D11Device_GetImmediateContext(device, &context); data.SysMemPitch = 0; data.SysMemSlicePitch = 0; data.pSysMem = heap_alloc(10240); ok(!!data.pSysMem, "Failed to allocate memory.\n"); for (i = 0; i < ARRAY_SIZE(tests); ++i) { switch (tests[i].bind_flags) { case D3D11_BIND_DEPTH_STENCIL: continue; case D3D11_BIND_SHADER_RESOURCE: case D3D11_BIND_STREAM_OUTPUT: case D3D11_BIND_RENDER_TARGET: if (feature_level < D3D_FEATURE_LEVEL_10_0) continue; break; case D3D11_BIND_UNORDERED_ACCESS: if (feature_level < D3D_FEATURE_LEVEL_11_0) continue; break; default: break; } allowed_cpu_access = tests[i].allowed_cpu_access; if (feature_level >= D3D_FEATURE_LEVEL_11_0 && is_d3d11_2_runtime(device) && tests[i].usage == D3D11_USAGE_DEFAULT && (tests[i].bind_flags == D3D11_BIND_SHADER_RESOURCE || tests[i].bind_flags == D3D11_BIND_UNORDERED_ACCESS)) allowed_cpu_access |= D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; required_cpu_access = tests[i].usage == D3D11_USAGE_DYNAMIC || tests[i].usage == D3D11_USAGE_STAGING; cpu_write = allowed_cpu_access & D3D11_CPU_ACCESS_WRITE; cpu_read = allowed_cpu_access & D3D11_CPU_ACCESS_READ; buffer_desc.ByteWidth = 1024; buffer_desc.Usage = tests[i].usage; buffer_desc.BindFlags = tests[i].bind_flags; buffer_desc.MiscFlags = 0; buffer_desc.StructureByteStride = 0; buffer_desc.CPUAccessFlags = 0; expected_hr = tests[i].is_valid && !required_cpu_access ? S_OK : E_INVALIDARG; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, &data, (ID3D11Buffer **)&resource); ok(hr == expected_hr, "Got hr %#x, expected %#x, test %u.\n", hr, expected_hr, i); if (SUCCEEDED(hr)) { check_resource_cpu_access(context, resource, buffer_desc.Usage, buffer_desc.BindFlags, buffer_desc.CPUAccessFlags); ID3D11Resource_Release(resource); } buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; expected_hr = tests[i].is_valid && cpu_write ? S_OK : E_INVALIDARG; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, &data, (ID3D11Buffer **)&resource); ok(hr == expected_hr, "Got hr %#x, expected %#x, test %u.\n", hr, expected_hr, i); if (SUCCEEDED(hr)) { check_resource_cpu_access(context, resource, buffer_desc.Usage, buffer_desc.BindFlags, buffer_desc.CPUAccessFlags); ID3D11Resource_Release(resource); } buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; expected_hr = tests[i].is_valid && cpu_read ? S_OK : E_INVALIDARG; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, &data, (ID3D11Buffer **)&resource); ok(hr == expected_hr, "Got hr %#x, expected %#x, test %u.\n", hr, expected_hr, i); if (SUCCEEDED(hr)) { check_resource_cpu_access(context, resource, buffer_desc.Usage, buffer_desc.BindFlags, buffer_desc.CPUAccessFlags); ID3D11Resource_Release(resource); } buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; expected_hr = tests[i].is_valid && cpu_write && cpu_read ? S_OK : E_INVALIDARG; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, &data, (ID3D11Buffer **)&resource); ok(hr == expected_hr, "Got hr %#x, expected %#x, test %u.\n", hr, expected_hr, i); if (SUCCEEDED(hr)) { check_resource_cpu_access(context, resource, buffer_desc.Usage, buffer_desc.BindFlags, buffer_desc.CPUAccessFlags); ID3D11Resource_Release(resource); } } data.SysMemPitch = 16; for (i = 0; i < ARRAY_SIZE(tests); ++i) { switch (tests[i].bind_flags) { case D3D11_BIND_VERTEX_BUFFER: case D3D11_BIND_INDEX_BUFFER: case D3D11_BIND_CONSTANT_BUFFER: case D3D11_BIND_STREAM_OUTPUT: continue; case D3D11_BIND_UNORDERED_ACCESS: if (feature_level < D3D_FEATURE_LEVEL_11_0) continue; break; default: break; } broken_validation = tests[i].usage == D3D11_USAGE_DEFAULT && (tests[i].bind_flags == D3D11_BIND_SHADER_RESOURCE || tests[i].bind_flags == D3D11_BIND_RENDER_TARGET || tests[i].bind_flags == D3D11_BIND_UNORDERED_ACCESS); required_cpu_access = tests[i].usage == D3D11_USAGE_DYNAMIC || tests[i].usage == D3D11_USAGE_STAGING; cpu_write = tests[i].allowed_cpu_access & D3D11_CPU_ACCESS_WRITE; cpu_read = tests[i].allowed_cpu_access & D3D11_CPU_ACCESS_READ; texture_desc.Width = 4; texture_desc.Height = 4; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = tests[i].usage; texture_desc.BindFlags = tests[i].bind_flags; texture_desc.MiscFlags = 0; if (tests[i].bind_flags == D3D11_BIND_DEPTH_STENCIL) texture_desc.Format = DXGI_FORMAT_D16_UNORM; texture_desc.CPUAccessFlags = 0; expected_hr = tests[i].is_valid && !required_cpu_access ? S_OK : E_INVALIDARG; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &data, (ID3D11Texture2D **)&resource); ok(hr == expected_hr, "Got hr %#x, expected %#x, test %u.\n", hr, expected_hr, i); if (SUCCEEDED(hr)) { check_resource_cpu_access(context, resource, texture_desc.Usage, texture_desc.BindFlags, texture_desc.CPUAccessFlags); ID3D11Resource_Release(resource); } texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; expected_hr = tests[i].is_valid && cpu_write ? S_OK : E_INVALIDARG; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &data, (ID3D11Texture2D **)&resource); ok(hr == expected_hr || (hr == S_OK && broken_validation), "Got hr %#x, expected %#x, test %u.\n", hr, expected_hr, i); if (SUCCEEDED(hr)) { if (broken_validation) texture_desc.CPUAccessFlags = 0; check_resource_cpu_access(context, resource, texture_desc.Usage, texture_desc.BindFlags, texture_desc.CPUAccessFlags); ID3D11Resource_Release(resource); } texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; expected_hr = tests[i].is_valid && cpu_read ? S_OK : E_INVALIDARG; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &data, (ID3D11Texture2D **)&resource); ok(hr == expected_hr || (hr == S_OK && broken_validation), "Got hr %#x, expected %#x, test %u.\n", hr, expected_hr, i); if (SUCCEEDED(hr)) { if (broken_validation) texture_desc.CPUAccessFlags = 0; check_resource_cpu_access(context, resource, texture_desc.Usage, texture_desc.BindFlags, texture_desc.CPUAccessFlags); ID3D11Resource_Release(resource); } texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; expected_hr = tests[i].is_valid && cpu_write && cpu_read ? S_OK : E_INVALIDARG; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &data, (ID3D11Texture2D **)&resource); ok(hr == expected_hr || (hr == S_OK && broken_validation), "Got hr %#x, expected %#x, test %u.\n", hr, expected_hr, i); if (SUCCEEDED(hr)) { if (broken_validation) texture_desc.CPUAccessFlags = 0; check_resource_cpu_access(context, resource, texture_desc.Usage, texture_desc.BindFlags, texture_desc.CPUAccessFlags); ID3D11Resource_Release(resource); } } heap_free((void *)data.pSysMem); ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_check_multisample_quality_levels(void) { ID3D11Device *device; UINT quality_levels; ULONG refcount; HRESULT hr; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 2, &quality_levels); ok(hr == S_OK, "Failed to check multisample quality levels, hr %#x.\n", hr); if (!quality_levels) { skip("Multisampling not supported for DXGI_FORMAT_R8G8B8A8_UNORM, skipping test.\n"); goto done; } quality_levels = 0xdeadbeef; hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_UNKNOWN, 2, &quality_levels); todo_wine ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); ok(!quality_levels, "Got unexpected quality_levels %u.\n", quality_levels); quality_levels = 0xdeadbeef; hr = ID3D11Device_CheckMultisampleQualityLevels(device, 65536, 2, &quality_levels); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); todo_wine ok(quality_levels == 0xdeadbeef, "Got unexpected quality_levels %u.\n", quality_levels); if (!enable_debug_layer) { hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 0, NULL); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 1, NULL); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 2, NULL); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); } quality_levels = 0xdeadbeef; hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &quality_levels); ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); ok(!quality_levels, "Got unexpected quality_levels %u.\n", quality_levels); quality_levels = 0xdeadbeef; hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 1, &quality_levels); ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels); quality_levels = 0xdeadbeef; hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 2, &quality_levels); ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels); /* We assume 15 samples multisampling is never supported in practice. */ quality_levels = 0xdeadbeef; hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 15, &quality_levels); ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); ok(!quality_levels, "Got unexpected quality_levels %u.\n", quality_levels); hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 32, &quality_levels); ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); quality_levels = 0xdeadbeef; hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 33, &quality_levels); ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); ok(!quality_levels, "Got unexpected quality_levels %u.\n", quality_levels); quality_levels = 0xdeadbeef; hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_UNORM, 64, &quality_levels); ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); ok(!quality_levels, "Got unexpected quality_levels %u.\n", quality_levels); hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_BC3_UNORM, 2, &quality_levels); ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); ok(!quality_levels, "Got unexpected quality_levels %u.\n", quality_levels); done: refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_swapchain_formats(const D3D_FEATURE_LEVEL feature_level) { DXGI_SWAP_CHAIN_DESC swapchain_desc; struct device_desc device_desc; IDXGISwapChain *swapchain; IDXGIDevice *dxgi_device; HRESULT hr, expected_hr; IDXGIAdapter *adapter; IDXGIFactory *factory; ID3D11Device *device; unsigned int i; ULONG refcount; swapchain_desc.BufferDesc.Width = 800; swapchain_desc.BufferDesc.Height = 600; swapchain_desc.BufferDesc.RefreshRate.Numerator = 60; swapchain_desc.BufferDesc.RefreshRate.Denominator = 60; swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; swapchain_desc.SampleDesc.Count = 1; swapchain_desc.SampleDesc.Quality = 0; swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapchain_desc.BufferCount = 1; swapchain_desc.OutputWindow = CreateWindowA("static", "d3d11_test", 0, 0, 0, 0, 0, 0, 0, 0, 0); swapchain_desc.Windowed = TRUE; swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swapchain_desc.Flags = 0; device_desc.feature_level = &feature_level; device_desc.flags = 0; if (!(device = create_device(&device_desc))) { skip("Failed to create device for feature level %#x.\n", feature_level); return; } hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); ok(SUCCEEDED(hr), "Failed to query IDXGIDevice, hr %#x.\n", hr); hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter); ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr); IDXGIDevice_Release(dxgi_device); hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory); ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr); IDXGIAdapter_Release(adapter); swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS; hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain); todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#x for typeless format (feature level %#x).\n", hr, feature_level); if (SUCCEEDED(hr)) IDXGISwapChain_Release(swapchain); for (i = 0; i < ARRAY_SIZE(display_format_support); ++i) { DXGI_FORMAT format = display_format_support[i].format; BOOL todo = FALSE; if (display_format_support[i].fl_required <= feature_level) { expected_hr = S_OK; if (format == DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM) todo = TRUE; } else if (!display_format_support[i].fl_optional || display_format_support[i].fl_optional > feature_level) { expected_hr = E_INVALIDARG; if (format != DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM) todo = TRUE; } else { continue; } swapchain_desc.BufferDesc.Format = format; hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain); todo_wine_if(todo) ok(hr == expected_hr || broken(hr == E_OUTOFMEMORY), "Got hr %#x, expected %#x (feature level %#x, format %#x).\n", hr, expected_hr, feature_level, format); if (FAILED(hr)) continue; refcount = IDXGISwapChain_Release(swapchain); ok(!refcount, "Swapchain has %u references left.\n", refcount); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); refcount = IDXGIFactory_Release(factory); ok(!refcount, "Factory has %u references left.\n", refcount); DestroyWindow(swapchain_desc.OutputWindow); } static void test_swapchain_views(void) { D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; struct d3d11_test_context test_context; D3D11_RENDER_TARGET_VIEW_DESC rtv_desc; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Device *device; ULONG refcount; HRESULT hr; static const struct vec4 color = {0.2f, 0.3f, 0.5f, 1.0f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; refcount = get_refcount(test_context.backbuffer); ok(refcount == 1, "Got unexpected refcount %u.\n", refcount); draw_color_quad(&test_context, &color); check_texture_color(test_context.backbuffer, 0xff7f4c33, 1); rtv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; U(rtv_desc).Texture2D.MipSlice = 0; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)test_context.backbuffer, &rtv_desc, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); refcount = get_refcount(test_context.backbuffer); ok(refcount == 1, "Got unexpected refcount %u.\n", refcount); draw_color_quad(&test_context, &color); todo_wine check_texture_color(test_context.backbuffer, 0xffbc957c, 1); srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; U(srv_desc).Texture2D.MostDetailedMip = 0; U(srv_desc).Texture2D.MipLevels = 1; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)test_context.backbuffer, &srv_desc, &srv); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); if (SUCCEEDED(hr)) ID3D11ShaderResourceView_Release(srv); ID3D11RenderTargetView_Release(rtv); release_test_context(&test_context); } static void test_swapchain_flip(void) { ID3D11Texture2D *backbuffer_0, *backbuffer_1, *backbuffer_2, *offscreen; ID3D11ShaderResourceView *backbuffer_0_srv, *backbuffer_1_srv; ID3D11RenderTargetView *backbuffer_0_rtv, *offscreen_rtv; D3D11_TEXTURE2D_DESC texture_desc; ID3D11InputLayout *input_layout; ID3D11DeviceContext *context; unsigned int stride, offset; struct swapchain_desc desc; IDXGISwapChain *swapchain; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *vb; ULONG refcount; DWORD color; HWND window; HRESULT hr; RECT rect; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const DWORD vs_code[] = { #if 0 float4 main(float4 position : POSITION) : SV_POSITION { return position; } #endif 0x43425844, 0xa7a2f22d, 0x83ff2560, 0xe61638bd, 0x87e3ce90, 0x00000001, 0x000000d8, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000003c, 0x00010040, 0x0000000f, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 Texture2D t0, t1; SamplerState s; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; p.x = 0.5; p.y = 0.5; if (position.x < 320) return t0.Sample(s, p); return t1.Sample(s, p); } #endif 0x43425844, 0xc00961ea, 0x48558efd, 0x5eec7aed, 0xb597e6d1, 0x00000001, 0x00000188, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000010f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000ec, 0x00000040, 0x0000003b, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101012, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x07000031, 0x00100012, 0x00000000, 0x0010100a, 0x00000000, 0x00004001, 0x43a00000, 0x0304001f, 0x0010000a, 0x00000000, 0x0c000045, 0x001020f2, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, 0x01000015, 0x0c000045, 0x001020f2, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x0100003e, }; static const struct vec2 quad[] = { {-1.0f, -1.0f}, {-1.0f, 1.0f}, { 1.0f, -1.0f}, { 1.0f, 1.0f}, }; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; static const float green[] = {0.0f, 1.0f, 0.0f, 0.5f}; static const float blue[] = {0.0f, 0.0f, 1.0f, 0.5f}; if (!(device = create_device(NULL))) { skip("Failed to create device, skipping tests.\n"); return; } SetRect(&rect, 0, 0, 640, 480); AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE); window = CreateWindowA("static", "d3d11_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL); desc.buffer_count = 3; desc.width = desc.height = 0; desc.swap_effect = DXGI_SWAP_EFFECT_SEQUENTIAL; desc.windowed = TRUE; desc.flags = SWAPCHAIN_FLAG_SHADER_INPUT; swapchain = create_swapchain(device, window, &desc); hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D11Texture2D, (void **)&backbuffer_0); ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr); hr = IDXGISwapChain_GetBuffer(swapchain, 1, &IID_ID3D11Texture2D, (void **)&backbuffer_1); ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr); hr = IDXGISwapChain_GetBuffer(swapchain, 2, &IID_ID3D11Texture2D, (void **)&backbuffer_2); ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)backbuffer_0, NULL, &backbuffer_0_rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)backbuffer_0, NULL, &backbuffer_0_srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)backbuffer_1, NULL, &backbuffer_1_srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); ID3D11Texture2D_GetDesc(backbuffer_0, &texture_desc); ok((texture_desc.BindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)) == (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), "Got unexpected bind flags %x.\n", texture_desc.BindFlags); ok(texture_desc.Usage == D3D11_USAGE_DEFAULT, "Got unexpected usage %u.\n", texture_desc.Usage); ID3D11Texture2D_GetDesc(backbuffer_1, &texture_desc); ok((texture_desc.BindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)) == (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), "Got unexpected bind flags %x.\n", texture_desc.BindFlags); ok(texture_desc.Usage == D3D11_USAGE_DEFAULT, "Got unexpected usage %u.\n", texture_desc.Usage); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)backbuffer_1, NULL, &offscreen_rtv); todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); if (SUCCEEDED(hr)) ID3D11RenderTargetView_Release(offscreen_rtv); ID3D11Device_GetImmediateContext(device, &context); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &backbuffer_0_srv); ID3D11DeviceContext_PSSetShaderResources(context, 1, 1, &backbuffer_1_srv); texture_desc.Width = 640; texture_desc.Height = 480; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &offscreen); ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)offscreen, NULL, &offscreen_rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &offscreen_rtv, NULL); set_viewport(context, 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1.0f); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(quad), quad); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); stride = sizeof(*quad); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, &stride, &offset); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, backbuffer_0_rtv, red); ID3D11DeviceContext_Draw(context, 4, 0); color = get_texture_color(offscreen, 120, 240); ok(compare_color(color, 0x7f0000ff, 1), "Got unexpected color 0x%08x.\n", color); /* DXGI moves buffers in the same direction as earlier versions. Buffer 2 * becomes buffer 1, buffer 1 becomes the new buffer 0, and buffer 0 * becomes buffer n - 1. However, only buffer 0 can be rendered to. * * What is this good for? I don't know. Ad-hoc tests suggest that * Present() always waits for the next V-sync interval, even if there are * still untouched buffers. Buffer 0 is the buffer that is shown on the * screen, just like in <= d3d9. Present() also doesn't discard buffers if * rendering finishes before the V-sync interval is over. I haven't found * any productive use for more than one buffer. */ IDXGISwapChain_Present(swapchain, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, backbuffer_0_rtv, green); ID3D11DeviceContext_Draw(context, 4, 0); color = get_texture_color(offscreen, 120, 240); /* green, buf 0 */ ok(compare_color(color, 0x7f00ff00, 1), "Got unexpected color 0x%08x.\n", color); /* Buffer 1 is still untouched. */ color = get_texture_color(backbuffer_0, 320, 240); /* green */ ok(compare_color(color, 0x7f00ff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(backbuffer_2, 320, 240); /* red */ ok(compare_color(color, 0x7f0000ff, 1), "Got unexpected color 0x%08x.\n", color); IDXGISwapChain_Present(swapchain, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, backbuffer_0_rtv, blue); ID3D11DeviceContext_Draw(context, 4, 0); color = get_texture_color(offscreen, 120, 240); /* blue, buf 0 */ ok(compare_color(color, 0x7fff0000, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(offscreen, 360, 240); /* red, buf 1 */ ok(compare_color(color, 0x7f0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(backbuffer_0, 320, 240); /* blue */ ok(compare_color(color, 0x7fff0000, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(backbuffer_1, 320, 240); /* red */ ok(compare_color(color, 0x7f0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(backbuffer_2, 320, 240); /* green */ ok(compare_color(color, 0x7f00ff00, 1), "Got unexpected color 0x%08x.\n", color); ID3D11VertexShader_Release(vs); ID3D11PixelShader_Release(ps); ID3D11Buffer_Release(vb); ID3D11InputLayout_Release(input_layout); ID3D11ShaderResourceView_Release(backbuffer_0_srv); ID3D11ShaderResourceView_Release(backbuffer_1_srv); ID3D11RenderTargetView_Release(backbuffer_0_rtv); ID3D11RenderTargetView_Release(offscreen_rtv); ID3D11Texture2D_Release(offscreen); ID3D11Texture2D_Release(backbuffer_0); ID3D11Texture2D_Release(backbuffer_1); ID3D11Texture2D_Release(backbuffer_2); IDXGISwapChain_Release(swapchain); ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); DestroyWindow(window); } static void test_clear_render_target_view_1d(void) { static const float color[] = {0.1f, 0.5f, 0.3f, 0.75f}; static const float green[] = {0.0f, 1.0f, 0.0f, 0.5f}; struct d3d11_test_context test_context; D3D11_TEXTURE1D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Texture1D *texture; ID3D11Device *device; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 64; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture1D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, color); check_texture1d_color(texture, 0xbf4c7f19, 1); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, green); check_texture1d_color(texture, 0x8000ff00, 1); ID3D11RenderTargetView_Release(rtv); ID3D11Texture1D_Release(texture); release_test_context(&test_context); } static void test_clear_render_target_view_2d(void) { static const DWORD expected_color = 0xbf4c7f19, expected_srgb_color = 0xbf95bc59; static const float color[] = {0.1f, 0.5f, 0.3f, 0.75f}; static const float green[] = {0.0f, 1.0f, 0.0f, 0.5f}; ID3D11Texture2D *texture, *srgb_texture; struct d3d11_test_context test_context; ID3D11RenderTargetView *rtv, *srgb_rtv; D3D11_RENDER_TARGET_VIEW_DESC rtv_desc; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Device *device; unsigned int i, j; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 640; texture_desc.Height = 480; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &srgb_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)srgb_texture, NULL, &srgb_rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, color); check_texture_color(test_context.backbuffer, expected_color, 1); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, color); check_texture_color(texture, expected_color, 1); if (!enable_debug_layer) ID3D11DeviceContext_ClearRenderTargetView(context, NULL, green); check_texture_color(texture, expected_color, 1); ID3D11DeviceContext_ClearRenderTargetView(context, srgb_rtv, color); check_texture_color(srgb_texture, expected_srgb_color, 1); ID3D11RenderTargetView_Release(srgb_rtv); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(srgb_texture); ID3D11Texture2D_Release(texture); texture_desc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); rtv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; U(rtv_desc).Texture2D.MipSlice = 0; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, &rtv_desc, &srgb_rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); rtv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; U(rtv_desc).Texture2D.MipSlice = 0; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, &rtv_desc, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, color); check_texture_color(texture, expected_color, 1); ID3D11DeviceContext_ClearRenderTargetView(context, srgb_rtv, color); get_texture_readback(texture, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { BOOL broken_device = is_warp_device(device) || is_nvidia_device(device); DWORD color = get_readback_color(&rb, 80 + i * 160, 60 + j * 120, 0); ok(compare_color(color, expected_srgb_color, 1) || broken(compare_color(color, expected_color, 1) && broken_device), "Got unexpected color 0x%08x.\n", color); } } release_resource_readback(&rb); ID3D11RenderTargetView_Release(srgb_rtv); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_clear_render_target_view_3d(void) { static const float color[] = {0.1f, 0.5f, 0.3f, 0.75f}; static const float green[] = {0.0f, 1.0f, 0.0f, 0.5f}; struct d3d11_test_context test_context; D3D11_RENDER_TARGET_VIEW_DESC rtv_desc; D3D11_TEXTURE3D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Texture3D *texture; ID3D11Device *device; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 8; texture_desc.Height = 8; texture_desc.Depth = 4; texture_desc.MipLevels = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture3D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, color); check_texture3d_color(texture, 0xbf4c7f19, 1); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, green); check_texture3d_color(texture, 0x8000ff00, 1); ID3D11RenderTargetView_Release(rtv); ID3D11Texture3D_Release(texture); texture_desc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS; hr = ID3D11Device_CreateTexture3D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); rtv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; U(rtv_desc).Texture3D.MipSlice = 0; U(rtv_desc).Texture3D.FirstWSlice = 0; U(rtv_desc).Texture3D.WSize = ~0u; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, &rtv_desc, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, color); check_texture3d_color(texture, 0xbf95bc59, 1); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, green); check_texture3d_color(texture, 0x8000ff00, 1); ID3D11RenderTargetView_Release(rtv); ID3D11Texture3D_Release(texture); release_test_context(&test_context); } static void test_clear_depth_stencil_view(void) { D3D11_TEXTURE2D_DESC texture_desc; ID3D11Texture2D *depth_texture; ID3D11DeviceContext *context; ID3D11DepthStencilView *dsv; ID3D11Device *device; ULONG refcount; HRESULT hr; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } ID3D11Device_GetImmediateContext(device, &context); texture_desc.Width = 640; texture_desc.Height = 480; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_D32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &depth_texture); ok(SUCCEEDED(hr), "Failed to create depth texture, hr %#x.\n", hr); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)depth_texture, NULL, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); check_texture_float(depth_texture, 1.0f, 0); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.25f, 0); check_texture_float(depth_texture, 0.25f, 0); if (!enable_debug_layer) ID3D11DeviceContext_ClearDepthStencilView(context, NULL, D3D11_CLEAR_DEPTH, 1.0f, 0); check_texture_float(depth_texture, 0.25f, 0); ID3D11Texture2D_Release(depth_texture); ID3D11DepthStencilView_Release(dsv); texture_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &depth_texture); ok(SUCCEEDED(hr), "Failed to create depth texture, hr %#x.\n", hr); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)depth_texture, NULL, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); todo_wine check_texture_color(depth_texture, 0x00ffffff, 0); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 0.0f, 0xff); todo_wine check_texture_color(depth_texture, 0xff000000, 0); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0xff); check_texture_color(depth_texture, 0xffffffff, 0); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 0.0f, 0); check_texture_color(depth_texture, 0x00000000, 0); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0xff); todo_wine check_texture_color(depth_texture, 0x00ffffff, 0); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_STENCIL, 0.0f, 0xff); check_texture_color(depth_texture, 0xffffffff, 0); ID3D11Texture2D_Release(depth_texture); ID3D11DepthStencilView_Release(dsv); ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static unsigned int to_sint8(unsigned int x) { union { signed int s; unsigned int u; } bits; bits.u = x; return min(max(bits.s, -128), 127) & 0xff; } #define check_rgba_sint8(data, uvec) check_rgba_sint8_(__LINE__, data, uvec) static void check_rgba_sint8_(unsigned int line, DWORD data, const struct uvec4 *v) { unsigned int x = to_sint8(v->x); unsigned int y = to_sint8(v->y); unsigned int z = to_sint8(v->z); unsigned int w = to_sint8(v->w); DWORD expected[] = { /* Windows 7 - Nvidia, WARP */ (v->x & 0xff) | (v->y & 0xff) << 8 | (v->z & 0xff) << 16 | (v->w & 0xff) << 24, /* Windows 10 - AMD */ x | y << 8 | z << 16 | w << 24, /* Windows 10 - Intel */ x | x << 8 | x << 16 | x << 24, }; ok_(__FILE__, line)(data == expected[0] || data == expected[1] || broken(data == expected[2]), "Got %#x, expected %#x or %#x at %u, uvec4 %#x, %#x, %#x, %#x.\n", data, expected[0], expected[1], x, v->x, v->y, v->z, v->w); } static void test_clear_buffer_unordered_access_view(void) { D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; ID3D11UnorderedAccessView *uav, *uav2; struct device_desc device_desc; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Buffer *buffer; ID3D11Device *device; struct uvec4 uvec4; unsigned int i, x; ULONG refcount; HRESULT hr; RECT rect; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const struct uvec4 fe_uvec4 = {0xfefefefe, 0xfefefefe, 0xfefefefe, 0xfefefefe}; static const struct uvec4 uvec4_data[] = { {0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00000000, 0xffffffff, 0xffffffff, 0xffffffff}, {0xffffffff, 0x00000000, 0x00000000, 0x00000000}, {0x00000000, 0xffffffff, 0x00000000, 0x00000000}, {0x00000000, 0x00000000, 0xffffffff, 0x00000000}, {0x00000000, 0x00000000, 0x00000000, 0xffffffff}, {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}, {0x80000000, 0x80000000, 0x80000000, 0x80000000}, {0x000000ff, 0x00000080, 0x80000080, 0x00000080}, {0x000000ff, 0x0000007f, 0x000000ef, 0x000000fe}, {0x800000ff, 0x8000007f, 0x800000ef, 0x800000fe}, {0xfefefefe, 0xf0f0f0f0, 0xefefefef, 0x0f0f0f0f}, {0xaaaaaaaa, 0xdeadbeef, 0xdeadbabe, 0xdeadf00d}, {0x00000001, 0x00000002, 0x00000003, 0x00000004}, {0x000000ff, 0x000000fe, 0x000000fd, 0x000000fc}, {0x000000f2, 0x000000f1, 0x000000f0, 0x000000ef}, {0x0000000a, 0x0000000d, 0x0000000e, 0x0000000f}, {0x0000001a, 0x0000002d, 0x0000003e, 0x0000004f}, {0x00000050, 0x00000060, 0x00000070, 0x00000080}, {0x00000090, 0x000000a0, 0x000000b0, 0x000000c0}, {0x000000d0, 0x000000e0, 0x000000f0, 0x000000ff}, {0x00000073, 0x00000077, 0x0000007a, 0x0000007b}, {0x0000007c, 0x0000007d, 0x0000007e, 0x0000007f}, {0x80000001, 0x80000002, 0x80000003, 0x80000004}, {0x800000ff, 0x800000fe, 0x800000fd, 0x800000fc}, {0x800000f2, 0x800000f1, 0x800000f0, 0x800000ef}, {0x8000000a, 0x0000000d, 0x8000000e, 0x8000000f}, {0x8000001a, 0x8000002d, 0x8000003e, 0x8000004f}, {0x80000050, 0x80000060, 0x80000070, 0x00000080}, {0x80000090, 0x800000a0, 0x800000b0, 0x800000c0}, {0x800000d0, 0x800000e0, 0x800000f0, 0x800000ff}, {0x80000073, 0x80000077, 0x8000007a, 0x8000007b}, {0x8000007c, 0x8000007d, 0x8000007e, 0x8000007f}, {0x7fffff01, 0x7fffff02, 0x7fffff03, 0x7fffff04}, {0x7fffffff, 0x7ffffffe, 0x7ffffffd, 0x7ffffffc}, {0x7ffffff2, 0x7ffffff1, 0x7ffffff0, 0x7fffffef}, {0x7fffff0a, 0x7fffff0d, 0x7fffff0e, 0x7fffff0f}, {0x7fffff1a, 0x7fffff2d, 0x7fffff3e, 0x7fffff4f}, {0x7fffff50, 0x7fffff60, 0x7fffff70, 0x7fffff80}, {0x8fffff90, 0x7fffffa0, 0x7fffffb0, 0x7fffffc0}, {0x7fffffd0, 0x7fffffe0, 0x7ffffff0, 0x7fffffff}, {0x7fffff73, 0x7fffff77, 0x7fffff7a, 0x7fffff7b}, {0x7fffff7c, 0x7fffff7d, 0x7fffff7e, 0x7fffff7f}, {0xffffff01, 0xffffff02, 0xffffff03, 0xffffff04}, {0xffffffff, 0xfffffffe, 0xfffffffd, 0xfffffffc}, {0xfffffff2, 0xfffffff1, 0xfffffff0, 0xffffffef}, {0xffffff0a, 0xffffff0d, 0xffffff0e, 0xffffff0f}, {0xffffff1a, 0xffffff2d, 0xffffff3e, 0xffffff4f}, {0xffffff50, 0xffffff60, 0xffffff70, 0xffffff80}, {0xffffff90, 0xffffffa0, 0xffffffb0, 0xffffffc0}, {0xffffffd0, 0xffffffe0, 0xfffffff0, 0xffffffff}, {0xffffff73, 0xffffff77, 0xffffff7a, 0xffffff7b}, {0xffffff7c, 0xffffff7d, 0xffffff7e, 0xffffff7f}, }; device_desc.feature_level = &feature_level; device_desc.flags = 0; if (!(device = create_device(&device_desc))) { skip("Failed to create device for feature level %#x.\n", feature_level); return; } ID3D11Device_GetImmediateContext(device, &context); /* Structured buffer views */ buffer_desc.ByteWidth = 64; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = 0; buffer_desc.StructureByteStride = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; buffer_desc.StructureByteStride = 4; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, NULL, &uav); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_UNKNOWN; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 4; U(uav_desc).Buffer.Flags = 0; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav2); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(uvec4_data); ++i) { uvec4 = uvec4_data[i]; ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, &uvec4.x); get_buffer_readback(buffer, &rb); SetRect(&rect, 0, 0, buffer_desc.ByteWidth / sizeof(uvec4.x), 1); check_readback_data_color(&rb, &rect, uvec4.x, 0); release_resource_readback(&rb); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav2, &fe_uvec4.x); get_buffer_readback(buffer, &rb); SetRect(&rect, 0, 0, U(uav_desc).Buffer.NumElements, 1); check_readback_data_color(&rb, &rect, fe_uvec4.x, 0); SetRect(&rect, U(uav_desc).Buffer.NumElements, 0, buffer_desc.ByteWidth / sizeof(uvec4.x), 1); check_readback_data_color(&rb, &rect, uvec4.x, 0); release_resource_readback(&rb); } ID3D11Buffer_Release(buffer); ID3D11UnorderedAccessView_Release(uav); ID3D11UnorderedAccessView_Release(uav2); /* Raw buffer views */ buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 16; U(uav_desc).Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); U(uav_desc).Buffer.FirstElement = 8; U(uav_desc).Buffer.NumElements = 8; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav2); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(uvec4_data); ++i) { uvec4 = uvec4_data[i]; ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, &uvec4.x); get_buffer_readback(buffer, &rb); SetRect(&rect, 0, 0, buffer_desc.ByteWidth / sizeof(uvec4.x), 1); check_readback_data_color(&rb, &rect, uvec4.x, 0); release_resource_readback(&rb); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav2, &fe_uvec4.x); get_buffer_readback(buffer, &rb); SetRect(&rect, 0, 0, U(uav_desc).Buffer.FirstElement, 1); check_readback_data_color(&rb, &rect, uvec4.x, 0); SetRect(&rect, U(uav_desc).Buffer.FirstElement, 0, buffer_desc.ByteWidth / sizeof(uvec4.x), 1); check_readback_data_color(&rb, &rect, fe_uvec4.x, 0); release_resource_readback(&rb); } ID3D11Buffer_Release(buffer); ID3D11UnorderedAccessView_Release(uav); ID3D11UnorderedAccessView_Release(uav2); /* Typed buffer views */ buffer_desc.MiscFlags = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_R32_SINT; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 16; U(uav_desc).Buffer.Flags = 0; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); U(uav_desc).Buffer.FirstElement = 9; U(uav_desc).Buffer.NumElements = 7; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav2); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(uvec4_data); ++i) { uvec4 = uvec4_data[i]; ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, &uvec4.x); get_buffer_readback(buffer, &rb); SetRect(&rect, 0, 0, buffer_desc.ByteWidth / sizeof(uvec4.x), 1); check_readback_data_color(&rb, &rect, uvec4.x, 0); release_resource_readback(&rb); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav2, &fe_uvec4.x); get_buffer_readback(buffer, &rb); SetRect(&rect, 0, 0, U(uav_desc).Buffer.FirstElement, 1); check_readback_data_color(&rb, &rect, uvec4.x, 0); SetRect(&rect, U(uav_desc).Buffer.FirstElement, 0, buffer_desc.ByteWidth / sizeof(uvec4.x), 1); check_readback_data_color(&rb, &rect, fe_uvec4.x, 0); release_resource_readback(&rb); } ID3D11UnorderedAccessView_Release(uav); ID3D11UnorderedAccessView_Release(uav2); uav_desc.Format = DXGI_FORMAT_R32G32B32A32_SINT; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 4; U(uav_desc).Buffer.Flags = 0; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); U(uav_desc).Buffer.FirstElement = 2; U(uav_desc).Buffer.NumElements = 2; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav2); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(uvec4_data); ++i) { const struct uvec4 *data = NULL; BOOL all_match; uvec4 = uvec4_data[i]; ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, &uvec4.x); get_buffer_readback(buffer, &rb); for (x = 0, all_match = TRUE; x < buffer_desc.ByteWidth / sizeof(uvec4); ++x) { const struct uvec4 broken_result = {uvec4.x, uvec4.x, uvec4.x, uvec4.x}; /* Intel */ data = get_readback_uvec4(&rb, x, 0); if (!(compare_uvec4(data, &uvec4) || broken(compare_uvec4(data, &broken_result)))) all_match = FALSE; } ok(all_match, "Got {%#x, %#x, %#x, %#x}, expected {%#x, %#x, %#x, %#x} at %u.\n", data->x, data->y, data->z, data->w, uvec4.x, uvec4.y, uvec4.z, uvec4.w, x); release_resource_readback(&rb); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav2, &fe_uvec4.x); get_buffer_readback(buffer, &rb); for (x = 0, all_match = TRUE; x < buffer_desc.ByteWidth / sizeof(uvec4); ++x) { struct uvec4 broken_result; data = get_readback_uvec4(&rb, x, 0); uvec4 = U(uav_desc).Buffer.FirstElement <= x ? fe_uvec4 : uvec4_data[i]; broken_result.x = broken_result.y = broken_result.z = broken_result.w = uvec4.x; if (!(compare_uvec4(data, &uvec4) || broken(compare_uvec4(data, &broken_result)))) all_match = FALSE; } ok(all_match, "Got {%#x, %#x, %#x, %#x}, expected {%#x, %#x, %#x, %#x} at %u.\n", data->x, data->y, data->z, data->w, uvec4.x, uvec4.y, uvec4.z, uvec4.w, x); release_resource_readback(&rb); } uvec4.x = uvec4.y = uvec4.z = uvec4.w = 0xdeadbeef; ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, &uvec4.x); ID3D11UnorderedAccessView_Release(uav); ID3D11UnorderedAccessView_Release(uav2); uav_desc.Format = DXGI_FORMAT_R8G8B8A8_SINT; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 16; U(uav_desc).Buffer.Flags = 0; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); U(uav_desc).Buffer.FirstElement = 8; U(uav_desc).Buffer.NumElements = 8; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav2); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(uvec4_data); ++i) { uvec4 = uvec4_data[i]; ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, &uvec4.x); get_buffer_readback(buffer, &rb); todo_wine check_rgba_sint8(get_readback_color(&rb, 0, 0, 0), &uvec4); todo_wine check_rgba_sint8(get_readback_color(&rb, 7, 0, 0), &uvec4); todo_wine check_rgba_sint8(get_readback_color(&rb, 15, 0, 0), &uvec4); release_resource_readback(&rb); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav2, &fe_uvec4.x); get_buffer_readback(buffer, &rb); todo_wine check_rgba_sint8(get_readback_color(&rb, 0, 0, 0), &uvec4); todo_wine check_rgba_sint8(get_readback_color(&rb, U(uav_desc).Buffer.FirstElement - 1, 0, 0), &uvec4); todo_wine check_rgba_sint8(get_readback_color(&rb, U(uav_desc).Buffer.FirstElement, 0, 0), &fe_uvec4); release_resource_readback(&rb); } ID3D11UnorderedAccessView_Release(uav); ID3D11UnorderedAccessView_Release(uav2); ID3D11Buffer_Release(buffer); ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_initial_depth_stencil_state(void) { static const struct vec4 green = {0.0f, 1.0f, 0.0f, 1.0f}; static const struct vec4 red = {1.0f, 0.0f, 0.0f, 1.0f}; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11DepthStencilView *dsv; ID3D11Texture2D *texture; ID3D11Device *device; unsigned int count; D3D11_VIEWPORT vp; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_D32_FLOAT; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, NULL, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, dsv); count = 1; ID3D11DeviceContext_RSGetViewports(context, &count, &vp); /* check if depth function is D3D11_COMPARISON_LESS */ ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.5f, 0); set_viewport(context, vp.TopLeftX, vp.TopLeftY, vp.Width, vp.Height, 0.4f, 0.4f); draw_color_quad(&test_context, &green); draw_color_quad(&test_context, &red); set_viewport(context, vp.TopLeftX, vp.TopLeftY, vp.Width, vp.Height, 0.6f, 0.6f); draw_color_quad(&test_context, &red); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); check_texture_float(texture, 0.4f, 1); ID3D11DepthStencilView_Release(dsv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_draw_depth_only(void) { struct d3d11_test_context test_context; ID3D11PixelShader *ps_color, *ps_depth; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11DepthStencilView *dsv; struct resource_readback rb; ID3D11Texture2D *texture; ID3D11Device *device; unsigned int i, j; struct vec4 depth; ID3D11Buffer *cb; HRESULT hr; static const DWORD ps_color_code[] = { #if 0 float4 main(float4 position : SV_POSITION) : SV_Target { return float4(0.0, 1.0, 0.0, 1.0); } #endif 0x43425844, 0x30240e72, 0x012f250c, 0x8673c6ea, 0x392e4cec, 0x00000001, 0x000000d4, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03000065, 0x001020f2, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const DWORD ps_depth_code[] = { #if 0 float depth; float main() : SV_Depth { return depth; } #endif 0x43425844, 0x91af6cd0, 0x7e884502, 0xcede4f54, 0x6f2c9326, 0x00000001, 0x000000b0, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0xffffffff, 0x00000e01, 0x445f5653, 0x68747065, 0xababab00, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x02000065, 0x0000c001, 0x05000036, 0x0000c001, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(depth), NULL); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_D32_FLOAT; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, NULL, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_color_code, sizeof(ps_color_code), NULL, &ps_color); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_depth_code, sizeof(ps_depth_code), NULL, &ps_depth); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_PSSetShader(context, ps_color, NULL, 0); ID3D11DeviceContext_OMSetRenderTargets(context, 0, NULL, dsv); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); check_texture_float(texture, 1.0f, 1); draw_quad(&test_context); check_texture_float(texture, 0.0f, 1); ID3D11DeviceContext_PSSetShader(context, ps_depth, NULL, 0); depth.x = 0.7f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &depth, 0, 0); draw_quad(&test_context); check_texture_float(texture, 0.0f, 1); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); check_texture_float(texture, 1.0f, 1); draw_quad(&test_context); check_texture_float(texture, 0.7f, 1); depth.x = 0.8f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &depth, 0, 0); draw_quad(&test_context); check_texture_float(texture, 0.7f, 1); depth.x = 0.5f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &depth, 0, 0); draw_quad(&test_context); check_texture_float(texture, 0.5f, 1); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { depth.x = 1.0f / 16.0f * (j + 4 * i); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &depth, 0, 0); set_viewport(context, 160.0f * j, 120.0f * i, 160.0f, 120.0f, 0.0f, 1.0f); draw_quad(&test_context); } } get_texture_readback(texture, 0, &rb); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { float obtained_depth, expected_depth; obtained_depth = get_readback_float(&rb, 80 + j * 160, 60 + i * 120); expected_depth = 1.0f / 16.0f * (j + 4 * i); ok(compare_float(obtained_depth, expected_depth, 1), "Got unexpected depth %.8e at (%u, %u), expected %.8e.\n", obtained_depth, j, i, expected_depth); } } release_resource_readback(&rb); ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps_color); ID3D11PixelShader_Release(ps_depth); ID3D11DepthStencilView_Release(dsv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_draw_uav_only(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11UnorderedAccessView *uav; ID3D11DeviceContext *context; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DWORD ps_code[] = { #if 0 RWTexture2D u; void main() { InterlockedAdd(u[uint2(0, 0)], 1); } #endif 0x43425844, 0x237a8398, 0xe7b34c17, 0xa28c91a4, 0xb3614d73, 0x00000001, 0x0000009c, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000048, 0x00000050, 0x00000012, 0x0100086a, 0x0400189c, 0x0011e000, 0x00000000, 0x00003333, 0x0a0000ad, 0x0011e000, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004001, 0x00000001, 0x0100003e, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const UINT values[4] = {0}; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 1; texture_desc.Height = 1; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32_SINT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)texture, NULL, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, 0, NULL, NULL, 0, 1, &uav, NULL); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, values); set_viewport(context, 0.0f, 0.0f, 10.0f, 10.0f, 0.0f, 0.0f); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, values); draw_quad(&test_context); check_texture_color(texture, 100, 1); draw_quad(&test_context); draw_quad(&test_context); draw_quad(&test_context); draw_quad(&test_context); check_texture_color(texture, 500, 1); ID3D11PixelShader_Release(ps); ID3D11Texture2D_Release(texture); ID3D11UnorderedAccessView_Release(uav); release_test_context(&test_context); } static void test_cb_relative_addressing(void) { struct d3d11_test_context test_context; ID3D11Buffer *colors_cb, *index_cb; unsigned int i, index[4] = {0}; ID3D11DeviceContext *context; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DWORD vs_code[] = { #if 0 int color_index; cbuffer colors { float4 colors[8]; }; struct vs_in { float4 position : POSITION; }; struct vs_out { float4 position : SV_POSITION; float4 color : COLOR; }; vs_out main(const vs_in v) { vs_out o; o.position = v.position; o.color = colors[color_index]; return o; } #endif 0x43425844, 0xc2eb30bf, 0x2868c855, 0xaa34b609, 0x1f4957d4, 0x00000001, 0x00000164, 0x00000003, 0x0000002c, 0x00000060, 0x000000b4, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x58454853, 0x000000a8, 0x00010050, 0x0000002a, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04000859, 0x00208e46, 0x00000001, 0x00000008, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x02000068, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x06000036, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x07000036, 0x001020f2, 0x00000001, 0x04208e46, 0x00000001, 0x0010000a, 0x00000000, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 struct ps_in { float4 position : SV_POSITION; float4 color : COLOR; }; float4 main(const ps_in v) : SV_TARGET { return v.color; } #endif 0x43425844, 0x1a6def50, 0x9c069300, 0x7cce68f0, 0x621239b9, 0x00000001, 0x000000f8, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x58454853, 0x0000003c, 0x00000050, 0x0000000f, 0x0100086a, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const struct { float color[4]; } colors[10] = { {{0.0f, 0.0f, 0.0f, 1.0f}}, {{0.0f, 0.0f, 1.0f, 0.0f}}, {{0.0f, 0.0f, 1.0f, 1.0f}}, {{0.0f, 1.0f, 0.0f, 0.0f}}, {{0.0f, 1.0f, 0.0f, 1.0f}}, {{0.0f, 1.0f, 1.0f, 0.0f}}, {{0.0f, 1.0f, 1.0f, 1.0f}}, {{1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, 0.0f, 0.0f, 1.0f}}, {{1.0f, 0.0f, 1.0f, 0.0f}}, }; static const struct { unsigned int index; DWORD expected; } test_data[] = { {0, 0xff000000}, {1, 0x00ff0000}, {2, 0xffff0000}, {3, 0x0000ff00}, {4, 0xff00ff00}, {5, 0x00ffff00}, {6, 0xffffff00}, {7, 0x000000ff}, {8, 0xff0000ff}, {9, 0x00ff00ff}, }; static const float white_color[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; colors_cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(colors), &colors); index_cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(index), NULL); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_VSSetConstantBuffers(context, 0, 1, &index_cb); ID3D11DeviceContext_VSSetConstantBuffers(context, 1, 1, &colors_cb); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); for (i = 0; i < ARRAY_SIZE(test_data); ++i) { ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white_color); index[0] = test_data[i].index; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)index_cb, 0, NULL, &index, 0, 0); draw_quad_vs(&test_context, vs_code, sizeof(vs_code)); check_texture_color(test_context.backbuffer, test_data[i].expected, 1); } ID3D11Buffer_Release(index_cb); ID3D11Buffer_Release(colors_cb); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_vs_input_relative_addressing(void) { struct d3d11_test_context test_context; ID3D11DeviceContext *context; unsigned int offset, stride; unsigned int index[4] = {0}; ID3D11PixelShader *ps; ID3D11Buffer *vb, *cb; ID3D11Device *device; unsigned int i; HRESULT hr; static const DWORD vs_code[] = { #if 0 struct vertex { float4 position : POSITION; float4 colors[4] : COLOR; }; uint index; void main(vertex vin, out float4 position : SV_Position, out float4 color : COLOR) { position = vin.position; color = vin.colors[index]; } #endif 0x43425844, 0x8623dd89, 0xe37fecf5, 0xea3fdfe1, 0xdf36e4e4, 0x00000001, 0x000001f4, 0x00000003, 0x0000002c, 0x000000c4, 0x00000118, 0x4e475349, 0x00000090, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000089, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x00000089, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x00000089, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000f0f, 0x00000089, 0x00000003, 0x00000000, 0x00000003, 0x00000004, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x000000d4, 0x00010040, 0x00000035, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x0300005f, 0x001010f2, 0x00000002, 0x0300005f, 0x001010f2, 0x00000003, 0x0300005f, 0x001010f2, 0x00000004, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x02000068, 0x00000001, 0x0400005b, 0x001010f2, 0x00000001, 0x00000004, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x06000036, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x07000036, 0x001020f2, 0x00000001, 0x00d01e46, 0x00000001, 0x0010000a, 0x00000000, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 struct vs_out { float4 position : SV_POSITION; float4 color : COLOR; }; float4 main(struct vs_out i) : SV_TARGET { return i.color; } #endif 0x43425844, 0xe2087fa6, 0xa35fbd95, 0x8e585b3f, 0x67890f54, 0x00000001, 0x000000f4, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1}, {"COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 4, D3D11_INPUT_PER_INSTANCE_DATA, 1}, {"COLOR", 2, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 8, D3D11_INPUT_PER_INSTANCE_DATA, 1}, {"COLOR", 3, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 12, D3D11_INPUT_PER_INSTANCE_DATA, 1}, }; static const unsigned int colors[] = {0xff0000ff, 0xff00ff00, 0xffff0000, 0xff0f0f0f}; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &test_context.input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(index), NULL); ID3D11DeviceContext_VSSetConstantBuffers(context, 0, 1, &cb); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(colors), colors); stride = sizeof(colors); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 1, 1, &vb, &stride, &offset); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); for (i = 0; i < ARRAY_SIZE(colors); ++i) { *index = i; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, index, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_quad_vs(&test_context, vs_code, sizeof(vs_code)); check_texture_color(test_context.backbuffer, colors[i], 1); } ID3D11Buffer_Release(cb); ID3D11Buffer_Release(vb); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_getdc(void) { static const struct { const char *name; DXGI_FORMAT format; BOOL getdc_supported; } testdata[] = { {"B8G8R8A8_UNORM", DXGI_FORMAT_B8G8R8A8_UNORM, TRUE }, {"B8G8R8A8_TYPELESS", DXGI_FORMAT_B8G8R8A8_TYPELESS, TRUE }, {"B8G8R8A8_UNORM_SRGB", DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, TRUE }, {"B8G8R8X8_UNORM", DXGI_FORMAT_B8G8R8X8_UNORM, FALSE }, {"B8G8R8X8_TYPELESS", DXGI_FORMAT_B8G8R8X8_TYPELESS, FALSE }, {"B8G8R8X8_UNORM_SRGB", DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, FALSE }, }; struct device_desc device_desc; D3D11_TEXTURE2D_DESC desc; ID3D11Texture2D *texture; IDXGISurface1 *surface; ID3D11Device *device; unsigned int i; ULONG refcount; HRESULT hr; HDC dc; device_desc.feature_level = NULL; device_desc.flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; if (!(device = create_device(&device_desc))) { skip("Failed to create device.\n"); return; } /* Without D3D11_RESOURCE_MISC_GDI_COMPATIBLE. */ desc.Width = 512; desc.Height = 512; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Texture2D_QueryInterface(texture, &IID_IDXGISurface1, (void**)&surface); ok(SUCCEEDED(hr), "Failed to get IDXGISurface1 interface, hr %#x.\n", hr); hr = IDXGISurface1_GetDC(surface, FALSE, &dc); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); IDXGISurface1_Release(surface); ID3D11Texture2D_Release(texture); desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Texture2D_QueryInterface(texture, &IID_IDXGISurface1, (void**)&surface); ok(SUCCEEDED(hr), "Failed to get IDXGISurface1 interface, hr %#x.\n", hr); hr = IDXGISurface1_ReleaseDC(surface, NULL); todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); hr = IDXGISurface1_GetDC(surface, FALSE, &dc); ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr); hr = IDXGISurface1_ReleaseDC(surface, NULL); ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr); IDXGISurface1_Release(surface); ID3D11Texture2D_Release(texture); for (i = 0; i < ARRAY_SIZE(testdata); ++i) { static const unsigned int bit_count = 32; unsigned int width_bytes; DIBSECTION dib; HBITMAP bitmap; DWORD type; int size; desc.Width = 64; desc.Height = 64; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = testdata[i].format; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_STAGING; desc.BindFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); ID3D11Texture2D_Release(texture); /* STAGING usage, requesting GDI compatibility mode. */ desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(FAILED(hr), "Expected CreateTexture2D to fail, hr %#x.\n", hr); desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); if (testdata[i].getdc_supported) ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name); else ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name); if (FAILED(hr)) continue; hr = ID3D11Texture2D_QueryInterface(texture, &IID_IDXGISurface1, (void**)&surface); ok(SUCCEEDED(hr), "Failed to get IDXGISurface1 interface, hr %#x.\n", hr); dc = (void *)0x1234; hr = IDXGISurface1_GetDC(surface, FALSE, &dc); ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name); if (FAILED(hr)) { IDXGISurface1_Release(surface); ID3D11Texture2D_Release(texture); continue; } type = GetObjectType(dc); ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name); bitmap = GetCurrentObject(dc, OBJ_BITMAP); type = GetObjectType(bitmap); ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name); size = GetObjectA(bitmap, sizeof(dib), &dib); ok(size == sizeof(dib) || broken(size == sizeof(dib.dsBm)), "Got unexpected size %d for format %s.\n", size, testdata[i].name); ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n", dib.dsBm.bmType, testdata[i].name); ok(dib.dsBm.bmWidth == 64, "Got unexpected width %d for format %s.\n", dib.dsBm.bmWidth, testdata[i].name); ok(dib.dsBm.bmHeight == 64, "Got unexpected height %d for format %s.\n", dib.dsBm.bmHeight, testdata[i].name); width_bytes = ((dib.dsBm.bmWidth * bit_count + 31) >> 3) & ~3; ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n", dib.dsBm.bmWidthBytes, testdata[i].name); ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n", dib.dsBm.bmPlanes, testdata[i].name); ok(dib.dsBm.bmBitsPixel == bit_count, "Got unexpected bit count %d for format %s.\n", dib.dsBm.bmBitsPixel, testdata[i].name); if (size == sizeof(dib)) ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n", dib.dsBm.bmBits, testdata[i].name); else ok(!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n", dib.dsBm.bmBits, testdata[i].name); if (size == sizeof(dib)) { ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n", dib.dsBmih.biSize, testdata[i].name); ok(dib.dsBmih.biWidth == 64, "Got unexpected width %d for format %s.\n", dib.dsBmih.biHeight, testdata[i].name); ok(dib.dsBmih.biHeight == 64, "Got unexpected height %d for format %s.\n", dib.dsBmih.biHeight, testdata[i].name); ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n", dib.dsBmih.biPlanes, testdata[i].name); ok(dib.dsBmih.biBitCount == bit_count, "Got unexpected bit count %u for format %s.\n", dib.dsBmih.biBitCount, testdata[i].name); ok(dib.dsBmih.biCompression == BI_RGB, "Got unexpected compression %#x for format %s.\n", dib.dsBmih.biCompression, testdata[i].name); ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n", dib.dsBmih.biSizeImage, testdata[i].name); ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n", dib.dsBmih.biXPelsPerMeter, testdata[i].name); ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n", dib.dsBmih.biYPelsPerMeter, testdata[i].name); ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n", dib.dsBmih.biClrUsed, testdata[i].name); ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n", dib.dsBmih.biClrImportant, testdata[i].name); ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2], "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n", dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name); ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, testdata[i].name); ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, testdata[i].name); } hr = IDXGISurface1_ReleaseDC(surface, NULL); ok(hr == S_OK, "Failed to release DC, hr %#x.\n", hr); IDXGISurface1_Release(surface); ID3D11Texture2D_Release(texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_shader_stage_input_output_matching(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11Texture2D *render_target; ID3D11RenderTargetView *rtv[2]; ID3D11DeviceContext *context; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DWORD vs_code[] = { #if 0 struct output { float4 position : SV_PoSiTion; float4 color0 : COLOR0; float4 color1 : COLOR1; }; void main(uint id : SV_VertexID, out output o) { float2 coords = float2((id << 1) & 2, id & 2); o.position = float4(coords * float2(2, -2) + float2(-1, 1), 0, 1); o.color0 = float4(1.0f, 0.0f, 0.0f, 1.0f); o.color1 = float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x93c216a1, 0xbaa7e8d4, 0xd5368c6a, 0x4e889e07, 0x00000001, 0x00000224, 0x00000003, 0x0000002c, 0x00000060, 0x000000cc, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000006, 0x00000001, 0x00000000, 0x00000101, 0x565f5653, 0x65747265, 0x00444978, 0x4e47534f, 0x00000064, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x0000005c, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x0000000f, 0x505f5653, 0x5469536f, 0x006e6f69, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000150, 0x00010040, 0x00000054, 0x04000060, 0x00101012, 0x00000000, 0x00000006, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x02000068, 0x00000001, 0x07000029, 0x00100012, 0x00000000, 0x0010100a, 0x00000000, 0x00004001, 0x00000001, 0x07000001, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000002, 0x07000001, 0x00100042, 0x00000000, 0x0010100a, 0x00000000, 0x00004001, 0x00000002, 0x05000056, 0x00100032, 0x00000000, 0x00100086, 0x00000000, 0x0f000032, 0x00102032, 0x00000000, 0x00100046, 0x00000000, 0x00004002, 0x40000000, 0xc0000000, 0x00000000, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x08000036, 0x001020f2, 0x00000002, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 struct input { float4 position : SV_PoSiTiOn; float4 color1 : COLOR1; float4 color0 : COLOR0; }; struct output { float4 target0 : SV_Target0; float4 target1 : SV_Target1; }; void main(const in input i, out output o) { o.target0 = i.color0; o.target1 = i.color1; } #endif 0x43425844, 0x620ef963, 0xed8f19fe, 0x7b3a0a53, 0x126ce021, 0x00000001, 0x00000150, 0x00000003, 0x0000002c, 0x00000098, 0x000000e4, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5469536f, 0x006e4f69, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x00000044, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000038, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000064, 0x00000040, 0x00000019, 0x03001062, 0x001010f2, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000002, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &render_target); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); rtv[0] = test_context.backbuffer_rtv; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)render_target, NULL, &rtv[1]); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D11DeviceContext_OMSetRenderTargets(context, 2, rtv, NULL); ID3D11DeviceContext_Draw(context, 3, 0); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); check_texture_color(render_target, 0xff0000ff, 0); ID3D11RenderTargetView_Release(rtv[1]); ID3D11Texture2D_Release(render_target); ID3D11PixelShader_Release(ps); ID3D11VertexShader_Release(vs); release_test_context(&test_context); } static void test_shader_interstage_interface(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11InputLayout *input_layout; ID3D11Texture2D *render_target; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; UINT stride, offset; ID3D11Buffer *vb; unsigned int i; HRESULT hr; static const DWORD vs_code[] = { #if 0 struct vertex { float4 position : SV_Position; float2 t0 : TEXCOORD0; nointerpolation float t1 : TEXCOORD1; uint t2 : TEXCOORD2; uint t3 : TEXCOORD3; float t4 : TEXCOORD4; }; void main(in vertex vin, out vertex vout) { vout = vin; } #endif 0x43425844, 0xd55780bf, 0x76866b06, 0x45d697a2, 0xafac2ecd, 0x00000001, 0x000002bc, 0x00000003, 0x0000002c, 0x000000e4, 0x0000019c, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x000000a4, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x000000a4, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000101, 0x000000a4, 0x00000002, 0x00000000, 0x00000001, 0x00000003, 0x00000101, 0x000000a4, 0x00000003, 0x00000000, 0x00000001, 0x00000004, 0x00000101, 0x000000a4, 0x00000004, 0x00000000, 0x00000003, 0x00000005, 0x00000101, 0x505f5653, 0x7469736f, 0x006e6f69, 0x43584554, 0x44524f4f, 0xababab00, 0x4e47534f, 0x000000b0, 0x00000006, 0x00000008, 0x00000098, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x000000a4, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000c03, 0x000000a4, 0x00000004, 0x00000000, 0x00000003, 0x00000001, 0x00000b04, 0x000000a4, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000e01, 0x000000a4, 0x00000002, 0x00000000, 0x00000001, 0x00000002, 0x00000d02, 0x000000a4, 0x00000003, 0x00000000, 0x00000001, 0x00000002, 0x00000b04, 0x505f5653, 0x7469736f, 0x006e6f69, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x00000118, 0x00010040, 0x00000046, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101012, 0x00000002, 0x0300005f, 0x00101012, 0x00000003, 0x0300005f, 0x00101012, 0x00000004, 0x0300005f, 0x00101012, 0x00000005, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102032, 0x00000001, 0x03000065, 0x00102042, 0x00000001, 0x03000065, 0x00102012, 0x00000002, 0x03000065, 0x00102022, 0x00000002, 0x03000065, 0x00102042, 0x00000002, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x00102032, 0x00000001, 0x00101046, 0x00000001, 0x05000036, 0x00102042, 0x00000001, 0x0010100a, 0x00000005, 0x05000036, 0x00102012, 0x00000002, 0x0010100a, 0x00000002, 0x05000036, 0x00102022, 0x00000002, 0x0010100a, 0x00000003, 0x05000036, 0x00102042, 0x00000002, 0x0010100a, 0x00000004, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 void main(float4 position : SV_Position, float2 t0 : TEXCOORD0, nointerpolation float t1 : TEXCOORD1, uint t2 : TEXCOORD2, uint t3 : TEXCOORD3, float t4 : TEXCOORD4, out float4 o : SV_Target) { o.x = t0.y + t1; o.y = t2 + t3; o.z = t4; o.w = t0.x; } #endif 0x43425844, 0x8a7ef706, 0xc8f2cbf1, 0x83a05df1, 0xfab8e613, 0x00000001, 0x000001dc, 0x00000003, 0x0000002c, 0x000000e4, 0x00000118, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x000000a4, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x000000a4, 0x00000004, 0x00000000, 0x00000003, 0x00000001, 0x00000404, 0x000000a4, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000101, 0x000000a4, 0x00000002, 0x00000000, 0x00000001, 0x00000002, 0x00000202, 0x000000a4, 0x00000003, 0x00000000, 0x00000001, 0x00000002, 0x00000404, 0x505f5653, 0x7469736f, 0x006e6f69, 0x43584554, 0x44524f4f, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000bc, 0x00000040, 0x0000002f, 0x03001062, 0x00101032, 0x00000001, 0x03001062, 0x00101042, 0x00000001, 0x03000862, 0x00101012, 0x00000002, 0x03000862, 0x00101022, 0x00000002, 0x03000862, 0x00101042, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0700001e, 0x00100012, 0x00000000, 0x0010101a, 0x00000002, 0x0010102a, 0x00000002, 0x05000056, 0x00102022, 0x00000000, 0x0010000a, 0x00000000, 0x07000000, 0x00102012, 0x00000000, 0x0010101a, 0x00000001, 0x0010100a, 0x00000002, 0x05000036, 0x001020c2, 0x00000000, 0x001012a6, 0x00000001, 0x0100003e, }; static const DWORD ps_partial_input_code[] = { #if 0 void main(float4 position : SV_Position, float2 t0 : TEXCOORD0, nointerpolation float t1 : TEXCOORD1, uint t2 : TEXCOORD2, uint t3 : TEXCOORD3, out float4 o : SV_Target) { o.x = t0.y + t1; o.y = t2 + t3; o.z = 0.0f; o.w = t0.x; } #endif 0x43425844, 0x5b1db356, 0xaa5a5e9d, 0xb916a081, 0x61e6dcb1, 0x00000001, 0x000001cc, 0x00000003, 0x0000002c, 0x000000cc, 0x00000100, 0x4e475349, 0x00000098, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000008c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x0000008c, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000101, 0x0000008c, 0x00000002, 0x00000000, 0x00000001, 0x00000002, 0x00000202, 0x0000008c, 0x00000003, 0x00000000, 0x00000001, 0x00000002, 0x00000404, 0x505f5653, 0x7469736f, 0x006e6f69, 0x43584554, 0x44524f4f, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c4, 0x00000040, 0x00000031, 0x03001062, 0x00101032, 0x00000001, 0x03000862, 0x00101012, 0x00000002, 0x03000862, 0x00101022, 0x00000002, 0x03000862, 0x00101042, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0700001e, 0x00100012, 0x00000000, 0x0010102a, 0x00000002, 0x0010101a, 0x00000002, 0x05000056, 0x00102022, 0x00000000, 0x0010000a, 0x00000000, 0x07000000, 0x00102012, 0x00000000, 0x0010101a, 0x00000001, 0x0010100a, 0x00000002, 0x05000036, 0x00102042, 0x00000000, 0x00004001, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x0010100a, 0x00000001, 0x0100003e, }; static const DWORD ps_single_input_code[] = { #if 0 void main(float4 position : SV_Position, float2 t0 : TEXCOORD0, out float4 o : SV_Target) { o.x = t0.x; o.y = t0.y; o.z = 1.0f; o.w = 2.0f; } #endif 0x43425844, 0x7cc601b6, 0xc65b8bdb, 0x54d0f606, 0x9cc74d3d, 0x00000001, 0x00000118, 0x00000003, 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x505f5653, 0x7469736f, 0x006e6f69, 0x43584554, 0x44524f4f, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000058, 0x00000040, 0x00000016, 0x03001062, 0x00101032, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00101046, 0x00000001, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x3f800000, 0x40000000, 0x0100003e, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"SV_POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 1, DXGI_FORMAT_R32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 2, DXGI_FORMAT_R32_UINT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 3, DXGI_FORMAT_R32_UINT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 4, DXGI_FORMAT_R32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const struct { struct vec2 position; struct vec2 t0; float t1; unsigned int t2; unsigned int t3; float t4; } quad[] = { {{-1.0f, -1.0f}, {3.0f, 5.0f}, 5.0f, 2, 6, 7.0f}, {{-1.0f, 1.0f}, {3.0f, 5.0f}, 5.0f, 2, 6, 7.0f}, {{ 1.0f, -1.0f}, {3.0f, 5.0f}, 5.0f, 2, 6, 7.0f}, {{ 1.0f, 1.0f}, {3.0f, 5.0f}, 5.0f, 2, 6, 7.0f}, }; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const struct { const DWORD *ps_code; size_t ps_size; struct vec4 expected_result; } tests[] = { {ps_code, sizeof(ps_code), {10.0f, 8.0f, 7.0f, 3.0f}}, {ps_partial_input_code, sizeof(ps_partial_input_code), {10.0f, 8.0f, 0.0f, 3.0f}}, {ps_single_input_code, sizeof(ps_single_input_code), {3.0f, 5.0f, 1.0f, 2.0f}}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &render_target); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)render_target, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(quad), quad); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, white); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); offset = 0; stride = sizeof(*quad); ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, &stride, &offset); for (i = 0; i < ARRAY_SIZE(tests); ++i) { hr = ID3D11Device_CreatePixelShader(device, tests[i].ps_code, tests[i].ps_size, NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_vec4(render_target, &tests[i].expected_result, 0); ID3D11PixelShader_Release(ps); } ID3D11InputLayout_Release(input_layout); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(render_target); ID3D11VertexShader_Release(vs); ID3D11Buffer_Release(vb); release_test_context(&test_context); } static void test_sm4_if_instruction(void) { struct d3d11_test_context test_context; ID3D11PixelShader *ps_if_nz, *ps_if_z; ID3D11DeviceContext *context; ID3D11Device *device; unsigned int bits[4]; DWORD expected_color; ID3D11Buffer *cb; unsigned int i; HRESULT hr; static const DWORD ps_if_nz_code[] = { #if 0 uint bits; float4 main() : SV_TARGET { if (bits) return float4(0.0f, 1.0f, 0.0f, 1.0f); else return float4(1.0f, 0.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x2a94f6f1, 0xdbe88943, 0x3426a708, 0x09cec990, 0x00000001, 0x00000100, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000088, 0x00000040, 0x00000022, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x0404001f, 0x0020800a, 0x00000000, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000012, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000015, 0x0100003e, }; static const DWORD ps_if_z_code[] = { #if 0 uint bits; float4 main() : SV_TARGET { if (!bits) return float4(0.0f, 1.0f, 0.0f, 1.0f); else return float4(1.0f, 0.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x2e3030ca, 0x94c8610c, 0xdf0c1b1f, 0x80f2ca2c, 0x00000001, 0x00000100, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000088, 0x00000040, 0x00000022, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x0400001f, 0x0020800a, 0x00000000, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000012, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000015, 0x0100003e, }; static unsigned int bit_patterns[] = { 0x00000000, 0x00000001, 0x10010001, 0x10000000, 0x80000000, 0xffff0000, 0x0000ffff, 0xffffffff, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_if_nz_code, sizeof(ps_if_nz_code), NULL, &ps_if_nz); ok(SUCCEEDED(hr), "Failed to create if_nz pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_if_z_code, sizeof(ps_if_z_code), NULL, &ps_if_z); ok(SUCCEEDED(hr), "Failed to create if_z pixel shader, hr %#x.\n", hr); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(bits), NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); for (i = 0; i < ARRAY_SIZE(bit_patterns); ++i) { *bits = bit_patterns[i]; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, bits, 0, 0); ID3D11DeviceContext_PSSetShader(context, ps_if_nz, NULL, 0); expected_color = *bits ? 0xff00ff00 : 0xff0000ff; draw_quad(&test_context); check_texture_color(test_context.backbuffer, expected_color, 0); ID3D11DeviceContext_PSSetShader(context, ps_if_z, NULL, 0); expected_color = *bits ? 0xff0000ff : 0xff00ff00; draw_quad(&test_context); check_texture_color(test_context.backbuffer, expected_color, 0); } ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps_if_z); ID3D11PixelShader_Release(ps_if_nz); release_test_context(&test_context); } static void test_sm4_breakc_instruction(void) { struct d3d11_test_context test_context; ID3D11DeviceContext *context; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DWORD ps_breakc_nz_code[] = { #if 0 float4 main() : SV_TARGET { uint counter = 0; for (uint i = 0; i < 255; ++i) ++counter; if (counter == 255) return float4(0.0f, 1.0f, 0.0f, 1.0f); else return float4(1.0f, 0.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x065ac80a, 0x24369e7e, 0x218d5dc1, 0x3532868c, 0x00000001, 0x00000188, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000110, 0x00000040, 0x00000044, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x08000036, 0x00100032, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x07000050, 0x00100042, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x000000ff, 0x03040003, 0x0010002a, 0x00000000, 0x0a00001e, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00004002, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x01000016, 0x07000020, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x000000ff, 0x0304001f, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000012, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000015, 0x0100003e, }; static const DWORD ps_breakc_z_code[] = { #if 0 float4 main() : SV_TARGET { uint counter = 0; for (int i = 0, j = 254; i < 255 && j >= 0; ++i, --j) ++counter; if (counter == 255) return float4(0.0f, 1.0f, 0.0f, 1.0f); else return float4(1.0f, 0.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x687406ef, 0x7bdeb7d1, 0xb3282292, 0x934a9101, 0x00000001, 0x000001c0, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000148, 0x00000040, 0x00000052, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x08000036, 0x00100072, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x000000fe, 0x00000000, 0x01000030, 0x07000022, 0x00100082, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x000000ff, 0x07000021, 0x00100012, 0x00000001, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100082, 0x00000000, 0x0010003a, 0x00000000, 0x0010000a, 0x00000001, 0x03000003, 0x0010003a, 0x00000000, 0x0a00001e, 0x00100072, 0x00000000, 0x00100246, 0x00000000, 0x00004002, 0x00000001, 0x00000001, 0xffffffff, 0x00000000, 0x01000016, 0x07000020, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x000000ff, 0x0304001f, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000012, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000015, 0x0100003e, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_breakc_nz_code, sizeof(ps_breakc_nz_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create breakc_nz pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); ID3D11PixelShader_Release(ps); hr = ID3D11Device_CreatePixelShader(device, ps_breakc_z_code, sizeof(ps_breakc_z_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create breakc_z pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_sm4_continuec_instruction(void) { struct d3d11_test_context test_context; ID3D11DeviceContext *context; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; /* To get fxc to output continuec_z/continuec_nz instead of an if-block * with a normal continue inside, the shaders have been compiled with * the /Gfa flag. */ static const DWORD ps_continuec_nz_code[] = { #if 0 float4 main() : SV_TARGET { uint counter = 0; int i = -1; while (i < 255) { ++i; if (i != 0) continue; ++counter; } if (counter == 1) return float4(0.0f, 1.0f, 0.0f, 1.0f); else return float4(1.0f, 0.0f, 0.0f, 1.0f); } #endif 0x43425844, 0xaadaac96, 0xbe00fdfb, 0x29356be0, 0x47e79bd6, 0x00000001, 0x00000208, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000190, 0x00000040, 0x00000064, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000003, 0x08000036, 0x00100032, 0x00000000, 0x00004002, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x01000030, 0x07000021, 0x00100042, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x000000ff, 0x03040003, 0x0010002a, 0x00000000, 0x0700001e, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x00004001, 0x00000001, 0x09000037, 0x00100022, 0x00000002, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x05000036, 0x00100012, 0x00000002, 0x0010000a, 0x00000000, 0x05000036, 0x00100032, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x03040008, 0x0010002a, 0x00000000, 0x0700001e, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x00004001, 0x00000001, 0x05000036, 0x00100032, 0x00000000, 0x00100046, 0x00000001, 0x01000016, 0x07000020, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000001, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0304003f, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, }; static const DWORD ps_continuec_z_code[] = { #if 0 float4 main() : SV_TARGET { uint counter = 0; int i = -1; while (i < 255) { ++i; if (i == 0) continue; ++counter; } if (counter == 255) return float4(0.0f, 1.0f, 0.0f, 1.0f); else return float4(1.0f, 0.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x0322b23d, 0x52b25dc8, 0xa625f5f1, 0x271e3f46, 0x00000001, 0x000001d0, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000158, 0x00000040, 0x00000056, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x08000036, 0x00100032, 0x00000000, 0x00004002, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x01000030, 0x07000021, 0x00100042, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x000000ff, 0x03040003, 0x0010002a, 0x00000000, 0x0700001e, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000000, 0x05000036, 0x00100072, 0x00000000, 0x00100966, 0x00000001, 0x03000008, 0x0010002a, 0x00000000, 0x0700001e, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x00004001, 0x00000001, 0x05000036, 0x00100032, 0x00000000, 0x00100046, 0x00000001, 0x01000016, 0x07000020, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x000000ff, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0304003f, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_continuec_nz_code, sizeof(ps_continuec_nz_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create continuec_nz pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); ID3D11PixelShader_Release(ps); hr = ID3D11Device_CreatePixelShader(device, ps_continuec_z_code, sizeof(ps_continuec_z_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create continuec_z pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_sm4_discard_instruction(void) { ID3D11PixelShader *ps_discard_nz, *ps_discard_z; struct d3d11_test_context test_context; ID3D11DeviceContext *context; ID3D11Device *device; ID3D11Buffer *cb; unsigned int i; HRESULT hr; static const DWORD ps_discard_nz_code[] = { #if 0 uint data; float4 main() : SV_Target { if (data) discard; return float4(0.0f, 0.5f, 0.0f, 1.0f); } #endif 0x43425844, 0xfa7e5758, 0xd8716ffc, 0x5ad6a940, 0x2b99bba2, 0x00000001, 0x000000d0, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000058, 0x00000040, 0x00000016, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x0404000d, 0x0020800a, 0x00000000, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f000000, 0x00000000, 0x3f800000, 0x0100003e, }; static const DWORD ps_discard_z_code[] = { #if 0 uint data; float4 main() : SV_Target { if (!data) discard; return float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x5c4dd108, 0x1eb43558, 0x7c02c98c, 0xd81eb34c, 0x00000001, 0x000000d0, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000058, 0x00000040, 0x00000016, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x0400000d, 0x0020800a, 0x00000000, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const struct uvec4 values[] = { {0x0000000}, {0x0000001}, {0x8000000}, {0xfffffff}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(*values), NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); hr = ID3D11Device_CreatePixelShader(device, ps_discard_nz_code, sizeof(ps_discard_nz_code), NULL, &ps_discard_nz); ok(SUCCEEDED(hr), "Failed to create discard_nz pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_discard_z_code, sizeof(ps_discard_z_code), NULL, &ps_discard_z); ok(SUCCEEDED(hr), "Failed to create discard_z pixel shader, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(values); ++i) { ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &values[i], 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ID3D11DeviceContext_PSSetShader(context, ps_discard_nz, NULL, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, values[i].x ? 0xffffffff : 0xff007f00, 1); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ID3D11DeviceContext_PSSetShader(context, ps_discard_z, NULL, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, values[i].x ? 0xff00ff00 : 0xffffffff, 1); } ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps_discard_nz); ID3D11PixelShader_Release(ps_discard_z); release_test_context(&test_context); } static void test_sm5_swapc_instruction(void) { struct input { struct uvec4 src0; struct uvec4 src1; struct uvec4 src2; }; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Texture2D *texture; ID3D11PixelShader *ps[6]; ID3D11Device *device; ID3D11Buffer *cb; unsigned int i; HRESULT hr; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const DWORD ps_swapc0_code[] = { #if 0 ps_5_0 dcl_globalFlags refactoringAllowed dcl_constantbuffer cb0[3], immediateIndexed dcl_output o0.xyzw dcl_temps 2 swapc r0.xyzw, r1.xyzw, cb0[0].xyzw, cb0[1].xyzw, cb0[2].xyzw mov o0.xyzw, r0.xyzw ret #endif 0x43425844, 0x9e089246, 0x9f8b5cbe, 0xbac66faf, 0xaef23488, 0x00000001, 0x000000f8, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000080, 0x00000050, 0x00000020, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0e00008e, 0x001000f2, 0x00000000, 0x001000f2, 0x00000001, 0x00208e46, 0x00000000, 0x00000000, 0x00208e46, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x0100003e, }; static const DWORD ps_swapc1_code[] = { #if 0 ps_5_0 dcl_globalFlags refactoringAllowed dcl_constantbuffer cb0[3], immediateIndexed dcl_output o0.xyzw dcl_temps 2 swapc r0.xyzw, r1.xyzw, cb0[0].xyzw, cb0[1].xyzw, cb0[2].xyzw mov o0.xyzw, r1.xyzw ret #endif 0x43425844, 0xf2daed61, 0xede211f7, 0x7300dbea, 0x573ed49f, 0x00000001, 0x000000f8, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000080, 0x00000050, 0x00000020, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0e00008e, 0x001000f2, 0x00000000, 0x001000f2, 0x00000001, 0x00208e46, 0x00000000, 0x00000000, 0x00208e46, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x0100003e, }; static const DWORD ps_swapc2_code[] = { #if 0 ps_5_0 dcl_globalFlags refactoringAllowed dcl_constantbuffer cb0[3], immediateIndexed dcl_output o0.xyzw dcl_temps 2 mov r0.xyzw, cb0[1].xyzw mov r1.xyzw, cb0[2].xyzw swapc r0.xyzw, r1.xyzw, cb0[0].xyzw, r0.xyzw, r1.xyzw mov o0.xyzw, r0.xyzw ret #endif 0x43425844, 0x230fcb22, 0x70d99148, 0x65814d89, 0x97473498, 0x00000001, 0x00000120, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000a8, 0x00000050, 0x0000002a, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x06000036, 0x001000f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000001, 0x06000036, 0x001000f2, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0c00008e, 0x001000f2, 0x00000000, 0x001000f2, 0x00000001, 0x00208e46, 0x00000000, 0x00000000, 0x00100e46, 0x00000000, 0x00100e46, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x0100003e, }; static const DWORD ps_swapc3_code[] = { #if 0 ps_5_0 dcl_globalFlags refactoringAllowed dcl_constantbuffer cb0[3], immediateIndexed dcl_output o0.xyzw dcl_temps 2 mov r0.xyzw, cb0[1].xyzw mov r1.xyzw, cb0[2].xyzw swapc r0.xyzw, r1.xyzw, cb0[0].xyzw, r0.xyzw, r1.xyzw mov o0.xyzw, r1.xyzw ret #endif 0x43425844, 0xce595d62, 0x98305541, 0xb04e74c8, 0xfc010f3a, 0x00000001, 0x00000120, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000a8, 0x00000050, 0x0000002a, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x06000036, 0x001000f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000001, 0x06000036, 0x001000f2, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0c00008e, 0x001000f2, 0x00000000, 0x001000f2, 0x00000001, 0x00208e46, 0x00000000, 0x00000000, 0x00100e46, 0x00000000, 0x00100e46, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x0100003e, }; static const DWORD ps_swapc4_code[] = { #if 0 ps_5_0 dcl_globalFlags refactoringAllowed dcl_constantbuffer cb0[3], immediateIndexed dcl_output o0.xyzw dcl_temps 2 mov r0.xyzw, cb0[0].xyzw swapc r0.xyzw, r1.xyzw, r0.xyzw, cb0[1].xyzw, cb0[2].xyzw mov o0.xyzw, r0.xyzw ret #endif 0x43425844, 0x72067c48, 0xb53572a0, 0x9dd9e0fd, 0x903e37e3, 0x00000001, 0x0000010c, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000094, 0x00000050, 0x00000025, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x06000036, 0x001000f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0d00008e, 0x001000f2, 0x00000000, 0x001000f2, 0x00000001, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x0100003e, }; static const DWORD ps_swapc5_code[] = { #if 0 ps_5_0 dcl_globalFlags refactoringAllowed dcl_constantbuffer cb0[3], immediateIndexed dcl_output o0.xyzw dcl_temps 2 mov r1.xyzw, cb0[0].xyzw swapc r0.xyzw, r1.xyzw, r1.xyzw, cb0[1].xyzw, cb0[2].xyzw mov o0.xyzw, r1.xyzw ret #endif 0x43425844, 0x7078fb08, 0xdd24cd44, 0x469d3258, 0x9e33a0bc, 0x00000001, 0x0000010c, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000094, 0x00000050, 0x00000025, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x06000036, 0x001000f2, 0x00000001, 0x00208e46, 0x00000000, 0x00000000, 0x0d00008e, 0x001000f2, 0x00000000, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208e46, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x0100003e, }; static const struct { struct input input; struct uvec4 dst0; struct uvec4 dst1; } tests[] = { { {{0, 0, 0, 0}, {0xdead, 0xc0de, 0xffff, 0xeeee}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}}, {0xdead, 0xc0de, 0xffff, 0xeeee}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd} }, { {{1, 1, 1, 1}, {0xdead, 0xc0de, 0xffff, 0xeeee}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}, {0xdead, 0xc0de, 0xffff, 0xeeee}, }, { {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, {0xdead, 0xc0de, 0xffff, 0xeeee}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}, {0xdead, 0xc0de, 0xffff, 0xeeee}, }, { {{1, 0, 1, 0}, {0xdead, 0xc0de, 0xffff, 0xeeee}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}}, {0xaaaa, 0xc0de, 0xcccc, 0xeeee}, {0xdead, 0xbbbb, 0xffff, 0xdddd}, }, { {{1, 0, 0, 1}, {0xdead, 0xc0de, 0xffff, 0xeeee}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}}, {0xaaaa, 0xc0de, 0xffff, 0xdddd}, {0xdead, 0xbbbb, 0xcccc, 0xeeee}, }, { {{1, 0, 0, 0}, {0xdead, 0xc0de, 0xffff, 0xeeee}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}}, {0xaaaa, 0xc0de, 0xffff, 0xeeee}, {0xdead, 0xbbbb, 0xcccc, 0xdddd} }, { {{0, 1, 0, 0}, {0xdead, 0xc0de, 0xffff, 0xeeee}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}}, {0xdead, 0xbbbb, 0xffff, 0xeeee}, {0xaaaa, 0xc0de, 0xcccc, 0xdddd} }, { {{0, 0, 1, 0}, {0xdead, 0xc0de, 0xffff, 0xeeee}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}}, {0xdead, 0xc0de, 0xcccc, 0xeeee}, {0xaaaa, 0xbbbb, 0xffff, 0xdddd} }, { {{0, 0, 0, 1}, {0xdead, 0xc0de, 0xffff, 0xeeee}, {0xaaaa, 0xbbbb, 0xcccc, 0xdddd}}, {0xdead, 0xc0de, 0xffff, 0xdddd}, {0xaaaa, 0xbbbb, 0xcccc, 0xeeee}, }, }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_R32G32B32A32_UINT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(struct input), NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); hr = ID3D11Device_CreatePixelShader(device, ps_swapc0_code, sizeof(ps_swapc0_code), NULL, &ps[0]); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_swapc1_code, sizeof(ps_swapc1_code), NULL, &ps[1]); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_swapc2_code, sizeof(ps_swapc2_code), NULL, &ps[2]); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_swapc3_code, sizeof(ps_swapc3_code), NULL, &ps[3]); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_swapc4_code, sizeof(ps_swapc4_code), NULL, &ps[4]); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_swapc5_code, sizeof(ps_swapc5_code), NULL, &ps[5]); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(tests); ++i) { ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &tests[i].input, 0, 0); ID3D11DeviceContext_PSSetShader(context, ps[0], NULL, 0); draw_quad(&test_context); check_texture_uvec4(texture, &tests[i].dst0); ID3D11DeviceContext_PSSetShader(context, ps[1], NULL, 0); draw_quad(&test_context); check_texture_uvec4(texture, &tests[i].dst1); ID3D11DeviceContext_PSSetShader(context, ps[2], NULL, 0); draw_quad(&test_context); check_texture_uvec4(texture, &tests[i].dst0); ID3D11DeviceContext_PSSetShader(context, ps[3], NULL, 0); draw_quad(&test_context); check_texture_uvec4(texture, &tests[i].dst1); ID3D11DeviceContext_PSSetShader(context, ps[4], NULL, 0); draw_quad(&test_context); check_texture_uvec4(texture, &tests[i].dst0); ID3D11DeviceContext_PSSetShader(context, ps[5], NULL, 0); draw_quad(&test_context); check_texture_uvec4(texture, &tests[i].dst1); } for (i = 0; i < ARRAY_SIZE(ps); ++i) ID3D11PixelShader_Release(ps[i]); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(texture); ID3D11Buffer_Release(cb); release_test_context(&test_context); } static void test_create_input_layout(void) { D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_UNKNOWN, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; ULONG refcount, expected_refcount; ID3D11InputLayout *input_layout; ID3D11Device *device; unsigned int i; HRESULT hr; static const DWORD vs_code[] = { #if 0 float4 main(float4 position : POSITION) : SV_POSITION { return position; } #endif 0x43425844, 0xa7a2f22d, 0x83ff2560, 0xe61638bd, 0x87e3ce90, 0x00000001, 0x000000d8, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000003c, 0x00010040, 0x0000000f, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; static const DXGI_FORMAT vertex_formats[] = { DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_SINT, }; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } for (i = 0; i < ARRAY_SIZE(vertex_formats); ++i) { expected_refcount = get_refcount(device) + 1; layout_desc->Format = vertex_formats[i]; hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(hr == S_OK, "Failed to create input layout for format %#x, hr %#x.\n", vertex_formats[i], hr); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11InputLayout_Release(input_layout); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_input_assembler(void) { enum layout_id { LAYOUT_FLOAT32, LAYOUT_UINT16, LAYOUT_SINT16, LAYOUT_UNORM16, LAYOUT_SNORM16, LAYOUT_UINT8, LAYOUT_SINT8, LAYOUT_UNORM8, LAYOUT_SNORM8, LAYOUT_UNORM10_2, LAYOUT_UINT10_2, LAYOUT_COUNT, }; D3D11_INPUT_ELEMENT_DESC input_layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"ATTRIBUTE", 0, DXGI_FORMAT_UNKNOWN, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; ID3D11VertexShader *vs_float, *vs_uint, *vs_sint; ID3D11InputLayout *input_layout[LAYOUT_COUNT]; ID3D11Buffer *vb_position, *vb_attribute; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; unsigned int i, j, stride, offset; ID3D11Texture2D *render_target; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DXGI_FORMAT layout_formats[LAYOUT_COUNT] = { DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UINT, }; static const struct vec2 quad[] = { {-1.0f, -1.0f}, {-1.0f, 1.0f}, { 1.0f, -1.0f}, { 1.0f, 1.0f}, }; static const DWORD ps_code[] = { #if 0 float4 main(float4 position : POSITION, float4 color: COLOR) : SV_Target { return color; } #endif 0x43425844, 0xa9150342, 0x70e18d2e, 0xf7769835, 0x4c3a7f02, 0x00000001, 0x000000f0, 0x00000003, 0x0000002c, 0x0000007c, 0x000000b0, 0x4e475349, 0x00000048, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000041, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const DWORD vs_float_code[] = { #if 0 struct output { float4 position : SV_Position; float4 color : COLOR; }; void main(float4 position : POSITION, float4 color : ATTRIBUTE, out output o) { o.position = position; o.color = color; } #endif 0x43425844, 0xf6051ffd, 0xd9e49503, 0x171ad197, 0x3764fe47, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0x54544100, 0x55424952, 0xab004554, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; static const DWORD vs_uint_code[] = { #if 0 struct output { float4 position : SV_Position; float4 color : COLOR; }; void main(float4 position : POSITION, uint4 color : ATTRIBUTE, out output o) { o.position = position; o.color = color; } #endif 0x43425844, 0x0bae0bc0, 0xf6473aa5, 0x4ecf4a25, 0x414fac23, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0x54544100, 0x55424952, 0xab004554, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000056, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; static const DWORD vs_sint_code[] = { #if 0 struct output { float4 position : SV_Position; float4 color : COLOR; }; void main(float4 position : POSITION, int4 color : ATTRIBUTE, out output o) { o.position = position; o.color = color; } #endif 0x43425844, 0xaf60aad9, 0xba91f3a4, 0x2015d384, 0xf746fdf5, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000, 0x00000002, 0x00000001, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0x54544100, 0x55424952, 0xab004554, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0500002b, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; static const float float32_data[] = {1.0f, 2.0f, 3.0f, 4.0f}; static const unsigned short uint16_data[] = {6, 8, 55, 777}; static const short sint16_data[] = {-1, 33, 8, -77}; static const unsigned short unorm16_data[] = {0, 16383, 32767, 65535}; static const short snorm16_data[] = {-32768, 0, 32767, 0}; static const unsigned char uint8_data[] = {0, 64, 128, 255}; static const signed char sint8_data[] = {-128, 0, 127, 64}; static const unsigned int uint32_zero = 0; static const unsigned int uint32_max = 0xffffffff; static const unsigned int unorm10_2_data= 0xa00003ff; static const unsigned int g10_data = 0x000ffc00; static const unsigned int a2_data = 0xc0000000; static const struct { enum layout_id layout_id; unsigned int stride; const void *data; struct vec4 expected_color; BOOL todo; } tests[] = { {LAYOUT_FLOAT32, sizeof(float32_data), float32_data, {1.0f, 2.0f, 3.0f, 4.0f}}, {LAYOUT_UINT16, sizeof(uint16_data), uint16_data, {6.0f, 8.0f, 55.0f, 777.0f}, TRUE}, {LAYOUT_SINT16, sizeof(sint16_data), sint16_data, {-1.0f, 33.0f, 8.0f, -77.0f}, TRUE}, {LAYOUT_UNORM16, sizeof(unorm16_data), unorm16_data, {0.0f, 16383.0f / 65535.0f, 32767.0f / 65535.0f, 1.0f}}, {LAYOUT_SNORM16, sizeof(snorm16_data), snorm16_data, {-1.0f, 0.0f, 1.0f, 0.0f}}, {LAYOUT_UINT8, sizeof(uint32_zero), &uint32_zero, {0.0f, 0.0f, 0.0f, 0.0f}}, {LAYOUT_UINT8, sizeof(uint32_max), &uint32_max, {255.0f, 255.0f, 255.0f, 255.0f}}, {LAYOUT_UINT8, sizeof(uint8_data), uint8_data, {0.0f, 64.0f, 128.0f, 255.0f}}, {LAYOUT_SINT8, sizeof(uint32_zero), &uint32_zero, {0.0f, 0.0f, 0.0f, 0.0f}}, {LAYOUT_SINT8, sizeof(uint32_max), &uint32_max, {-1.0f, -1.0f, -1.0f, -1.0f}}, {LAYOUT_SINT8, sizeof(sint8_data), sint8_data, {-128.0f, 0.0f, 127.0f, 64.0f}}, {LAYOUT_UNORM8, sizeof(uint32_zero), &uint32_zero, {0.0f, 0.0f, 0.0f, 0.0f}}, {LAYOUT_UNORM8, sizeof(uint32_max), &uint32_max, {1.0f, 1.0f, 1.0f, 1.0f}}, {LAYOUT_UNORM8, sizeof(uint8_data), uint8_data, {0.0f, 64.0f / 255.0f, 128.0f / 255.0f, 1.0f}}, {LAYOUT_SNORM8, sizeof(uint32_zero), &uint32_zero, {0.0f, 0.0f, 0.0f, 0.0f}}, {LAYOUT_SNORM8, sizeof(sint8_data), sint8_data, {-1.0f, 0.0f, 1.0f, 64.0f / 127.0f}}, {LAYOUT_UNORM10_2, sizeof(uint32_zero), &uint32_zero, {0.0f, 0.0f, 0.0f, 0.0f}}, {LAYOUT_UNORM10_2, sizeof(uint32_max), &uint32_max, {1.0f, 1.0f, 1.0f, 1.0f}}, {LAYOUT_UNORM10_2, sizeof(g10_data), &g10_data, {0.0f, 1.0f, 0.0f, 0.0f}}, {LAYOUT_UNORM10_2, sizeof(a2_data), &a2_data, {0.0f, 0.0f, 0.0f, 1.0f}}, {LAYOUT_UNORM10_2, sizeof(unorm10_2_data), &unorm10_2_data, {1.0f, 0.0f, 512.0f / 1023.0f, 2.0f / 3.0f}}, {LAYOUT_UINT10_2, sizeof(uint32_zero), &uint32_zero, {0.0f, 0.0f, 0.0f, 0.0f}}, {LAYOUT_UINT10_2, sizeof(uint32_max), &uint32_max, {1023.0f, 1023.0f, 1023.0f, 3.0f}}, {LAYOUT_UINT10_2, sizeof(g10_data), &g10_data, {0.0f, 1023.0f, 0.0f, 0.0f}}, {LAYOUT_UINT10_2, sizeof(a2_data), &a2_data, {0.0f, 0.0f, 0.0f, 3.0f}}, {LAYOUT_UINT10_2, sizeof(unorm10_2_data), &unorm10_2_data, {1023.0f, 0.0f, 512.0f, 2.0f}}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreateVertexShader(device, vs_float_code, sizeof(vs_float_code), NULL, &vs_float); ok(SUCCEEDED(hr), "Failed to create float vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreateVertexShader(device, vs_uint_code, sizeof(vs_uint_code), NULL, &vs_uint); ok(SUCCEEDED(hr), "Failed to create uint vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreateVertexShader(device, vs_sint_code, sizeof(vs_sint_code), NULL, &vs_sint); ok(SUCCEEDED(hr), "Failed to create sint vertex shader, hr %#x.\n", hr); for (i = 0; i < LAYOUT_COUNT; ++i) { input_layout_desc[1].Format = layout_formats[i]; input_layout[i] = NULL; hr = ID3D11Device_CreateInputLayout(device, input_layout_desc, ARRAY_SIZE(input_layout_desc), vs_float_code, sizeof(vs_float_code), &input_layout[i]); todo_wine_if(input_layout_desc[1].Format == DXGI_FORMAT_R10G10B10A2_UINT) ok(SUCCEEDED(hr), "Failed to create input layout for format %#x, hr %#x.\n", layout_formats[i], hr); } vb_position = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(quad), quad); vb_attribute = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, 1024, NULL); texture_desc.Width = 640; texture_desc.Height = 480; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &render_target); ok(SUCCEEDED(hr), "Failed to create 2d texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)render_target, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); offset = 0; stride = sizeof(*quad); ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb_position, &stride, &offset); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); for (i = 0; i < ARRAY_SIZE(tests); ++i) { D3D11_BOX box = {0, 0, 0, 1, 1, 1}; if (tests[i].layout_id == LAYOUT_UINT10_2) continue; assert(tests[i].layout_id < LAYOUT_COUNT); ID3D11DeviceContext_IASetInputLayout(context, input_layout[tests[i].layout_id]); assert(4 * tests[i].stride <= 1024); box.right = tests[i].stride; for (j = 0; j < 4; ++j) { ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb_attribute, 0, &box, tests[i].data, 0, 0); box.left += tests[i].stride; box.right += tests[i].stride; } stride = tests[i].stride; ID3D11DeviceContext_IASetVertexBuffers(context, 1, 1, &vb_attribute, &stride, &offset); switch (layout_formats[tests[i].layout_id]) { case DXGI_FORMAT_R16G16B16A16_UINT: case DXGI_FORMAT_R10G10B10A2_UINT: case DXGI_FORMAT_R8G8B8A8_UINT: ID3D11DeviceContext_VSSetShader(context, vs_uint, NULL, 0); break; case DXGI_FORMAT_R16G16B16A16_SINT: case DXGI_FORMAT_R8G8B8A8_SINT: ID3D11DeviceContext_VSSetShader(context, vs_sint, NULL, 0); break; default: trace("Unhandled format %#x.\n", layout_formats[tests[i].layout_id]); /* Fall through. */ case DXGI_FORMAT_R32G32B32A32_FLOAT: case DXGI_FORMAT_R16G16B16A16_UNORM: case DXGI_FORMAT_R16G16B16A16_SNORM: case DXGI_FORMAT_R10G10B10A2_UNORM: case DXGI_FORMAT_R8G8B8A8_UNORM: case DXGI_FORMAT_R8G8B8A8_SNORM: ID3D11DeviceContext_VSSetShader(context, vs_float, NULL, 0); break; } ID3D11DeviceContext_Draw(context, 4, 0); check_texture_vec4(render_target, &tests[i].expected_color, 2); } ID3D11Texture2D_Release(render_target); ID3D11RenderTargetView_Release(rtv); ID3D11Buffer_Release(vb_attribute); ID3D11Buffer_Release(vb_position); for (i = 0; i < LAYOUT_COUNT; ++i) { if (input_layout[i]) ID3D11InputLayout_Release(input_layout[i]); } ID3D11PixelShader_Release(ps); ID3D11VertexShader_Release(vs_float); ID3D11VertexShader_Release(vs_uint); ID3D11VertexShader_Release(vs_sint); release_test_context(&test_context); } static void test_null_sampler(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11SamplerState *sampler; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DWORD ps_code[] = { #if 0 Texture2D t; SamplerState s; float4 main(float4 position : SV_POSITION) : SV_Target { return t.Sample(s, float2(position.x / 640.0f, position.y / 480.0f)); } #endif 0x43425844, 0x1ce9b612, 0xc8176faa, 0xd37844af, 0xdb515605, 0x00000001, 0x00000134, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040, 0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, }; static const float blue[] = {0.0f, 0.0f, 1.0f, 1.0f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); texture_desc.Width = 64; texture_desc.Height = 64; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, blue); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); sampler = NULL; ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xffff0000, 0); ID3D11ShaderResourceView_Release(srv); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(texture); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_check_feature_support(void) { D3D11_FEATURE_DATA_THREADING threading[2]; D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts; D3D11_FEATURE_DATA_ARCHITECTURE_INFO archinfo; ID3D11Device *device; ULONG refcount; HRESULT hr; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } memset(threading, 0xef, sizeof(threading)); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_THREADING, NULL, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_THREADING, threading, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_THREADING, threading, sizeof(*threading) - 1); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_THREADING, threading, sizeof(*threading) / 2); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_THREADING, threading, sizeof(*threading) + 1); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_THREADING, threading, sizeof(*threading) * 2); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ok(threading[0].DriverConcurrentCreates == 0xefefefef, "Got unexpected concurrent creates %#x.\n", threading[0].DriverConcurrentCreates); ok(threading[0].DriverCommandLists == 0xefefefef, "Got unexpected command lists %#x.\n", threading[0].DriverCommandLists); ok(threading[1].DriverConcurrentCreates == 0xefefefef, "Got unexpected concurrent creates %#x.\n", threading[1].DriverConcurrentCreates); ok(threading[1].DriverCommandLists == 0xefefefef, "Got unexpected command lists %#x.\n", threading[1].DriverCommandLists); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_THREADING, threading, sizeof(*threading)); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ok(threading->DriverConcurrentCreates == TRUE || threading->DriverConcurrentCreates == FALSE, "Got unexpected concurrent creates %#x.\n", threading->DriverConcurrentCreates); ok(threading->DriverCommandLists == TRUE || threading->DriverCommandLists == FALSE, "Got unexpected command lists %#x.\n", threading->DriverCommandLists); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, NULL, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, 0); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) - 1); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) / 2); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) + 1); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) * 2); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts)); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); trace("Compute shader support via SM4 %#x.\n", hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_ARCHITECTURE_INFO, &archinfo, sizeof(archinfo)); ok(hr == S_OK || broken(hr == E_INVALIDARG) /* Not available on all Windows versions. */, "Got unexpected hr %#x.\n", hr); hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_ARCHITECTURE_INFO, &archinfo, sizeof(archinfo)*2); ok(hr == E_INVALIDARG /* Not available on all Windows versions but they will return E_INVALIDARG anyways. */, "Got unexpected hr %#x.\n", hr); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_create_unordered_access_view(void) { static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; D3D11_TEXTURE3D_DESC texture3d_desc; D3D11_TEXTURE2D_DESC texture2d_desc; ULONG refcount, expected_refcount; D3D11_SUBRESOURCE_DATA data = {0}; ID3D11UnorderedAccessView *uav; struct device_desc device_desc; D3D11_BUFFER_DESC buffer_desc; ID3D11Device *device, *tmp; ID3D11Texture3D *texture3d; ID3D11Texture2D *texture2d; ID3D11Resource *texture; ID3D11Buffer *buffer; unsigned int i; HRESULT hr; #define FMT_UNKNOWN DXGI_FORMAT_UNKNOWN #define RGBA8_UNORM DXGI_FORMAT_R8G8B8A8_UNORM #define RGBA8_SRGB DXGI_FORMAT_R8G8B8A8_UNORM_SRGB #define RGBA8_UINT DXGI_FORMAT_R8G8B8A8_UINT #define RGBA8_TL DXGI_FORMAT_R8G8B8A8_TYPELESS #define DIM_UNKNOWN D3D11_UAV_DIMENSION_UNKNOWN #define TEX_1D D3D11_UAV_DIMENSION_TEXTURE1D #define TEX_1D_ARRAY D3D11_UAV_DIMENSION_TEXTURE1DARRAY #define TEX_2D D3D11_UAV_DIMENSION_TEXTURE2D #define TEX_2D_ARRAY D3D11_UAV_DIMENSION_TEXTURE2DARRAY #define TEX_3D D3D11_UAV_DIMENSION_TEXTURE3D static const struct { struct { unsigned int miplevel_count; unsigned int depth_or_array_size; DXGI_FORMAT format; } texture; struct uav_desc uav_desc; struct uav_desc expected_uav_desc; } tests[] = { {{ 1, 1, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_2D, 0}}, {{10, 1, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_2D, 0}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D, 0}, {RGBA8_UNORM, TEX_2D, 0}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D, 1}, {RGBA8_UNORM, TEX_2D, 1}}, {{10, 1, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D, 9}, {RGBA8_UNORM, TEX_2D, 9}}, {{ 1, 1, RGBA8_TL}, {RGBA8_UNORM, TEX_2D, 0}, {RGBA8_UNORM, TEX_2D, 0}}, {{10, 1, RGBA8_TL}, {RGBA8_UNORM, TEX_2D, 0}, {RGBA8_UNORM, TEX_2D, 0}}, {{ 1, 1, RGBA8_UINT}, {0}, {RGBA8_UINT, TEX_2D, 0, 0, 1}}, {{ 1, 1, RGBA8_TL}, {RGBA8_UINT, TEX_2D, 0, 0, ~0u}, {RGBA8_UINT, TEX_2D, 0, 0, 1}}, {{ 1, 4, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 4}}, {{10, 4, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 1, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 1, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 3, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 3, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 5, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 5, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 9, 0, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 9, 0, 4}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 1, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 1, 3}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 2, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 2, 2}}, {{10, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_2D_ARRAY, 0, 3, ~0u}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 3, 1}}, {{ 1, 6, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_3D, 0, 0, 6}}, {{ 2, 6, RGBA8_UNORM}, {0}, {RGBA8_UNORM, TEX_3D, 0, 0, 6}}, {{ 2, 6, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 0, 6}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 1, 0, 2}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 1, 0, 2}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 1, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 1, 3}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 2, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 2, 2}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 3, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 3, 1}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 1, 1}, {RGBA8_UNORM, TEX_3D, 0, 1, 1}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 1, 1}, {RGBA8_UNORM, TEX_3D, 1, 1, 1}}, {{ 2, 4, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 1, ~0u}, {RGBA8_UNORM, TEX_3D, 1, 1, 1}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 0, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 0, 0, 8}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 1, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 1, 0, 4}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 2, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 2, 0, 2}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 3, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 3, 0, 1}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 4, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 4, 0, 1}}, {{ 6, 8, RGBA8_UNORM}, {FMT_UNKNOWN, TEX_3D, 5, 0, ~0u}, {RGBA8_UNORM, TEX_3D, 5, 0, 1}}, }; static const struct { struct { D3D11_UAV_DIMENSION dimension; unsigned int miplevel_count; unsigned int depth_or_array_size; DXGI_FORMAT format; } texture; struct uav_desc uav_desc; } invalid_desc_tests[] = { {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, DIM_UNKNOWN}}, {{TEX_2D, 6, 4, RGBA8_UNORM}, {RGBA8_UNORM, DIM_UNKNOWN}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, ~0u}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_TL, TEX_2D, 0}}, {{TEX_2D, 1, 1, RGBA8_TL}, {FMT_UNKNOWN, TEX_2D, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 0}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 1, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 2}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 1, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_UINT, TEX_2D, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UINT}, {RGBA8_UNORM, TEX_2D, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_UNORM}, {RGBA8_SRGB, TEX_2D, 0, 0, 1}}, {{TEX_2D, 1, 1, RGBA8_SRGB}, {RGBA8_UNORM, TEX_2D, 0, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D, 0}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_1D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D, 0}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_UNORM, TEX_2D_ARRAY, 0, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, 0}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 1, 0, 1}}, {{TEX_3D, 1, 1, RGBA8_UNORM}, {RGBA8_TL, TEX_3D, 0, 0, 1}}, {{TEX_3D, 1, 9, RGBA8_UNORM}, {RGBA8_TL, TEX_3D, 0, 0, 1}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 0, 9}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 3, 0, 2}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 2, 0, 4}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 1, 0, 8}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 0, 8, ~0u}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 1, 4, ~0u}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 2, 2, ~0u}}, {{TEX_3D, 4, 8, RGBA8_UNORM}, {RGBA8_UNORM, TEX_3D, 3, 1, ~0u}}, }; #undef FMT_UNKNOWN #undef RGBA8_UNORM #undef RGBA8_SRGB #undef RGBA8_UINT #undef RGBA8_TL #undef DIM_UNKNOWN #undef TEX_1D #undef TEX_1D_ARRAY #undef TEX_2D #undef TEX_2D_ARRAY #undef TEX_3D device_desc.feature_level = &feature_level; device_desc.flags = 0; if (!(device = create_device(&device_desc))) { skip("Failed to create device.\n"); return; } buffer_desc.ByteWidth = 1024; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = 0; buffer_desc.StructureByteStride = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, &data, &buffer); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11Buffer_GetDevice(buffer, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); uav_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 64; U(uav_desc).Buffer.Flags = 0; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, NULL, &uav); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); expected_refcount = get_refcount(device) + 1; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount >= expected_refcount, "Got unexpected refcount %u, expected >= %u.\n", refcount, expected_refcount); tmp = NULL; expected_refcount = refcount + 1; ID3D11UnorderedAccessView_GetDevice(uav, &tmp); ok(tmp == device, "Got unexpected device %p, expected %p.\n", tmp, device); refcount = get_refcount(device); ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount); ID3D11Device_Release(tmp); ID3D11UnorderedAccessView_Release(uav); ID3D11Buffer_Release(buffer); buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; buffer_desc.StructureByteStride = 4; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, NULL, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); memset(&uav_desc, 0, sizeof(uav_desc)); ID3D11UnorderedAccessView_GetDesc(uav, &uav_desc); ok(uav_desc.Format == DXGI_FORMAT_UNKNOWN, "Got unexpected format %#x.\n", uav_desc.Format); ok(uav_desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER, "Got unexpected view dimension %#x.\n", uav_desc.ViewDimension); ok(!U(uav_desc).Buffer.FirstElement, "Got unexpected first element %u.\n", U(uav_desc).Buffer.FirstElement); ok(U(uav_desc).Buffer.NumElements == 256, "Got unexpected num elements %u.\n", U(uav_desc).Buffer.NumElements); ok(!U(uav_desc).Buffer.Flags, "Got unexpected flags %u.\n", U(uav_desc).Buffer.Flags); ID3D11UnorderedAccessView_Release(uav); ID3D11Buffer_Release(buffer); /* Without D3D11_BIND_UNORDERED_ACCESS. */ buffer = create_buffer(device, 0, 1024, NULL); uav_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 64; U(uav_desc).Buffer.Flags = 0; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ID3D11Buffer_Release(buffer); texture2d_desc.Width = 512; texture2d_desc.Height = 512; texture2d_desc.SampleDesc.Count = 1; texture2d_desc.SampleDesc.Quality = 0; texture2d_desc.Usage = D3D11_USAGE_DEFAULT; texture2d_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; texture2d_desc.CPUAccessFlags = 0; texture2d_desc.MiscFlags = 0; texture3d_desc.Width = 64; texture3d_desc.Height = 64; texture3d_desc.Usage = D3D11_USAGE_DEFAULT; texture3d_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; texture3d_desc.CPUAccessFlags = 0; texture3d_desc.MiscFlags = 0; for (i = 0; i < ARRAY_SIZE(tests); ++i) { D3D11_UNORDERED_ACCESS_VIEW_DESC *current_desc; if (tests[i].expected_uav_desc.dimension != D3D11_UAV_DIMENSION_TEXTURE3D) { texture2d_desc.MipLevels = tests[i].texture.miplevel_count; texture2d_desc.ArraySize = tests[i].texture.depth_or_array_size; texture2d_desc.Format = tests[i].texture.format; hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, NULL, &texture2d); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture2d; } else { texture3d_desc.MipLevels = tests[i].texture.miplevel_count; texture3d_desc.Depth = tests[i].texture.depth_or_array_size; texture3d_desc.Format = tests[i].texture.format; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, &texture3d); ok(SUCCEEDED(hr), "Test %u: Failed to create 3d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture3d; } if (tests[i].uav_desc.dimension == D3D11_UAV_DIMENSION_UNKNOWN) { current_desc = NULL; } else { current_desc = &uav_desc; get_uav_desc(current_desc, &tests[i].uav_desc); } expected_refcount = get_refcount(texture); hr = ID3D11Device_CreateUnorderedAccessView(device, texture, current_desc, &uav); ok(SUCCEEDED(hr), "Test %u: Failed to create unordered access view, hr %#x.\n", i, hr); refcount = get_refcount(texture); ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount); memset(&uav_desc, 0, sizeof(uav_desc)); ID3D11UnorderedAccessView_GetDesc(uav, &uav_desc); check_uav_desc(&uav_desc, &tests[i].expected_uav_desc); ID3D11UnorderedAccessView_Release(uav); ID3D11Resource_Release(texture); } for (i = 0; i < ARRAY_SIZE(invalid_desc_tests); ++i) { assert(invalid_desc_tests[i].texture.dimension == D3D11_UAV_DIMENSION_TEXTURE2D || invalid_desc_tests[i].texture.dimension == D3D11_UAV_DIMENSION_TEXTURE3D); if (invalid_desc_tests[i].texture.dimension != D3D11_UAV_DIMENSION_TEXTURE3D) { texture2d_desc.MipLevels = invalid_desc_tests[i].texture.miplevel_count; texture2d_desc.ArraySize = invalid_desc_tests[i].texture.depth_or_array_size; texture2d_desc.Format = invalid_desc_tests[i].texture.format; hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, NULL, &texture2d); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture2d; } else { texture3d_desc.MipLevels = invalid_desc_tests[i].texture.miplevel_count; texture3d_desc.Depth = invalid_desc_tests[i].texture.depth_or_array_size; texture3d_desc.Format = invalid_desc_tests[i].texture.format; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, &texture3d); ok(SUCCEEDED(hr), "Test %u: Failed to create 3d texture, hr %#x.\n", i, hr); texture = (ID3D11Resource *)texture3d; } get_uav_desc(&uav_desc, &invalid_desc_tests[i].uav_desc); hr = ID3D11Device_CreateUnorderedAccessView(device, texture, &uav_desc, &uav); ok(hr == E_INVALIDARG, "Test %u: Got unexpected hr %#x.\n", i, hr); ID3D11Resource_Release(texture); } refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_immediate_constant_buffer(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; unsigned int index[4] = {0}; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *cb; unsigned int i; HRESULT hr; static const DWORD ps_code[] = { #if 0 uint index; static const int int_array[6] = { 310, 111, 212, -513, -318, 0, }; static const uint uint_array[6] = { 2, 7, 0x7f800000, 0xff800000, 0x7fc00000, 0 }; static const float float_array[6] = { 76, 83.5f, 0.5f, 0.75f, -0.5f, 0.0f, }; float4 main() : SV_Target { return float4(int_array[index], uint_array[index], float_array[index], 1.0f); } #endif 0x43425844, 0xbad068da, 0xd631ea3c, 0x41648374, 0x3ccd0120, 0x00000001, 0x00000184, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000010c, 0x00000040, 0x00000043, 0x00001835, 0x0000001a, 0x00000136, 0x00000002, 0x42980000, 0x00000000, 0x0000006f, 0x00000007, 0x42a70000, 0x00000000, 0x000000d4, 0x7f800000, 0x3f000000, 0x00000000, 0xfffffdff, 0xff800000, 0x3f400000, 0x00000000, 0xfffffec2, 0x7fc00000, 0xbf000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x3f800000, 0x06000036, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x06000056, 0x00102022, 0x00000000, 0x0090901a, 0x0010000a, 0x00000000, 0x0600002b, 0x00102012, 0x00000000, 0x0090900a, 0x0010000a, 0x00000000, 0x06000036, 0x00102042, 0x00000000, 0x0090902a, 0x0010000a, 0x00000000, 0x0100003e, }; static struct vec4 expected_result[] = { { 310.0f, 2.0f, 76.00f, 1.0f}, { 111.0f, 7.0f, 83.50f, 1.0f}, { 212.0f, 2139095040.0f, 0.50f, 1.0f}, {-513.0f, 4286578688.0f, 0.75f, 1.0f}, {-318.0f, 2143289344.0f, -0.50f, 1.0f}, { 0.0f, 0.0f, 0.0f, 1.0f}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(index), NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); for (i = 0; i < ARRAY_SIZE(expected_result); ++i) { *index = i; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, index, 0, 0); draw_quad(&test_context); check_texture_vec4(texture, &expected_result[i], 0); } ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps); ID3D11Texture2D_Release(texture); ID3D11RenderTargetView_Release(rtv); release_test_context(&test_context); } static void test_fp_specials(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DWORD ps_code[] = { #if 0 float4 main() : SV_Target { return float4(0.0f / 0.0f, 1.0f / 0.0f, -1.0f / 0.0f, 1.0f); } #endif 0x43425844, 0x86d7f319, 0x14cde598, 0xe7ce83a8, 0x0e06f3f0, 0x00000001, 0x000000b0, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03000065, 0x001020f2, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0xffc00000, 0x7f800000, 0xff800000, 0x3f800000, 0x0100003e, }; static const struct uvec4 expected_result = {BITS_NNAN, BITS_INF, BITS_NINF, BITS_1_0}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); draw_quad(&test_context); check_texture_uvec4(texture, &expected_result); ID3D11PixelShader_Release(ps); ID3D11Texture2D_Release(texture); ID3D11RenderTargetView_Release(rtv); release_test_context(&test_context); } static void test_uint_shader_instructions(void) { struct shader { const DWORD *code; size_t size; D3D_FEATURE_LEVEL required_feature_level; }; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; D3D_FEATURE_LEVEL feature_level; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *cb; unsigned int i; HRESULT hr; static const DWORD ps_bfi_code[] = { #if 0 uint bits, offset, insert, base; uint4 main() : SV_Target { uint mask = ((1 << bits) - 1) << offset; return ((insert << offset) & mask) | (base & ~mask); } #endif 0x43425844, 0xbe9af688, 0xf5caec6f, 0x63ed2522, 0x5f91f209, 0x00000001, 0x000000e0, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000068, 0x00000050, 0x0000001a, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x0f00008c, 0x001020f2, 0x00000000, 0x00208006, 0x00000000, 0x00000000, 0x00208556, 0x00000000, 0x00000000, 0x00208aa6, 0x00000000, 0x00000000, 0x00208ff6, 0x00000000, 0x00000000, 0x0100003e, }; static const DWORD ps_bfi2_code[] = { #if 0 ps_5_0 dcl_globalFlags refactoringAllowed dcl_constantbuffer cb0[1], immediateIndexed dcl_output o0.xyzw dcl_temps 1 mov r0.xyzw, cb0[0].xyzw bfi r0.xyzw, r0.xxxx, r0.yyyy, r0.zzzz, r0.wwww mov o0.xyzw, r0.xyzw ret #endif 0x43425844, 0x900f86b6, 0x73f4dabf, 0xea1b1106, 0x591ac790, 0x00000001, 0x00000104, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x0000008c, 0x00000050, 0x00000023, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x06000036, 0x001000f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0b00008c, 0x001000f2, 0x00000000, 0x00100006, 0x00000000, 0x00100556, 0x00000000, 0x00100aa6, 0x00000000, 0x00100ff6, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x0100003e, }; static const DWORD ps_ibfe_code[] = { #if 0 ps_5_0 dcl_globalFlags refactoringAllowed dcl_constantbuffer cb0[1], immediateIndexed dcl_output o0.xyzw ibfe o0.xyzw, cb0[0].xxxx, cb0[0].yyyy, cb0[0].zzzz ret #endif 0x43425844, 0x4b2225f7, 0xd0860f66, 0xe38775bb, 0x6d23d1d2, 0x00000001, 0x000000d4, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x0000005c, 0x00000050, 0x00000017, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x0c00008b, 0x001020f2, 0x00000000, 0x00208006, 0x00000000, 0x00000000, 0x00208556, 0x00000000, 0x00000000, 0x00208aa6, 0x00000000, 0x00000000, 0x0100003e, }; static const DWORD ps_ibfe2_code[] = { #if 0 ps_5_0 dcl_globalFlags refactoringAllowed dcl_constantbuffer cb0[1], immediateIndexed dcl_output o0.xyzw dcl_temps 1 mov r0.xyzw, cb0[0].xyzw ibfe r0.xyzw, r0.xxxx, r0.yyyy, r0.zzzz mov o0.xyzw, r0.xyzw ret #endif 0x43425844, 0x347a9c0e, 0x3eff39a4, 0x3dd41cc5, 0xff87ec8d, 0x00000001, 0x000000fc, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000084, 0x00000050, 0x00000021, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x06000036, 0x001000f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0900008b, 0x001000f2, 0x00000000, 0x00100006, 0x00000000, 0x00100556, 0x00000000, 0x00100aa6, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x0100003e, }; static const DWORD ps_ubfe_code[] = { #if 0 uint u; uint4 main() : SV_Target { return uint4((u & 0xf0) >> 4, (u & 0x7fffff00) >> 8, (u & 0xfe) >> 1, (u & 0x7fffffff) >> 1); } #endif 0x43425844, 0xc4ac0509, 0xaea83154, 0xf1fb3b80, 0x4c22e3cc, 0x00000001, 0x000000e4, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x0000006c, 0x00000050, 0x0000001b, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x1000008a, 0x001020f2, 0x00000000, 0x00004002, 0x00000004, 0x00000017, 0x00000007, 0x0000001e, 0x00004002, 0x00000004, 0x00000008, 0x00000001, 0x00000001, 0x00208006, 0x00000000, 0x00000000, 0x0100003e, }; static const DWORD ps_ubfe2_code[] = { #if 0 ps_5_0 dcl_globalFlags refactoringAllowed dcl_constantbuffer cb0[1], immediateIndexed dcl_output o0.xyzw dcl_temps 1 mov r0.xyzw, cb0[0].xyzw ubfe r0.xyzw, r0.xxxx, r0.yyyy, r0.zzzz mov o0.xyzw, r0.xyzw ret #endif 0x43425844, 0xf377b7fc, 0x1e4cb9e7, 0xb9b1020d, 0xde484388, 0x00000001, 0x000000fc, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000084, 0x00000050, 0x00000021, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x06000036, 0x001000f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0900008a, 0x001000f2, 0x00000000, 0x00100006, 0x00000000, 0x00100556, 0x00000000, 0x00100aa6, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x0100003e, }; static const DWORD ps_bfrev_code[] = { #if 0 uint bits; uint4 main() : SV_Target { return uint4(reversebits(bits), reversebits(reversebits(bits)), reversebits(bits & 0xFFFF), reversebits(bits >> 16)); } #endif 0x43425844, 0x73daef82, 0xe52befa3, 0x8504d5f0, 0xebdb321d, 0x00000001, 0x00000154, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000dc, 0x00000050, 0x00000037, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x08000001, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x0000ffff, 0x0500008d, 0x00102042, 0x00000000, 0x0010000a, 0x00000000, 0x08000055, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000010, 0x0500008d, 0x00102082, 0x00000000, 0x0010000a, 0x00000000, 0x0600008d, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0500008d, 0x00102022, 0x00000000, 0x0010000a, 0x00000000, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0100003e, }; static const DWORD ps_bits_code[] = { #if 0 uint u; int i; uint4 main() : SV_Target { return uint4(countbits(u), firstbitlow(u), firstbithigh(u), firstbithigh(i)); } #endif 0x43425844, 0x23fee911, 0x145287d1, 0xea904419, 0x8aa59a6a, 0x00000001, 0x000001b4, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x0000013c, 0x00000050, 0x0000004f, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x06000089, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x07000020, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0xffffffff, 0x0800001e, 0x00100012, 0x00000000, 0x00004001, 0x0000001f, 0x8010000a, 0x00000041, 0x00000000, 0x09000037, 0x00102082, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xffffffff, 0x0010000a, 0x00000000, 0x06000087, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0800001e, 0x00100012, 0x00000000, 0x00004001, 0x0000001f, 0x8010000a, 0x00000041, 0x00000000, 0x0a000037, 0x00102042, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0xffffffff, 0x06000086, 0x00102012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x06000088, 0x00102022, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; static const DWORD ps_ftou_code[] = { #if 0 float f; uint4 main() : SV_Target { return uint4(f, -f, 0, 0); } #endif 0x43425844, 0xfde0ee2d, 0x812b339a, 0xb9fc36d2, 0x5820bec6, 0x00000001, 0x000000f4, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000007c, 0x00000040, 0x0000001f, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x0600001c, 0x00102012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0700001c, 0x00102022, 0x00000000, 0x8020800a, 0x00000041, 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0100003e, }; static const DWORD ps_f16tof32_code[] = { #if 0 uint4 hf; uint4 main() : SV_Target { return f16tof32(hf); } #endif 0x43425844, 0xc1816e6e, 0x27562d96, 0x56980fa2, 0x421e6640, 0x00000001, 0x000000d8, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000060, 0x00000050, 0x00000018, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x06000083, 0x001000f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0500001c, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x0100003e, }; static const DWORD ps_f32tof16_code[] = { #if 0 float4 f; uint4 main() : SV_Target { return f32tof16(f); } #endif 0x43425844, 0x523a765c, 0x1a5be3a9, 0xaed69c80, 0xd26fe296, 0x00000001, 0x000000bc, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000044, 0x00000050, 0x00000011, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x06000082, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e, }; static const DWORD ps_not_code[] = { #if 0 uint2 bits; uint4 main() : SV_Target { return uint4(~bits.x, ~(bits.x ^ ~0u), ~bits.y, ~(bits.y ^ ~0u)); } #endif 0x43425844, 0xaed0fd26, 0xf719a878, 0xc832efd6, 0xba03c264, 0x00000001, 0x00000100, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000088, 0x00000040, 0x00000022, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0b000057, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00004002, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x0500003b, 0x001020a2, 0x00000000, 0x00100406, 0x00000000, 0x0600003b, 0x00102052, 0x00000000, 0x00208106, 0x00000000, 0x00000000, 0x0100003e, }; static const struct shader ps_bfi = {ps_bfi_code, sizeof(ps_bfi_code), D3D_FEATURE_LEVEL_11_0}; static const struct shader ps_bfi2 = {ps_bfi2_code, sizeof(ps_bfi2_code), D3D_FEATURE_LEVEL_11_0}; static const struct shader ps_ibfe = {ps_ibfe_code, sizeof(ps_ibfe_code), D3D_FEATURE_LEVEL_11_0}; static const struct shader ps_ibfe2 = {ps_ibfe2_code, sizeof(ps_ibfe2_code), D3D_FEATURE_LEVEL_11_0}; static const struct shader ps_ubfe = {ps_ubfe_code, sizeof(ps_ubfe_code), D3D_FEATURE_LEVEL_11_0}; static const struct shader ps_ubfe2 = {ps_ubfe2_code, sizeof(ps_ubfe2_code), D3D_FEATURE_LEVEL_11_0}; static const struct shader ps_bfrev = {ps_bfrev_code, sizeof(ps_bfrev_code), D3D_FEATURE_LEVEL_11_0}; static const struct shader ps_bits = {ps_bits_code, sizeof(ps_bits_code), D3D_FEATURE_LEVEL_11_0}; static const struct shader ps_ftou = {ps_ftou_code, sizeof(ps_ftou_code), D3D_FEATURE_LEVEL_10_0}; static const struct shader ps_f16tof32 = {ps_f16tof32_code, sizeof(ps_f16tof32_code), D3D_FEATURE_LEVEL_11_0}; static const struct shader ps_f32tof16 = {ps_f32tof16_code, sizeof(ps_f32tof16_code), D3D_FEATURE_LEVEL_11_0}; static const struct shader ps_not = {ps_not_code, sizeof(ps_not_code), D3D_FEATURE_LEVEL_10_0}; static const struct { const struct shader *ps; unsigned int bits[4]; struct uvec4 expected_result; } tests[] = { {&ps_bfi, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, {&ps_bfi, { 0, 0, 0, 1}, { 1, 1, 1, 1}}, {&ps_bfi, { ~0u, 0, ~0u, 0}, {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}}, {&ps_bfi, { ~0u, ~0u, ~0u, 0}, {0x80000000, 0x80000000, 0x80000000, 0x80000000}}, {&ps_bfi, { ~0u, 0x1fu, ~0u, 0}, {0x80000000, 0x80000000, 0x80000000, 0x80000000}}, {&ps_bfi, { ~0u, ~0x1fu, ~0u, 0}, {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}}, {&ps_bfi, { 0, 0, 0xff, 1}, { 1, 1, 1, 1}}, {&ps_bfi, { 0, 0, 0xff, 2}, { 2, 2, 2, 2}}, {&ps_bfi, { 16, 16, 0xff, 0xff}, {0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff}}, {&ps_bfi, { 0, 0, ~0u, ~0u}, { ~0u, ~0u, ~0u, ~0u}}, {&ps_bfi, {~0x1fu, 0, ~0u, 0}, { 0, 0, 0, 0}}, {&ps_bfi, {~0x1fu, 0, ~0u, 1}, { 1, 1, 1, 1}}, {&ps_bfi, {~0x1fu, 0, ~0u, 2}, { 2, 2, 2, 2}}, {&ps_bfi, { 0, ~0x1fu, ~0u, 0}, { 0, 0, 0, 0}}, {&ps_bfi, { 0, ~0x1fu, ~0u, 1}, { 1, 1, 1, 1}}, {&ps_bfi, { 0, ~0x1fu, ~0u, 2}, { 2, 2, 2, 2}}, {&ps_bfi, {~0x1fu, ~0x1fu, ~0u, 0}, { 0, 0, 0, 0}}, {&ps_bfi, {~0x1fu, ~0x1fu, ~0u, 1}, { 1, 1, 1, 1}}, {&ps_bfi, {~0x1fu, ~0x1fu, ~0u, 2}, { 2, 2, 2, 2}}, {&ps_bfi2, { ~0u, 0, ~0u, 0}, {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}}, {&ps_bfi2, { ~0u, ~0u, ~0u, 0}, {0x80000000, 0x80000000, 0x80000000, 0x80000000}}, {&ps_bfi2, { ~0u, 0x1fu, ~0u, 0}, {0x80000000, 0x80000000, 0x80000000, 0x80000000}}, {&ps_bfi2, { ~0u, ~0x1fu, ~0u, 0}, {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}}, {&ps_ibfe, { 0, 4, 0x00000000}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_ibfe, { 0, 4, 0xffffffff}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_ibfe, { 0, 4, 0x7fffffff}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_ibfe, { 4, 0, 0x00000000}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_ibfe, { 4, 0, 0xfffffffa}, {0xfffffffa, 0xfffffffa, 0xfffffffa, 0xfffffffa}}, {&ps_ibfe, { 4, 0, 0x7ffffffc}, {0xfffffffc, 0xfffffffc, 0xfffffffc, 0xfffffffc}}, {&ps_ibfe, { 4, 4, 0x00000000}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_ibfe, { 4, 4, 0xffffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, { 4, 4, 0xffffff1f}, {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, {&ps_ibfe, { 4, 4, 0x7fffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {23, 8, 0x00000000}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_ibfe, {23, 8, 0xffffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {23, 8, 0x7fffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {30, 1, 0x00000000}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_ibfe, {30, 1, 0xffffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {30, 1, 0x7fffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {15, 15, 0x7fffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {15, 15, 0x3fffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {15, 15, 0x1fffffff}, {0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff}}, {&ps_ibfe, {15, 15, 0xffff00ff}, {0xfffffffe, 0xfffffffe, 0xfffffffe, 0xfffffffe}}, {&ps_ibfe, {16, 15, 0xffffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {16, 15, 0x3fffffff}, {0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff}}, {&ps_ibfe, {20, 15, 0xffffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {31, 31, 0xffffffff}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {31, 31, 0x80000000}, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, {&ps_ibfe, {31, 31, 0x7fffffff}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_ibfe2, {16, 15, 0x3fffffff}, {0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff}}, {&ps_ubfe, {0x00000000}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_ubfe, {0xffffffff}, {0x0000000f, 0x007fffff, 0x0000007f, 0x3fffffff}}, {&ps_ubfe, {0xff000000}, {0x00000000, 0x007f0000, 0x00000000, 0x3f800000}}, {&ps_ubfe, {0x00ff0000}, {0x00000000, 0x0000ff00, 0x00000000, 0x007f8000}}, {&ps_ubfe, {0x000000ff}, {0x0000000f, 0x00000000, 0x0000007f, 0x0000007f}}, {&ps_ubfe, {0x80000001}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_ubfe, {0xc0000003}, {0x00000000, 0x00400000, 0x00000001, 0x20000001}}, {&ps_ubfe2, { 4, 4, 0x7fffffff}, {0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f}}, {&ps_ubfe2, {23, 8, 0xffffffff}, {0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff}}, {&ps_ubfe2, {30, 1, 0xffffffff}, {0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff}}, {&ps_ubfe2, {15, 15, 0x7fffffff}, {0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff}}, {&ps_ubfe2, {15, 15, 0xffff00ff}, {0x00007ffe, 0x00007ffe, 0x00007ffe, 0x00007ffe}}, {&ps_ubfe2, {16, 15, 0xffffffff}, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}}, {&ps_ubfe2, {16, 15, 0x3fffffff}, {0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff}}, {&ps_ubfe2, {20, 15, 0xffffffff}, {0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff}}, {&ps_ubfe2, {31, 31, 0xffffffff}, {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, {&ps_ubfe2, {31, 31, 0x80000000}, {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, {&ps_ubfe2, {31, 31, 0x7fffffff}, {0x00000000, 0x00000000, 0x00000000, 0x00000000}}, {&ps_bfrev, {0x12345678}, {0x1e6a2c48, 0x12345678, 0x1e6a0000, 0x2c480000}}, {&ps_bfrev, {0xffff0000}, {0x0000ffff, 0xffff0000, 0x00000000, 0xffff0000}}, {&ps_bfrev, {0xffffffff}, {0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000}}, {&ps_bits, { 0, 0}, { 0, ~0u, ~0u, ~0u}}, {&ps_bits, { ~0u, ~0u}, {32, 0, 31, ~0u}}, {&ps_bits, {0x7fffffff, 0x7fffffff}, {31, 0, 30, 30}}, {&ps_bits, {0x80000000, 0x80000000}, { 1, 31, 31, 30}}, {&ps_bits, {0x00000001, 0x00000001}, { 1, 0, 0, 0}}, {&ps_bits, {0x80000001, 0x80000001}, { 2, 0, 31, 30}}, {&ps_bits, {0x88888888, 0x88888888}, { 8, 3, 31, 30}}, {&ps_bits, {0xcccccccc, 0xcccccccc}, {16, 2, 31, 29}}, {&ps_bits, {0x11111111, 0x11111c11}, { 8, 0, 28, 28}}, {&ps_bits, {0x0000000f, 0x0000000f}, { 4, 0, 3, 3}}, {&ps_bits, {0x8000000f, 0x8000000f}, { 5, 0, 31, 30}}, {&ps_bits, {0x00080000, 0x00080000}, { 1, 19, 19, 19}}, {&ps_ftou, {BITS_NNAN}, { 0, 0}}, {&ps_ftou, {BITS_NAN}, { 0, 0}}, {&ps_ftou, {BITS_NINF}, { 0, ~0u}}, {&ps_ftou, {BITS_INF}, {~0u, 0}}, {&ps_ftou, {BITS_N1_0}, { 0, 1}}, {&ps_ftou, {BITS_1_0}, { 1, 0}}, {&ps_f16tof32, {0x00000000, 0x00003c00, 0x00005640, 0x00005bd0}, {0, 1, 100, 250}}, {&ps_f16tof32, {0x00010000, 0x00013c00, 0x00015640, 0x00015bd0}, {0, 1, 100, 250}}, {&ps_f16tof32, {0x000f0000, 0x000f3c00, 0x000f5640, 0x000f5bd0}, {0, 1, 100, 250}}, {&ps_f16tof32, {0xffff0000, 0xffff3c00, 0xffff5640, 0xffff5bd0}, {0, 1, 100, 250}}, {&ps_f32tof16, {0, BITS_1_0, BITS_N1_0, 0x44268000}, {0, 0x3c00, 0xbc00, 0x6134}}, {&ps_not, {0x00000000, 0xffffffff}, {0xffffffff, 0x00000000, 0x00000000, 0xffffffff}}, {&ps_not, {0xf0f0f0f0, 0x0f0f0f0f}, {0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f}}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; feature_level = ID3D11Device_GetFeatureLevel(device); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(tests[0].bits), NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_R32G32B32A32_UINT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); for (i = 0; i < ARRAY_SIZE(tests); ++i) { if (feature_level < tests[i].ps->required_feature_level) continue; hr = ID3D11Device_CreatePixelShader(device, tests[i].ps->code, tests[i].ps->size, NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, tests[i].bits, 0, 0); draw_quad(&test_context); check_texture_uvec4(texture, &tests[i].expected_result); ID3D11PixelShader_Release(ps); } ID3D11Buffer_Release(cb); ID3D11Texture2D_Release(texture); ID3D11RenderTargetView_Release(rtv); release_test_context(&test_context); } static void test_index_buffer_offset(void) { ID3D11Buffer *vb, *ib, *so_buffer, *args_buffer; struct d3d11_test_context test_context; ID3D11InputLayout *input_layout; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11GeometryShader *gs; const struct vec4 *data; ID3D11VertexShader *vs; ID3D11Device *device; UINT stride, offset; unsigned int i; HRESULT hr; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const DWORD vs_code[] = { #if 0 void main(float4 position : SV_POSITION, float4 attrib : ATTRIB, out float4 out_position : SV_Position, out float4 out_attrib : ATTRIB) { out_position = position; out_attrib = attrib; } #endif 0x43425844, 0xd7716716, 0xe23207f3, 0xc8af57c0, 0x585e2919, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52545441, 0xab004249, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52545441, 0xab004249, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; static const DWORD gs_code[] = { #if 0 struct vertex { float4 position : SV_POSITION; float4 attrib : ATTRIB; }; [maxvertexcount(1)] void main(point vertex input[1], inout PointStream output) { output.Append(input[0]); output.RestartStrip(); } #endif 0x43425844, 0x3d1dc497, 0xdf450406, 0x284ab03b, 0xa4ec0fd6, 0x00000001, 0x00000170, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52545441, 0xab004249, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52545441, 0xab004249, 0x52444853, 0x00000094, 0x00020040, 0x00000025, 0x05000061, 0x002010f2, 0x00000001, 0x00000000, 0x00000001, 0x0400005f, 0x002010f2, 0x00000001, 0x00000001, 0x0100085d, 0x0100085c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x0200005e, 0x00000001, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000000, 0x00000000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x01000013, 0x01000009, 0x0100003e, }; static const D3D11_INPUT_ELEMENT_DESC input_desc[] = { {"SV_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"ATTRIB", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const D3D11_SO_DECLARATION_ENTRY so_declaration[] = { {0, "SV_Position", 0, 0, 4, 0}, {0, "ATTRIB", 0, 0, 4, 0}, }; static const struct { struct vec4 position; struct vec4 attrib; } vertices[] = { {{-1.0f, -1.0f, 0.0f, 1.0f}, {1.0f}}, {{-1.0f, 1.0f, 0.0f, 1.0f}, {2.0f}}, {{ 1.0f, -1.0f, 0.0f, 1.0f}, {3.0f}}, {{ 1.0f, 1.0f, 0.0f, 1.0f}, {4.0f}}, }; static const unsigned int indices[] = { 0, 1, 2, 3, 3, 2, 1, 0, 1, 3, 2, 0, }; static const struct vec4 expected_data[] = { {-1.0f, -1.0f, 0.0f, 1.0f}, {1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f}, {2.0f}, { 1.0f, -1.0f, 0.0f, 1.0f}, {3.0f}, { 1.0f, 1.0f, 0.0f, 1.0f}, {4.0f}, { 1.0f, 1.0f, 0.0f, 1.0f}, {4.0f}, { 1.0f, -1.0f, 0.0f, 1.0f}, {3.0f}, {-1.0f, 1.0f, 0.0f, 1.0f}, {2.0f}, {-1.0f, -1.0f, 0.0f, 1.0f}, {1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f}, {2.0f}, { 1.0f, 1.0f, 0.0f, 1.0f}, {4.0f}, { 1.0f, -1.0f, 0.0f, 1.0f}, {3.0f}, {-1.0f, -1.0f, 0.0f, 1.0f}, {1.0f}, }; static const struct vec4 broken_result = {0.0f, 0.0f, 0.0f, 1.0f}; static const D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS argument_data[] = { {4, 1, 0, 0, 0}, }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateInputLayout(device, input_desc, ARRAY_SIZE(input_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); stride = 32; hr = ID3D11Device_CreateGeometryShaderWithStreamOutput(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), &stride, 1, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &gs); ok(SUCCEEDED(hr), "Failed to create geometry shader with stream output, hr %#x.\n", hr); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(vertices), vertices); ib = create_buffer(device, D3D11_BIND_INDEX_BUFFER, sizeof(indices), indices); so_buffer = create_buffer(device, D3D11_BIND_STREAM_OUTPUT, 1024, NULL); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); stride = sizeof(*vertices); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, &stride, &offset); offset = 0; ID3D11DeviceContext_SOSetTargets(context, 1, &so_buffer, &offset); ID3D11DeviceContext_IASetIndexBuffer(context, ib, DXGI_FORMAT_R32_UINT, 0); ID3D11DeviceContext_DrawIndexed(context, 4, 0, 0); ID3D11DeviceContext_IASetIndexBuffer(context, ib, DXGI_FORMAT_R32_UINT, 4 * sizeof(*indices)); ID3D11DeviceContext_DrawIndexed(context, 4, 0, 0); ID3D11DeviceContext_IASetIndexBuffer(context, ib, DXGI_FORMAT_R32_UINT, 8 * sizeof(*indices)); ID3D11DeviceContext_DrawIndexed(context, 4, 0, 0); get_buffer_readback(so_buffer, &rb); for (i = 0; i < ARRAY_SIZE(expected_data); ++i) { data = get_readback_vec4(&rb, i, 0); ok(compare_vec4(data, &expected_data[i], 0) || broken(is_nvidia_device(device) && !(i % 2) && compare_vec4(data, &broken_result, 0)), "Got unexpected result {%.8e, %.8e, %.8e, %.8e} at %u.\n", data->x, data->y, data->z, data->w, i); } release_resource_readback(&rb); /* indirect draws */ args_buffer = create_buffer_misc(device, 0, D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS, sizeof(argument_data), argument_data); offset = 0; ID3D11DeviceContext_SOSetTargets(context, 1, &so_buffer, &offset); ID3D11DeviceContext_IASetIndexBuffer(context, ib, DXGI_FORMAT_R32_UINT, 0); ID3D11DeviceContext_DrawIndexedInstancedIndirect(context, args_buffer, 0); ID3D11DeviceContext_IASetIndexBuffer(context, ib, DXGI_FORMAT_R32_UINT, 4 * sizeof(*indices)); ID3D11DeviceContext_DrawIndexedInstancedIndirect(context, args_buffer, 0); ID3D11DeviceContext_IASetIndexBuffer(context, ib, DXGI_FORMAT_R32_UINT, 8 * sizeof(*indices)); ID3D11DeviceContext_DrawIndexedInstancedIndirect(context, args_buffer, 0); get_buffer_readback(so_buffer, &rb); for (i = 0; i < ARRAY_SIZE(expected_data); ++i) { data = get_readback_vec4(&rb, i, 0); todo_wine_if(i >= 8 && i != 20 && i != 21) ok(compare_vec4(data, &expected_data[i], 0) || broken(is_nvidia_device(device) && !(i % 2) && compare_vec4(data, &broken_result, 0)), "Got unexpected result {%.8e, %.8e, %.8e, %.8e} at %u.\n", data->x, data->y, data->z, data->w, i); } release_resource_readback(&rb); ID3D11Buffer_Release(so_buffer); ID3D11Buffer_Release(args_buffer); ID3D11Buffer_Release(ib); ID3D11Buffer_Release(vb); ID3D11VertexShader_Release(vs); ID3D11GeometryShader_Release(gs); ID3D11InputLayout_Release(input_layout); release_test_context(&test_context); } static void test_face_culling(void) { struct d3d11_test_context test_context; D3D11_RASTERIZER_DESC rasterizer_desc; ID3D11RasterizerState *state; ID3D11DeviceContext *context; ID3D11Buffer *cw_vb, *ccw_vb; ID3D11Device *device; BOOL broken_warp; unsigned int i; HRESULT hr; static const struct vec4 red = {1.0f, 0.0f, 0.0f, 1.0f}; static const struct vec4 green = {0.0f, 1.0f, 0.0f, 1.0f}; static const DWORD ps_code[] = { #if 0 float4 main(uint front : SV_IsFrontFace) : SV_Target { return (front == ~0u) ? float4(0.0f, 1.0f, 0.0f, 1.0f) : float4(0.0f, 0.0f, 1.0f, 1.0f); } #endif 0x43425844, 0x92002fad, 0xc5c620b9, 0xe7a154fb, 0x78b54e63, 0x00000001, 0x00000128, 0x00000003, 0x0000002c, 0x00000064, 0x00000098, 0x4e475349, 0x00000030, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000009, 0x00000001, 0x00000000, 0x00000101, 0x495f5653, 0x6f724673, 0x6146746e, 0xab006563, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000088, 0x00000040, 0x00000022, 0x04000863, 0x00101012, 0x00000000, 0x00000009, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x07000020, 0x00100012, 0x00000000, 0x0010100a, 0x00000000, 0x00004001, 0xffffffff, 0x0f000037, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x00004002, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x0100003e, }; static const struct vec3 ccw_quad[] = { {-1.0f, 1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}, { 1.0f, 1.0f, 0.0f}, { 1.0f, -1.0f, 0.0f}, }; static const struct { D3D11_CULL_MODE cull_mode; BOOL front_ccw; BOOL expected_cw; BOOL expected_ccw; } tests[] = { {D3D11_CULL_NONE, FALSE, TRUE, TRUE}, {D3D11_CULL_NONE, TRUE, TRUE, TRUE}, {D3D11_CULL_FRONT, FALSE, FALSE, TRUE}, {D3D11_CULL_FRONT, TRUE, TRUE, FALSE}, {D3D11_CULL_BACK, FALSE, TRUE, FALSE}, {D3D11_CULL_BACK, TRUE, FALSE, TRUE}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); cw_vb = test_context.vb; ccw_vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(ccw_quad), ccw_quad); test_context.vb = ccw_vb; ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff0000ff, 0); rasterizer_desc.FillMode = D3D11_FILL_SOLID; rasterizer_desc.CullMode = D3D11_CULL_BACK; rasterizer_desc.FrontCounterClockwise = FALSE; rasterizer_desc.DepthBias = 0; rasterizer_desc.DepthBiasClamp = 0.0f; rasterizer_desc.SlopeScaledDepthBias = 0.0f; rasterizer_desc.DepthClipEnable = TRUE; rasterizer_desc.ScissorEnable = FALSE; rasterizer_desc.MultisampleEnable = FALSE; rasterizer_desc.AntialiasedLineEnable = FALSE; for (i = 0; i < ARRAY_SIZE(tests); ++i) { rasterizer_desc.CullMode = tests[i].cull_mode; rasterizer_desc.FrontCounterClockwise = tests[i].front_ccw; hr = ID3D11Device_CreateRasterizerState(device, &rasterizer_desc, &state); ok(SUCCEEDED(hr), "Test %u: Failed to create rasterizer state, hr %#x.\n", i, hr); ID3D11DeviceContext_RSSetState(context, state); test_context.vb = cw_vb; ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, tests[i].expected_cw ? 0xff00ff00 : 0xff0000ff, 0); test_context.vb = ccw_vb; ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, tests[i].expected_ccw ? 0xff00ff00 : 0xff0000ff, 0); ID3D11RasterizerState_Release(state); } broken_warp = is_warp_device(device) && ID3D11Device_GetFeatureLevel(device) < D3D_FEATURE_LEVEL_11_0; /* Test SV_IsFrontFace. */ ID3D11PixelShader_Release(test_context.ps); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &test_context.ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); rasterizer_desc.CullMode = D3D11_CULL_NONE; rasterizer_desc.FrontCounterClockwise = FALSE; hr = ID3D11Device_CreateRasterizerState(device, &rasterizer_desc, &state); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ID3D11DeviceContext_RSSetState(context, state); test_context.vb = cw_vb; ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); test_context.vb = ccw_vb; ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); if (!broken_warp) check_texture_color(test_context.backbuffer, 0xffff0000, 0); else win_skip("Broken WARP.\n"); ID3D11RasterizerState_Release(state); rasterizer_desc.CullMode = D3D11_CULL_NONE; rasterizer_desc.FrontCounterClockwise = TRUE; hr = ID3D11Device_CreateRasterizerState(device, &rasterizer_desc, &state); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ID3D11DeviceContext_RSSetState(context, state); test_context.vb = cw_vb; ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); if (!broken_warp) check_texture_color(test_context.backbuffer, 0xffff0000 , 0); else win_skip("Broken WARP.\n"); test_context.vb = ccw_vb; ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); ID3D11RasterizerState_Release(state); test_context.vb = cw_vb; ID3D11Buffer_Release(ccw_vb); release_test_context(&test_context); } static void test_line_antialiasing_blending(void) { ID3D11RasterizerState *rasterizer_state; struct d3d11_test_context test_context; D3D11_RASTERIZER_DESC rasterizer_desc; ID3D11BlendState *blend_state; ID3D11DeviceContext *context; D3D11_BLEND_DESC blend_desc; ID3D11Device *device; HRESULT hr; static const struct vec4 red = {1.0f, 0.0f, 0.0f, 0.8f}; static const struct vec4 green = {0.0f, 1.0f, 0.0f, 0.5f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; memset(&blend_desc, 0, sizeof(blend_desc)); blend_desc.AlphaToCoverageEnable = FALSE; blend_desc.IndependentBlendEnable = FALSE; blend_desc.RenderTarget[0].BlendEnable = TRUE; blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_DEST_ALPHA; blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA; blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &blend_state); ok(SUCCEEDED(hr), "Failed to create blend state, hr %#x.\n", hr); ID3D11DeviceContext_OMSetBlendState(context, blend_state, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xe2007fcc, 1); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &green.x); draw_color_quad(&test_context, &red); check_texture_color(test_context.backbuffer, 0xe2007fcc, 1); ID3D11DeviceContext_OMSetBlendState(context, NULL, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11BlendState_Release(blend_state); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0x7f00ff00, 1); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &green.x); draw_color_quad(&test_context, &red); check_texture_color(test_context.backbuffer, 0xcc0000ff, 1); rasterizer_desc.FillMode = D3D11_FILL_SOLID; rasterizer_desc.CullMode = D3D11_CULL_BACK; rasterizer_desc.FrontCounterClockwise = FALSE; rasterizer_desc.DepthBias = 0; rasterizer_desc.DepthBiasClamp = 0.0f; rasterizer_desc.SlopeScaledDepthBias = 0.0f; rasterizer_desc.DepthClipEnable = TRUE; rasterizer_desc.ScissorEnable = FALSE; rasterizer_desc.MultisampleEnable = FALSE; rasterizer_desc.AntialiasedLineEnable = TRUE; hr = ID3D11Device_CreateRasterizerState(device, &rasterizer_desc, &rasterizer_state); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ID3D11DeviceContext_RSSetState(context, rasterizer_state); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &red.x); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0x7f00ff00, 1); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &green.x); draw_color_quad(&test_context, &red); check_texture_color(test_context.backbuffer, 0xcc0000ff, 1); ID3D11RasterizerState_Release(rasterizer_state); release_test_context(&test_context); } static void check_format_support(const unsigned int *format_support, D3D_FEATURE_LEVEL feature_level, const struct format_support *formats, unsigned int format_count, unsigned int feature_flag, const char *feature_name) { unsigned int i; for (i = 0; i < format_count; ++i) { DXGI_FORMAT format = formats[i].format; unsigned int supported = format_support[format] & feature_flag; if (formats[i].fl_required <= feature_level) { todo_wine ok(supported, "Format %#x - %s not supported, feature_level %#x, format support %#x.\n", format, feature_name, feature_level, format_support[format]); continue; } if (formats[i].fl_optional && formats[i].fl_optional <= feature_level) { if (supported) trace("Optional format %#x - %s supported, feature level %#x.\n", format, feature_name, feature_level); continue; } ok(!supported, "Format %#x - %s supported, feature level %#x, format support %#x.\n", format, feature_name, feature_level, format_support[format]); } } static void test_format_support(const D3D_FEATURE_LEVEL feature_level) { unsigned int format_support[DXGI_FORMAT_B4G4R4A4_UNORM + 1]; struct device_desc device_desc; ID3D11Device *device; DXGI_FORMAT format; ULONG refcount; UINT support; HRESULT hr; static const struct format_support index_buffers[] = { {DXGI_FORMAT_R32_UINT, D3D_FEATURE_LEVEL_9_2}, {DXGI_FORMAT_R16_UINT, D3D_FEATURE_LEVEL_9_1}, }; device_desc.feature_level = &feature_level; device_desc.flags = 0; if (!(device = create_device(&device_desc))) { skip("Failed to create device for feature level %#x.\n", feature_level); return; } support = 0xdeadbeef; hr = ID3D11Device_CheckFormatSupport(device, ~0u, &support); ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr); ok(!support, "Got unexpected format support %#x.\n", support); memset(format_support, 0, sizeof(format_support)); for (format = DXGI_FORMAT_UNKNOWN; format <= DXGI_FORMAT_B4G4R4A4_UNORM; ++format) { hr = ID3D11Device_CheckFormatSupport(device, format, &format_support[format]); ok(hr == S_OK || (hr == E_FAIL && !format_support[format]), "Got unexpected result for format %#x: hr %#x, format_support %#x.\n", format, hr, format_support[format]); if (format_support[format] & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) { ok(format_support[format] & D3D11_FORMAT_SUPPORT_TEXTURE2D, "Got unexpected format support %#x for format %#x", format_support[format], format); } } for (format = DXGI_FORMAT_UNKNOWN; format <= DXGI_FORMAT_B4G4R4A4_UNORM; ++format) { if (feature_level < D3D_FEATURE_LEVEL_10_0) { /* SHADER_SAMPLE_COMPARISON is never advertised as supported on feature level 9. */ ok(!(format_support[format] & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON), "Unexpected SHADER_SAMPLE_COMPARISON for format %#x, feature level %#x.\n", format, feature_level); } if (feature_level < D3D_FEATURE_LEVEL_10_1) { ok(!(format_support[format] & D3D11_FORMAT_SUPPORT_SHADER_GATHER), "Unexpected SHADER_GATHER for format %#x, feature level %#x.\n", format, feature_level); ok(!(format_support[format] & D3D11_FORMAT_SUPPORT_SHADER_GATHER_COMPARISON), "Unexpected SHADER_GATHER_COMPARISON for format %#x, feature level %#x.\n", format, feature_level); } } ok(format_support[DXGI_FORMAT_R8G8B8A8_UNORM] & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE, "SHADER_SAMPLE is not supported for R8G8B8A8_UNORM.\n"); todo_wine ok(!(format_support[DXGI_FORMAT_R32G32B32A32_UINT] & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE), "SHADER_SAMPLE is supported for R32G32B32A32_UINT.\n"); if (feature_level >= D3D_FEATURE_LEVEL_10_0) { ok(format_support[DXGI_FORMAT_R32G32B32A32_UINT] & D3D11_FORMAT_SUPPORT_SHADER_LOAD, "SHADER_LOAD is not supported for R32G32B32A32_UINT.\n"); } check_format_support(format_support, feature_level, index_buffers, ARRAY_SIZE(index_buffers), D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER, "index buffer"); check_format_support(format_support, feature_level, display_format_support, ARRAY_SIZE(display_format_support), D3D11_FORMAT_SUPPORT_DISPLAY, "display"); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_fl9_draw(const D3D_FEATURE_LEVEL feature_level) { struct d3d11_test_context test_context; D3D11_SUBRESOURCE_DATA resource_data; D3D11_TEXTURE2D_DESC texture_desc; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const struct vec4 color = {0.2f, 0.3f, 0.0f, 1.0f}; static const DWORD ps_code[] = { #if 0 float4 main() : SV_TARGET { return float4(1.0f, 0.0f, 0.0f, 0.5f); } #endif 0x43425844, 0xb70eda74, 0xc9a7f982, 0xebc31bbf, 0x952a1360, 0x00000001, 0x00000168, 0x00000005, 0x00000034, 0x0000008c, 0x000000e4, 0x00000124, 0x00000134, 0x53414e58, 0x00000050, 0x00000050, 0xffff0200, 0x0000002c, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0xffff0200, 0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f000000, 0x02000001, 0x800f0800, 0xa0e40000, 0x0000ffff, 0x396e6f41, 0x00000050, 0x00000050, 0xffff0200, 0x0000002c, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0xffff0200, 0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f000000, 0x02000001, 0x800f0800, 0xa0e40000, 0x0000ffff, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03000065, 0x001020f2, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f000000, 0x0100003e, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, }; static const DWORD ps_texture_code[] = { #if 0 Texture2D t; SamplerState s; float4 main() : SV_TARGET { return t.Sample(s, (float2)0); } #endif 0x43425844, 0xf876c2db, 0x13725f1f, 0xcb6d3d65, 0x9994473f, 0x00000001, 0x000001d4, 0x00000005, 0x00000034, 0x000000a0, 0x00000124, 0x00000190, 0x000001a0, 0x53414e58, 0x00000064, 0x00000064, 0xffff0200, 0x0000003c, 0x00000028, 0x00280000, 0x00280000, 0x00280000, 0x00240001, 0x00280000, 0x00000000, 0xffff0200, 0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x90000000, 0xa00f0800, 0x03000042, 0x800f0800, 0xa0000000, 0xa0e40800, 0x0000ffff, 0x396e6f41, 0x0000007c, 0x0000007c, 0xffff0200, 0x00000054, 0x00000028, 0x00280000, 0x00280000, 0x00280000, 0x00240001, 0x00280000, 0x00000000, 0xffff0200, 0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x90000000, 0xa00f0800, 0x02000001, 0x80030000, 0xa0000000, 0x03000042, 0x800f0000, 0x80e40000, 0xa0e40800, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff, 0x52444853, 0x00000064, 0x00000040, 0x00000019, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x0c000045, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, }; static const DWORD texture_data[] = {0xffffff00}; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 1; texture_desc.Height = 1; texture_desc.MipLevels = 0; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; resource_data.pSysMem = texture_data; resource_data.SysMemPitch = sizeof(texture_data); resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &texture); ok(SUCCEEDED(hr), "Failed to create 2d texture, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x, feature level %#x.\n", hr, feature_level); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0x7f0000ff, 1); ID3D11PixelShader_Release(ps); draw_color_quad(&test_context, &color); todo_wine check_texture_color(test_context.backbuffer, 0xff004c33, 1); hr = ID3D11Device_CreatePixelShader(device, ps_texture_code, sizeof(ps_texture_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x, feature level %#x.\n", hr, feature_level); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xffffff00, 1); ID3D11PixelShader_Release(ps); ID3D11ShaderResourceView_Release(srv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void queue_for_each_feature_level_in_range(D3D_FEATURE_LEVEL begin, D3D_FEATURE_LEVEL end, void (*test_func)(const D3D_FEATURE_LEVEL fl)) { static const D3D_FEATURE_LEVEL feature_levels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; unsigned int i; assert(begin <= end); for (i = 0; i < ARRAY_SIZE(feature_levels); ++i) { if (begin <= feature_levels[i] && feature_levels[i] <= end) queue_test_fl(test_func, feature_levels[i]); } } static void queue_for_each_feature_level(void (*test_func)(const D3D_FEATURE_LEVEL fl)) { queue_for_each_feature_level_in_range(D3D_FEATURE_LEVEL_9_1, D3D_FEATURE_LEVEL_11_1, test_func); } static void queue_for_each_9_x_feature_level(void (*test_func)(const D3D_FEATURE_LEVEL fl)) { queue_for_each_feature_level_in_range(D3D_FEATURE_LEVEL_9_1, D3D_FEATURE_LEVEL_9_3, test_func); } static void test_ddy(void) { static const struct { struct vec4 position; unsigned int color; } quad[] = { {{-1.0f, -1.0f, 0.0f, 1.0f}, 0x00ff0000}, {{-1.0f, 1.0f, 0.0f, 1.0f}, 0x0000ff00}, {{ 1.0f, -1.0f, 0.0f, 1.0f}, 0x00ff0000}, {{ 1.0f, 1.0f, 0.0f, 1.0f}, 0x0000ff00}, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"SV_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; #if 0 struct vs_data { float4 pos : SV_POSITION; float4 color : COLOR; }; void main(in struct vs_data vs_input, out struct vs_data vs_output) { vs_output.pos = vs_input.pos; vs_output.color = vs_input.color; } #endif static const DWORD vs_code[] = { 0x43425844, 0xd5b32785, 0x35332906, 0x4d05e031, 0xf66a58af, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; #if 0 struct ps_data { float4 pos : SV_POSITION; float4 color : COLOR; }; float4 main(struct ps_data ps_input) : SV_Target { return ddy(ps_input.color) * 240.0 + 0.5; } #endif static const DWORD ps_code_ddy[] = { 0x43425844, 0x423712f6, 0x786c59c2, 0xa6023c60, 0xb79faad2, 0x00000001, 0x00000138, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000007c, 0x00000040, 0x0000001f, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0500000c, 0x001000f2, 0x00000000, 0x00101e46, 0x00000001, 0x0f000032, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x43700000, 0x43700000, 0x43700000, 0x43700000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x0100003e, }; #if 0 struct ps_data { float4 pos : SV_POSITION; float4 color : COLOR; }; float4 main(struct ps_data ps_input) : SV_Target { return ddy_coarse(ps_input.color) * 240.0 + 0.5; } #endif static const DWORD ps_code_ddy_coarse[] = { 0x43425844, 0xbf9a31cb, 0xb42695b6, 0x629119b8, 0x6962d5dd, 0x00000001, 0x0000013c, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000080, 0x00000050, 0x00000020, 0x0100086a, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0500007c, 0x001000f2, 0x00000000, 0x00101e46, 0x00000001, 0x0f000032, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x43700000, 0x43700000, 0x43700000, 0x43700000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x0100003e, }; #if 0 struct ps_data { float4 pos : SV_POSITION; float4 color : COLOR; }; float4 main(struct ps_data ps_input) : SV_Target { return ddy_fine(ps_input.color) * 240.0 + 0.5; } #endif static const DWORD ps_code_ddy_fine[] = { 0x43425844, 0xea6563ae, 0x3ee0da50, 0x4c2b3ef3, 0xa69a4077, 0x00000001, 0x0000013c, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000080, 0x00000050, 0x00000020, 0x0100086a, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0500007d, 0x001000f2, 0x00000000, 0x00101e46, 0x00000001, 0x0f000032, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x43700000, 0x43700000, 0x43700000, 0x43700000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x0100003e, }; static const struct { D3D_FEATURE_LEVEL min_feature_level; const DWORD *ps_code; unsigned int ps_code_size; } tests[] = { {D3D_FEATURE_LEVEL_10_0, ps_code_ddy, sizeof(ps_code_ddy)}, {D3D_FEATURE_LEVEL_11_0, ps_code_ddy_coarse, sizeof(ps_code_ddy_coarse)}, {D3D_FEATURE_LEVEL_11_0, ps_code_ddy_fine, sizeof(ps_code_ddy_fine)}, }; static const float red[] = {1.0f, 0.0f, 0.0f, 1.0f}; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; D3D_FEATURE_LEVEL feature_level; ID3D11InputLayout *input_layout; ID3D11DeviceContext *context; unsigned int stride, offset; struct resource_readback rb; ID3D11RenderTargetView *rtv; ID3D11Texture2D *texture; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *vb; unsigned int i; DWORD color; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; feature_level = ID3D11Device_GetFeatureLevel(device); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(quad), quad); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); stride = sizeof(*quad); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, &stride, &offset); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); for (i = 0; i < ARRAY_SIZE(tests); ++i) { if (feature_level < tests[i].min_feature_level) { skip("Skipping test %u, feature_level %#x lower than minimum required %#x.\n", i, feature_level, tests[i].min_feature_level); continue; } hr = ID3D11Device_CreatePixelShader(device, tests[i].ps_code, tests[i].ps_code_size, NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, red); ID3D11DeviceContext_Draw(context, 4, 0); get_texture_readback(texture, 0, &rb); color = get_readback_color(&rb, 320, 190, 0); ok(compare_color(color, 0x7fff007f, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 255, 240, 0); ok(compare_color(color, 0x7fff007f, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 320, 240, 0); ok(compare_color(color, 0x7fff007f, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 385, 240, 0); ok(compare_color(color, 0x7fff007f, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 320, 290, 0); ok(compare_color(color, 0x7fff007f, 1), "Got unexpected color 0x%08x.\n", color); release_resource_readback(&rb); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, NULL); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); ID3D11DeviceContext_Draw(context, 4, 0); get_texture_readback(test_context.backbuffer, 0, &rb); color = get_readback_color(&rb, 320, 190, 0); ok(compare_color(color, 0x7fff007f, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 255, 240, 0); ok(compare_color(color, 0x7fff007f, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 320, 240, 0); ok(compare_color(color, 0x7fff007f, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 385, 240, 0); ok(compare_color(color, 0x7fff007f, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 320, 290, 0); ok(compare_color(color, 0x7fff007f, 1), "Got unexpected color 0x%08x.\n", color); release_resource_readback(&rb); ID3D11PixelShader_Release(ps); } ID3D11VertexShader_Release(vs); ID3D11Buffer_Release(vb); ID3D11InputLayout_Release(input_layout); ID3D11Texture2D_Release(texture); ID3D11RenderTargetView_Release(rtv); release_test_context(&test_context); } static void test_shader_input_registers_limits(void) { struct d3d11_test_context test_context; D3D11_SUBRESOURCE_DATA resource_data; D3D11_TEXTURE2D_DESC texture_desc; D3D11_SAMPLER_DESC sampler_desc; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; ID3D11SamplerState *sampler; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DWORD ps_last_register_code[] = { #if 0 Texture2D t : register(t127); SamplerState s : register(s15); void main(out float4 target : SV_Target) { target = t.Sample(s, float2(0, 0)); } #endif 0x43425844, 0xd81ff2f8, 0x8c704b9c, 0x8c6f4857, 0xd02949ac, 0x00000001, 0x000000dc, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000064, 0x00000040, 0x00000019, 0x0300005a, 0x00106000, 0x0000000f, 0x04001858, 0x00107000, 0x0000007f, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x0c000045, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x0000007f, 0x00106000, 0x0000000f, 0x0100003e, }; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const DWORD texture_data[] = {0xff00ff00}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 1; texture_desc.Height = 1; texture_desc.MipLevels = 0; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; resource_data.pSysMem = texture_data; resource_data.SysMemPitch = sizeof(texture_data); resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &texture); ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = 0.0f; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_last_register_code, sizeof(ps_last_register_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_PSSetShaderResources(context, D3D11_COMMONSHADER_INPUT_RESOURCE_REGISTER_COUNT - 1, 1, &srv); ID3D11DeviceContext_PSSetSamplers(context, D3D11_COMMONSHADER_SAMPLER_REGISTER_COUNT - 1, 1, &sampler); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); ID3D11PixelShader_Release(ps); ID3D11SamplerState_Release(sampler); ID3D11ShaderResourceView_Release(srv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_unbind_shader_resource_view(void) { struct d3d11_test_context test_context; D3D11_SUBRESOURCE_DATA resource_data; ID3D11ShaderResourceView *srv, *srv2; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DWORD ps_code[] = { #if 0 Texture2D t0; Texture2D t1; SamplerState s; float4 main() : SV_Target { return min(t0.Sample(s, float2(0, 0)) + t1.Sample(s, float2(0, 0)), 1.0f); } #endif 0x43425844, 0x698dc0cb, 0x0bf322b8, 0xee127418, 0xfe9214ce, 0x00000001, 0x00000168, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000f0, 0x00000040, 0x0000003c, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0c000045, 0x001000f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0c000045, 0x001000f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x07000000, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100e46, 0x00000001, 0x0a000033, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x0100003e, }; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const DWORD texture_data[] = {0xff00ff00}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 1; texture_desc.Height = 1; texture_desc.MipLevels = 0; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; resource_data.pSysMem = texture_data; resource_data.SysMemPitch = sizeof(texture_data); resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &texture); ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); ID3D11DeviceContext_PSSetShaderResources(context, 1, 1, &srv); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); srv2 = NULL; ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv2); ID3D11DeviceContext_PSSetShaderResources(context, 1, 1, &srv2); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_quad(&test_context); todo_wine check_texture_color(test_context.backbuffer, 0x00000000, 1); ID3D11PixelShader_Release(ps); ID3D11ShaderResourceView_Release(srv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_stencil_separate(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; D3D11_DEPTH_STENCIL_DESC ds_desc; ID3D11DepthStencilState *ds_state; ID3D11DepthStencilView *ds_view; D3D11_RASTERIZER_DESC rs_desc; ID3D11DeviceContext *context; ID3D11RasterizerState *rs; ID3D11Texture2D *texture; ID3D11Device *device; HRESULT hr; static const float red[] = {1.0f, 0.0f, 0.0f, 1.0f}; static const struct vec4 green = {0.0f, 1.0f, 0.0f, 1.0f}; static const struct vec3 ccw_quad[] = { {-1.0f, -1.0f, 0.0f}, { 1.0f, -1.0f, 0.0f}, {-1.0f, 1.0f, 0.0f}, { 1.0f, 1.0f, 0.0f}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 640; texture_desc.Height = 480; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, NULL, &ds_view); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); ds_desc.DepthEnable = TRUE; ds_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; ds_desc.DepthFunc = D3D11_COMPARISON_LESS; ds_desc.StencilEnable = TRUE; ds_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; ds_desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; ds_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_ZERO; ds_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_ZERO; ds_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_ZERO; ds_desc.FrontFace.StencilFunc = D3D11_COMPARISON_NEVER; ds_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_ZERO; ds_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_ZERO; ds_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_ZERO; ds_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; hr = ID3D11Device_CreateDepthStencilState(device, &ds_desc, &ds_state); ok(SUCCEEDED(hr), "Failed to create depth stencil state, hr %#x.\n", hr); rs_desc.FillMode = D3D11_FILL_SOLID; rs_desc.CullMode = D3D11_CULL_NONE; rs_desc.FrontCounterClockwise = FALSE; rs_desc.DepthBias = 0; rs_desc.DepthBiasClamp = 0.0f; rs_desc.SlopeScaledDepthBias = 0.0f; rs_desc.DepthClipEnable = TRUE; rs_desc.ScissorEnable = FALSE; rs_desc.MultisampleEnable = FALSE; rs_desc.AntialiasedLineEnable = FALSE; ID3D11Device_CreateRasterizerState(device, &rs_desc, &rs); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); ID3D11DeviceContext_ClearDepthStencilView(context, ds_view, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, ds_view); ID3D11DeviceContext_OMSetDepthStencilState(context, ds_state, 0); ID3D11DeviceContext_RSSetState(context, rs); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff0000ff, 1); ID3D11Buffer_Release(test_context.vb); test_context.vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(ccw_quad), ccw_quad); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); ID3D11RasterizerState_Release(rs); rs_desc.FrontCounterClockwise = TRUE; ID3D11Device_CreateRasterizerState(device, &rs_desc, &rs); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ID3D11DeviceContext_RSSetState(context, rs); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff0000ff, 1); ID3D11DepthStencilState_Release(ds_state); ID3D11DepthStencilView_Release(ds_view); ID3D11RasterizerState_Release(rs); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_uav_load(void) { struct shader { const DWORD *code; size_t size; }; struct texture { UINT width; UINT height; UINT miplevel_count; UINT array_size; DXGI_FORMAT format; D3D11_SUBRESOURCE_DATA data[3]; }; ID3D11RenderTargetView *rtv_float, *rtv_uint, *rtv_sint; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; D3D11_RENDER_TARGET_VIEW_DESC rtv_desc; struct d3d11_test_context test_context; const struct texture *current_texture; ID3D11Texture2D *texture, *rt_texture; D3D11_TEXTURE2D_DESC texture_desc; const struct shader *current_ps; ID3D11UnorderedAccessView *uav; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, x, y; ID3D11Buffer *cb; HRESULT hr; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const DWORD ps_ld_2d_float_code[] = { #if 0 RWTexture2D u; float main(float4 position : SV_Position) : SV_Target { float2 s; u.GetDimensions(s.x, s.y); return u[s * float2(position.x / 640.0f, position.y / 480.0f)]; } #endif 0x43425844, 0xd5996e04, 0x6bede909, 0x0a7ad18e, 0x5eb277fb, 0x00000001, 0x00000194, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000e01, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000f8, 0x00000050, 0x0000003e, 0x0100086a, 0x0400189c, 0x0011e000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000000, 0x02000068, 0x00000001, 0x8900003d, 0x800000c2, 0x00155543, 0x00100032, 0x00000000, 0x00004001, 0x00000000, 0x0011ee46, 0x00000001, 0x07000038, 0x001000f2, 0x00000000, 0x00100546, 0x00000000, 0x00101546, 0x00000000, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x3b088889, 0x3b088889, 0x0500001c, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x890000a3, 0x800000c2, 0x00155543, 0x00100012, 0x00000000, 0x00100e46, 0x00000000, 0x0011ee46, 0x00000001, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0100003e, }; static const struct shader ps_ld_2d_float = {ps_ld_2d_float_code, sizeof(ps_ld_2d_float_code)}; static const DWORD ps_ld_2d_uint_code[] = { #if 0 RWTexture2D u; uint main(float4 position : SV_Position) : SV_Target { float2 s; u.GetDimensions(s.x, s.y); return u[s * float2(position.x / 640.0f, position.y / 480.0f)]; } #endif 0x43425844, 0x2cc0af18, 0xb28eca73, 0x9651215b, 0xebe3f361, 0x00000001, 0x00000194, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000e01, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000f8, 0x00000050, 0x0000003e, 0x0100086a, 0x0400189c, 0x0011e000, 0x00000001, 0x00004444, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000000, 0x02000068, 0x00000001, 0x8900003d, 0x800000c2, 0x00111103, 0x00100032, 0x00000000, 0x00004001, 0x00000000, 0x0011ee46, 0x00000001, 0x07000038, 0x001000f2, 0x00000000, 0x00100546, 0x00000000, 0x00101546, 0x00000000, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x3b088889, 0x3b088889, 0x0500001c, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x890000a3, 0x800000c2, 0x00111103, 0x00100012, 0x00000000, 0x00100e46, 0x00000000, 0x0011ee46, 0x00000001, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0100003e, }; static const struct shader ps_ld_2d_uint = {ps_ld_2d_uint_code, sizeof(ps_ld_2d_uint_code)}; static const DWORD ps_ld_2d_int_code[] = { #if 0 RWTexture2D u; int main(float4 position : SV_Position) : SV_Target { float2 s; u.GetDimensions(s.x, s.y); return u[s * float2(position.x / 640.0f, position.y / 480.0f)]; } #endif 0x43425844, 0x7deee248, 0xe7c48698, 0x9454db00, 0x921810e7, 0x00000001, 0x00000194, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000e01, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000f8, 0x00000050, 0x0000003e, 0x0100086a, 0x0400189c, 0x0011e000, 0x00000001, 0x00003333, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000000, 0x02000068, 0x00000001, 0x8900003d, 0x800000c2, 0x000cccc3, 0x00100032, 0x00000000, 0x00004001, 0x00000000, 0x0011ee46, 0x00000001, 0x07000038, 0x001000f2, 0x00000000, 0x00100546, 0x00000000, 0x00101546, 0x00000000, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x3b088889, 0x3b088889, 0x0500001c, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x890000a3, 0x800000c2, 0x000cccc3, 0x00100012, 0x00000000, 0x00100e46, 0x00000000, 0x0011ee46, 0x00000001, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0100003e, }; static const struct shader ps_ld_2d_int = {ps_ld_2d_int_code, sizeof(ps_ld_2d_int_code)}; static const DWORD ps_ld_2d_uint_arr_code[] = { #if 0 RWTexture2DArray u; uint layer; uint main(float4 position : SV_Position) : SV_Target { float3 s; u.GetDimensions(s.x, s.y, s.z); s.z = layer; return u[s * float3(position.x / 640.0f, position.y / 480.0f, 1.0f)]; } #endif 0x43425844, 0xa7630358, 0xd7e7228f, 0xa9f1be03, 0x838554f1, 0x00000001, 0x000001bc, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000e01, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000120, 0x00000050, 0x00000048, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0400409c, 0x0011e000, 0x00000001, 0x00004444, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000000, 0x02000068, 0x00000001, 0x8900003d, 0x80000202, 0x00111103, 0x00100032, 0x00000000, 0x00004001, 0x00000000, 0x0011ee46, 0x00000001, 0x07000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00101046, 0x00000000, 0x06000056, 0x001000c2, 0x00000000, 0x00208006, 0x00000000, 0x00000000, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x3f800000, 0x3f800000, 0x0500001c, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x890000a3, 0x80000202, 0x00111103, 0x00100012, 0x00000000, 0x00100e46, 0x00000000, 0x0011ee46, 0x00000001, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0100003e, }; static const struct shader ps_ld_2d_uint_arr = {ps_ld_2d_uint_arr_code, sizeof(ps_ld_2d_uint_arr_code)}; static const float float_data[] = { 0.50f, 0.25f, 1.00f, 0.00f, -1.00f, -2.00f, -3.00f, -4.00f, -0.50f, -0.25f, -1.00f, -0.00f, 1.00f, 2.00f, 3.00f, 4.00f, }; static const unsigned int uint_data[] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, }; static const unsigned int uint_data2[] = { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc000, 0xc000, 0xffff, 0xffff, 0xc000, 0xc000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, }; static const unsigned int uint_data3[] = { 0xaa, 0xaa, 0xcc, 0xcc, 0xaa, 0xaa, 0xdd, 0xdd, 0xbb, 0xbb, 0xee, 0xee, 0xbb, 0xbb, 0xff, 0xff, }; static const int int_data[] = { -1, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, -777, -666, 0x90, -555, 0xb0, 0xc0, 0xd0, 0xe0, -101, }; static const struct texture float_2d = {4, 4, 1, 1, DXGI_FORMAT_R32_FLOAT, {{float_data, 4 * sizeof(*float_data), 0}}}; static const struct texture uint_2d = {4, 4, 1, 1, DXGI_FORMAT_R32_UINT, {{uint_data, 4 * sizeof(*uint_data), 0}}}; static const struct texture uint2d_arr = {4, 4, 1, 3, DXGI_FORMAT_R32_UINT, {{uint_data, 4 * sizeof(*uint_data), 0}, {uint_data2, 4 * sizeof(*uint_data2), 0}, {uint_data3, 4 * sizeof(*uint_data3), 0}}}; static const struct texture int_2d = {4, 4, 1, 1, DXGI_FORMAT_R32_SINT, {{int_data, 4 * sizeof(*int_data), 0}}}; static const struct test { const struct shader *ps; const struct texture *texture; struct uav_desc uav_desc; struct uvec4 constant; const DWORD *expected_colors; } tests[] = { #define TEX_2D D3D11_UAV_DIMENSION_TEXTURE2D #define TEX_2D_ARRAY D3D11_UAV_DIMENSION_TEXTURE2DARRAY #define R32_FLOAT DXGI_FORMAT_R32_FLOAT #define R32_UINT DXGI_FORMAT_R32_UINT #define R32_SINT DXGI_FORMAT_R32_SINT {&ps_ld_2d_float, &float_2d, {R32_FLOAT, TEX_2D, 0}, {0}, (const DWORD *)float_data}, {&ps_ld_2d_uint, &uint_2d, {R32_UINT, TEX_2D, 0}, {0}, (const DWORD *)uint_data}, {&ps_ld_2d_int, &int_2d, {R32_SINT, TEX_2D, 0}, {0}, (const DWORD *)int_data}, {&ps_ld_2d_uint_arr, &uint2d_arr, {R32_UINT, TEX_2D_ARRAY, 0, 0, ~0u}, {0}, (const DWORD *)uint_data}, {&ps_ld_2d_uint_arr, &uint2d_arr, {R32_UINT, TEX_2D_ARRAY, 0, 0, ~0u}, {1}, (const DWORD *)uint_data2}, {&ps_ld_2d_uint_arr, &uint2d_arr, {R32_UINT, TEX_2D_ARRAY, 0, 0, ~0u}, {2}, (const DWORD *)uint_data3}, {&ps_ld_2d_uint_arr, &uint2d_arr, {R32_UINT, TEX_2D_ARRAY, 0, 1, ~0u}, {0}, (const DWORD *)uint_data2}, {&ps_ld_2d_uint_arr, &uint2d_arr, {R32_UINT, TEX_2D_ARRAY, 0, 1, ~0u}, {1}, (const DWORD *)uint_data3}, {&ps_ld_2d_uint_arr, &uint2d_arr, {R32_UINT, TEX_2D_ARRAY, 0, 2, ~0u}, {0}, (const DWORD *)uint_data3}, #undef TEX_2D #undef TEX_2D_ARRAY #undef R32_FLOAT #undef R32_UINT #undef R32_SINT }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 640; texture_desc.Height = 480; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32_TYPELESS; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rt_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; U(rtv_desc).Texture2D.MipSlice = 0; rtv_desc.Format = DXGI_FORMAT_R32_FLOAT; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rt_texture, &rtv_desc, &rtv_float); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); rtv_desc.Format = DXGI_FORMAT_R32_UINT; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rt_texture, &rtv_desc, &rtv_uint); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); rtv_desc.Format = DXGI_FORMAT_R32_SINT; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rt_texture, &rtv_desc, &rtv_sint); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); texture_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(struct uvec4), NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ps = NULL; uav = NULL; texture = NULL; current_ps = NULL; current_texture = NULL; for (i = 0; i < ARRAY_SIZE(tests); ++i) { const struct test *test = &tests[i]; ID3D11RenderTargetView *current_rtv; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &test->constant, 0, 0); if (current_ps != test->ps) { if (ps) ID3D11PixelShader_Release(ps); current_ps = test->ps; hr = ID3D11Device_CreatePixelShader(device, current_ps->code, current_ps->size, NULL, &ps); ok(SUCCEEDED(hr), "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); } if (current_texture != test->texture) { if (texture) ID3D11Texture2D_Release(texture); current_texture = test->texture; texture_desc.Width = current_texture->width; texture_desc.Height = current_texture->height; texture_desc.MipLevels = current_texture->miplevel_count; texture_desc.ArraySize = current_texture->array_size; texture_desc.Format = current_texture->format; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, current_texture->data, &texture); ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr); } if (uav) ID3D11UnorderedAccessView_Release(uav); get_uav_desc(&uav_desc, &test->uav_desc); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)texture, &uav_desc, &uav); ok(SUCCEEDED(hr), "Test %u: Failed to create unordered access view, hr %#x.\n", i, hr); switch (uav_desc.Format) { case DXGI_FORMAT_R32_FLOAT: current_rtv = rtv_float; break; case DXGI_FORMAT_R32_UINT: current_rtv = rtv_uint; break; case DXGI_FORMAT_R32_SINT: current_rtv = rtv_sint; break; default: trace("Unhandled format %#x.\n", uav_desc.Format); current_rtv = NULL; break; } ID3D11DeviceContext_ClearRenderTargetView(context, current_rtv, white); ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, 1, ¤t_rtv, NULL, 1, 1, &uav, NULL); draw_quad(&test_context); get_texture_readback(rt_texture, 0, &rb); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { DWORD expected = test->expected_colors[y * 4 + x]; DWORD color = get_readback_color(&rb, 80 + x * 160, 60 + y * 120, 0); ok(compare_color(color, expected, 0), "Test %u: Got 0x%08x, expected 0x%08x at (%u, %u).\n", i, color, expected, x, y); } } release_resource_readback(&rb); } ID3D11PixelShader_Release(ps); ID3D11Texture2D_Release(texture); ID3D11UnorderedAccessView_Release(uav); ID3D11Buffer_Release(cb); ID3D11RenderTargetView_Release(rtv_float); ID3D11RenderTargetView_Release(rtv_sint); ID3D11RenderTargetView_Release(rtv_uint); ID3D11Texture2D_Release(rt_texture); release_test_context(&test_context); } static void test_cs_uav_store(void) { static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; static const float zero[4] = {0.0f}; D3D11_TEXTURE2D_DESC texture_desc; ID3D11UnorderedAccessView *uav; struct device_desc device_desc; ID3D11DeviceContext *context; struct vec4 input = {1.0f}; ID3D11Texture2D *texture; ID3D11ComputeShader *cs; ID3D11Device *device; ID3D11Buffer *cb; ULONG refcount; HRESULT hr; RECT rect; static const DWORD cs_1_thread_code[] = { #if 0 RWTexture2D u; float value; [numthreads(1, 1, 1)] void main() { uint x, y, width, height; u.GetDimensions(width, height); for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x) u[uint2(x, y)] = value; } } #endif 0x43425844, 0x6503503a, 0x4cd524e6, 0x2473915d, 0x93cf1201, 0x00000001, 0x000001c8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000174, 0x00050050, 0x0000005d, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0400189c, 0x0011e000, 0x00000000, 0x00005555, 0x02000068, 0x00000003, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x8900103d, 0x800000c2, 0x00155543, 0x00100032, 0x00000000, 0x00004001, 0x00000000, 0x0011ee46, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100082, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a, 0x00000000, 0x03040003, 0x0010003a, 0x00000000, 0x05000036, 0x001000e2, 0x00000001, 0x00100aa6, 0x00000000, 0x05000036, 0x00100082, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100012, 0x00000002, 0x0010003a, 0x00000000, 0x0010000a, 0x00000000, 0x03040003, 0x0010000a, 0x00000002, 0x05000036, 0x00100012, 0x00000001, 0x0010003a, 0x00000000, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46, 0x00000001, 0x00208006, 0x00000000, 0x00000000, 0x0700001e, 0x00100082, 0x00000000, 0x0010003a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x0700001e, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x0100003e, }; static const DWORD cs_1_group_code[] = { #if 0 RWTexture2D u; float value; [numthreads(16, 16, 1)] void main(uint3 threadID : SV_GroupThreadID) { uint2 count, size ; u.GetDimensions(size.x, size.y); count = size / (uint2)16; for (uint y = 0; y < count.y; ++y) for (uint x = 0; x < count.x; ++x) u[count * threadID.xy + uint2(x, y)] = value; } #endif 0x43425844, 0x9fb86044, 0x352c196d, 0x92e14094, 0x46bb95a7, 0x00000001, 0x00000218, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000001c4, 0x00050050, 0x00000071, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0400189c, 0x0011e000, 0x00000000, 0x00005555, 0x0200005f, 0x00022032, 0x02000068, 0x00000004, 0x0400009b, 0x00000010, 0x00000010, 0x00000001, 0x8900103d, 0x800000c2, 0x00155543, 0x00100032, 0x00000000, 0x00004001, 0x00000000, 0x0011ee46, 0x00000000, 0x0a000055, 0x001000f2, 0x00000000, 0x00100546, 0x00000000, 0x00004002, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x05000036, 0x00100012, 0x00000001, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100022, 0x00000001, 0x0010000a, 0x00000001, 0x0010003a, 0x00000000, 0x03040003, 0x0010001a, 0x00000001, 0x05000036, 0x001000e2, 0x00000002, 0x00100006, 0x00000001, 0x05000036, 0x00100022, 0x00000001, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x03040003, 0x0010002a, 0x00000001, 0x05000036, 0x00100012, 0x00000002, 0x0010001a, 0x00000001, 0x08000023, 0x001000f2, 0x00000003, 0x00100e46, 0x00000000, 0x00022546, 0x00100e46, 0x00000002, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46, 0x00000003, 0x00208006, 0x00000000, 0x00000000, 0x0700001e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x00004001, 0x00000001, 0x01000016, 0x0700001e, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000001, 0x01000016, 0x0100003e, }; static const DWORD cs_1_store_code[] = { #if 0 RWTexture2D u; float value; [numthreads(1, 1, 1)] void main(uint3 groupID : SV_GroupID) { u[groupID.xy] = value; } #endif 0x43425844, 0xc3add41b, 0x67df51b1, 0x2b887930, 0xcb1ee991, 0x00000001, 0x000000b8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000064, 0x00050050, 0x00000019, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0400189c, 0x0011e000, 0x00000000, 0x00005555, 0x0200005f, 0x00021032, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x070000a4, 0x0011e0f2, 0x00000000, 0x00021546, 0x00208006, 0x00000000, 0x00000000, 0x0100003e, }; static const DWORD cs_dispatch_id_code[] = { #if 0 RWTexture2D u; float value; [numthreads(4, 4, 1)] void main(uint3 id : SV_DispatchThreadID) { u[id.xy] = value; } #endif 0x43425844, 0x60166991, 0x4b595266, 0x7fb67d79, 0x485c4f0d, 0x00000001, 0x000000b8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000064, 0x00050050, 0x00000019, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0400189c, 0x0011e000, 0x00000000, 0x00005555, 0x0200005f, 0x00020032, 0x0400009b, 0x00000004, 0x00000004, 0x00000001, 0x070000a4, 0x0011e0f2, 0x00000000, 0x00020546, 0x00208006, 0x00000000, 0x00000000, 0x0100003e, }; static const DWORD cs_group_index_code[] = { #if 0 RWTexture2D u; float value; [numthreads(32, 1, 1)] void main(uint index : SV_GroupIndex) { uint2 size; u.GetDimensions(size.x, size.y); uint count = size.x * size.y / 32; index *= count; for (uint i = 0; i < count; ++i, ++index) u[uint2(index % size.x, index / size.x)] = value; } #endif 0x43425844, 0xb685a70f, 0x94c2f263, 0x4f1d8eaa, 0xeab65731, 0x00000001, 0x000001f8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000001a4, 0x00050050, 0x00000069, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0400189c, 0x0011e000, 0x00000000, 0x00005555, 0x0200005f, 0x00024000, 0x02000068, 0x00000004, 0x0400009b, 0x00000020, 0x00000001, 0x00000001, 0x8900103d, 0x800000c2, 0x00155543, 0x00100032, 0x00000000, 0x00004001, 0x00000000, 0x0011ee46, 0x00000000, 0x08000026, 0x0000d000, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0010001a, 0x00000000, 0x07000055, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000005, 0x07000026, 0x0000d000, 0x00100042, 0x00000000, 0x0002400a, 0x0010001a, 0x00000000, 0x05000036, 0x00100012, 0x00000001, 0x0010002a, 0x00000000, 0x05000036, 0x00100022, 0x00000001, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100082, 0x00000000, 0x0010001a, 0x00000001, 0x0010001a, 0x00000000, 0x03040003, 0x0010003a, 0x00000000, 0x0900004e, 0x00100012, 0x00000002, 0x00100012, 0x00000003, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x05000036, 0x001000e2, 0x00000003, 0x00100006, 0x00000002, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46, 0x00000003, 0x00208006, 0x00000000, 0x00000000, 0x0a00001e, 0x00100032, 0x00000001, 0x00100046, 0x00000001, 0x00004002, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x01000016, 0x0100003e, }; device_desc.feature_level = &feature_level; device_desc.flags = 0; if (!(device = create_device(&device_desc))) { skip("Failed to create device for feature level %#x.\n", feature_level); return; } cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(input), &input.x); texture_desc.Width = 64; texture_desc.Height = 64; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); uav_desc.Format = texture_desc.Format; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; U(uav_desc).Texture2D.MipSlice = 0; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)texture, &uav_desc, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); ID3D11Device_GetImmediateContext(device, &context); ID3D11DeviceContext_CSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); ID3D11DeviceContext_ClearUnorderedAccessViewFloat(context, uav, zero); check_texture_float(texture, 0.0f, 2); hr = ID3D11Device_CreateComputeShader(device, cs_1_thread_code, sizeof(cs_1_thread_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); check_texture_float(texture, 1.0f, 2); input.x = 0.5f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); check_texture_float(texture, 0.5f, 2); ID3D11ComputeShader_Release(cs); input.x = 2.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_CSSetShader(context, NULL, NULL, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); check_texture_float(texture, 0.5f, 2); hr = ID3D11Device_CreateComputeShader(device, cs_1_group_code, sizeof(cs_1_group_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); check_texture_float(texture, 2.0f, 2); input.x = 4.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); check_texture_float(texture, 4.0f, 2); ID3D11ComputeShader_Release(cs); hr = ID3D11Device_CreateComputeShader(device, cs_1_store_code, sizeof(cs_1_store_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); input.x = 1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_Dispatch(context, texture_desc.Width, texture_desc.Height, 1); check_texture_float(texture, 1.0f, 2); input.x = 0.5f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_Dispatch(context, 16, 32, 1); SetRect(&rect, 0, 0, 16, 32); check_texture_sub_resource_float(texture, 0, &rect, 0.5f, 2); SetRect(&rect, 0, 32, texture_desc.Width, texture_desc.Height); check_texture_sub_resource_float(texture, 0, &rect, 1.0f, 2); SetRect(&rect, 16, 0, texture_desc.Width, texture_desc.Height); check_texture_sub_resource_float(texture, 0, &rect, 1.0f, 2); ID3D11ComputeShader_Release(cs); hr = ID3D11Device_CreateComputeShader(device, cs_dispatch_id_code, sizeof(cs_dispatch_id_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); input.x = 0.6f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_Dispatch(context, 15, 15, 1); SetRect(&rect, 0, 0, 60, 60); check_texture_sub_resource_float(texture, 0, &rect, 0.6f, 2); SetRect(&rect, 0, 60, texture_desc.Width, texture_desc.Height); check_texture_sub_resource_float(texture, 0, &rect, 1.0f, 2); SetRect(&rect, 60, 0, texture_desc.Width, texture_desc.Height); check_texture_sub_resource_float(texture, 0, &rect, 1.0f, 2); input.x = 0.7f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_Dispatch(context, 16, 16, 1); check_texture_float(texture, 0.7f, 2); ID3D11ComputeShader_Release(cs); hr = ID3D11Device_CreateComputeShader(device, cs_group_index_code, sizeof(cs_group_index_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); input.x = 0.3f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); check_texture_float(texture, 0.3f, 2); input.x = 0.1f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_Dispatch(context, 2, 2, 2); check_texture_float(texture, 0.1f, 2); ID3D11ComputeShader_Release(cs); ID3D11Buffer_Release(cb); ID3D11Texture2D_Release(texture); ID3D11UnorderedAccessView_Release(uav); ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_uav_store_immediate_constant(void) { D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11UnorderedAccessView *uav; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Texture2D *texture; ID3D11ComputeShader *cs; unsigned int uint_data; ID3D11Device *device; ID3D11Buffer *buffer; float float_data; int int_data; HRESULT hr; static const DWORD cs_store_int_code[] = { #if 0 RWBuffer u; [numthreads(1, 1, 1)] void main() { u[0] = 42; } #endif 0x43425844, 0x7246d785, 0x3f4ccbd6, 0x6a7cdbc0, 0xe2b58c72, 0x00000001, 0x000000b8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000064, 0x00050050, 0x00000019, 0x0100086a, 0x0400089c, 0x0011e000, 0x00000000, 0x00003333, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x0d0000a4, 0x0011e0f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004002, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, 0x0100003e, }; static const DWORD cs_store_float_code[] = { #if 0 RWBuffer u; [numthreads(1, 1, 1)] void main() { u[0] = 1.0; } #endif 0x43425844, 0x525eea68, 0xc4cd5716, 0xc588f9c4, 0x0da27c5a, 0x00000001, 0x000000b8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000064, 0x00050050, 0x00000019, 0x0100086a, 0x0400089c, 0x0011e000, 0x00000000, 0x00005555, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x0d0000a4, 0x0011e0f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x0100003e, }; static const DWORD cs_store_unorm_code[] = { #if 0 RWTexture2D u; [numthreads(1, 1, 1)] void main() { u[uint2(0, 0)] = 0.5f; } #endif 0x43425844, 0x3623f1de, 0xe847109e, 0x8e3da13f, 0xb6787b06, 0x00000001, 0x000000b8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000064, 0x00050050, 0x00000019, 0x0100086a, 0x0400189c, 0x0011e000, 0x00000000, 0x00001111, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x0d0000a4, 0x0011e0f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x0100003e, }; static const DWORD cs_store_snorm_code[] = { #if 0 RWTexture2D u; [numthreads(1, 1, 1)] void main() { u[uint2(0, 0)] = -0.5f; } #endif 0x43425844, 0xce5397fc, 0x7464bc06, 0xc79aa56c, 0x881bd7ef, 0x00000001, 0x000000b8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000064, 0x00050050, 0x00000019, 0x0100086a, 0x0400189c, 0x0011e000, 0x00000000, 0x00002222, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x0d0000a4, 0x0011e0f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004002, 0xbf000000, 0xbf000000, 0xbf000000, 0xbf000000, 0x0100003e, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const unsigned int zero[4] = {0}; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; buffer = create_buffer(device, D3D11_BIND_UNORDERED_ACCESS, 1024, NULL); uav_desc.Format = DXGI_FORMAT_R32_SINT; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 1; U(uav_desc).Buffer.Flags = 0; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateComputeShader(device, cs_store_int_code, sizeof(cs_store_int_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, zero); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); get_buffer_readback(buffer, &rb); int_data = get_readback_color(&rb, 0, 0, 0); ok(int_data == 42, "Got unexpected value %u.\n", int_data); release_resource_readback(&rb); ID3D11ComputeShader_Release(cs); ID3D11UnorderedAccessView_Release(uav); uav_desc.Format = DXGI_FORMAT_R32_FLOAT; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateComputeShader(device, cs_store_float_code, sizeof(cs_store_float_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, zero); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); get_buffer_readback(buffer, &rb); float_data = get_readback_float(&rb, 0, 0); ok(float_data == 1.0f, "Got unexpected value %.8e.\n", float_data); release_resource_readback(&rb); texture_desc.Width = 64; texture_desc.Height = 64; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); ID3D11UnorderedAccessView_Release(uav); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)texture, NULL, &uav); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); ID3D11ComputeShader_Release(cs); hr = ID3D11Device_CreateComputeShader(device, cs_store_unorm_code, sizeof(cs_store_unorm_code), NULL, &cs); ok(hr == S_OK, "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, zero); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); get_texture_readback(texture, 0, &rb); uint_data = get_readback_color(&rb, 0, 0, 0); ok(compare_color(uint_data, 0x80808080, 1), "Got unexpected color 0x%08x.\n", uint_data); release_resource_readback(&rb); ID3D11Texture2D_Release(texture); texture_desc.Format = DXGI_FORMAT_R8G8B8A8_SNORM; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); ID3D11UnorderedAccessView_Release(uav); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)texture, NULL, &uav); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); ID3D11ComputeShader_Release(cs); hr = ID3D11Device_CreateComputeShader(device, cs_store_snorm_code, sizeof(cs_store_snorm_code), NULL, &cs); ok(hr == S_OK, "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, zero); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); get_texture_readback(texture, 0, &rb); uint_data = get_readback_color(&rb, 0, 0, 0); ok(compare_color(uint_data, 0xc0c0c0c0, 1), "Got unexpected color 0x%08x.\n", uint_data); release_resource_readback(&rb); ID3D11Buffer_Release(buffer); ID3D11Texture2D_Release(texture); ID3D11ComputeShader_Release(cs); ID3D11UnorderedAccessView_Release(uav); release_test_context(&test_context); } static void test_ps_cs_uav_binding(void) { static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; ID3D11UnorderedAccessView *cs_uav, *ps_uav; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; ID3D11Texture2D *cs_texture, *ps_texture; struct d3d11_test_context test_context; static const float zero[4] = {0.0f}; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11Buffer *cs_cb, *ps_cb; struct vec4 input = {1.0f}; ID3D11ComputeShader *cs; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DWORD cs_code[] = { #if 0 RWTexture2D u; float value; [numthreads(1, 1, 1)] void main() { uint x, y, width, height; u.GetDimensions(width, height); for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x) u[uint2(x, y)] = value; } } #endif 0x43425844, 0x6503503a, 0x4cd524e6, 0x2473915d, 0x93cf1201, 0x00000001, 0x000001c8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000174, 0x00050050, 0x0000005d, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0400189c, 0x0011e000, 0x00000000, 0x00005555, 0x02000068, 0x00000003, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x8900103d, 0x800000c2, 0x00155543, 0x00100032, 0x00000000, 0x00004001, 0x00000000, 0x0011ee46, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100082, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a, 0x00000000, 0x03040003, 0x0010003a, 0x00000000, 0x05000036, 0x001000e2, 0x00000001, 0x00100aa6, 0x00000000, 0x05000036, 0x00100082, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100012, 0x00000002, 0x0010003a, 0x00000000, 0x0010000a, 0x00000000, 0x03040003, 0x0010000a, 0x00000002, 0x05000036, 0x00100012, 0x00000001, 0x0010003a, 0x00000000, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46, 0x00000001, 0x00208006, 0x00000000, 0x00000000, 0x0700001e, 0x00100082, 0x00000000, 0x0010003a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x0700001e, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 RWTexture2D u : register(u1); float value; void main() { uint x, y, width, height; u.GetDimensions(width, height); for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x) u[uint2(x, y)] = value; } } #endif 0x43425844, 0x2e14423b, 0x62c015c8, 0x5ea5ab9f, 0x514f1e22, 0x00000001, 0x000001b8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000164, 0x00000050, 0x00000059, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0400189c, 0x0011e000, 0x00000001, 0x00005555, 0x02000068, 0x00000003, 0x8900103d, 0x800000c2, 0x00155543, 0x00100032, 0x00000000, 0x00004001, 0x00000000, 0x0011ee46, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100082, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a, 0x00000000, 0x03040003, 0x0010003a, 0x00000000, 0x05000036, 0x001000e2, 0x00000001, 0x00100aa6, 0x00000000, 0x05000036, 0x00100082, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100012, 0x00000002, 0x0010003a, 0x00000000, 0x0010000a, 0x00000000, 0x03040003, 0x0010000a, 0x00000002, 0x05000036, 0x00100012, 0x00000001, 0x0010003a, 0x00000000, 0x080000a4, 0x0011e0f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208006, 0x00000000, 0x00000000, 0x0700001e, 0x00100082, 0x00000000, 0x0010003a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x0700001e, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x0100003e, }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; ps_cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(input), &input.x); cs_cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(input), &input.x); texture_desc.Width = 64; texture_desc.Height = 64; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &cs_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &ps_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); uav_desc.Format = texture_desc.Format; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; U(uav_desc).Texture2D.MipSlice = 0; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)cs_texture, &uav_desc, &cs_uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)ps_texture, &uav_desc, &ps_uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); ID3D11Device_GetImmediateContext(device, &context); ID3D11DeviceContext_CSSetConstantBuffers(context, 0, 1, &cs_cb); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &cs_uav, NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &ps_cb); ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, 0, NULL, NULL, 1, 1, &ps_uav, NULL); ID3D11DeviceContext_ClearUnorderedAccessViewFloat(context, cs_uav, zero); check_texture_float(cs_texture, 0.0f, 2); ID3D11DeviceContext_ClearUnorderedAccessViewFloat(context, ps_uav, zero); check_texture_float(ps_texture, 0.0f, 2); hr = ID3D11Device_CreateComputeShader(device, cs_code, sizeof(cs_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); check_texture_float(cs_texture, 1.0f, 2); check_texture_float(ps_texture, 0.0f, 2); draw_quad(&test_context); check_texture_float(cs_texture, 1.0f, 2); check_texture_float(ps_texture, 1.0f, 2); input.x = 0.5f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cs_cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); check_texture_float(cs_texture, 0.5f, 2); check_texture_float(ps_texture, 1.0f, 2); input.x = 2.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)ps_cb, 0, NULL, &input, 0, 0); draw_quad(&test_context); check_texture_float(cs_texture, 0.5f, 2); check_texture_float(ps_texture, 2.0f, 2); input.x = 8.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cs_cb, 0, NULL, &input, 0, 0); input.x = 4.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)ps_cb, 0, NULL, &input, 0, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); check_texture_float(cs_texture, 8.0f, 2); check_texture_float(ps_texture, 2.0f, 2); draw_quad(&test_context); check_texture_float(cs_texture, 8.0f, 2); check_texture_float(ps_texture, 4.0f, 2); ID3D11ComputeShader_Release(cs); ID3D11PixelShader_Release(ps); ID3D11Buffer_Release(cs_cb); ID3D11Buffer_Release(ps_cb); ID3D11Texture2D_Release(cs_texture); ID3D11Texture2D_Release(ps_texture); ID3D11UnorderedAccessView_Release(cs_uav); ID3D11UnorderedAccessView_Release(ps_uav); ID3D11DeviceContext_Release(context); release_test_context(&test_context); } static void test_atomic_instructions(void) { ID3D11UnorderedAccessView *in_uav, *out_uav; ID3D11Buffer *cb, *in_buffer, *out_buffer; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; struct d3d11_test_context test_context; struct resource_readback rb, out_rb; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; ID3D11ComputeShader *cs; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, j; HRESULT hr; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const unsigned int zero[4] = {0, 0, 0, 0}; static const DWORD ps_atomics_code[] = { #if 0 RWByteAddressBuffer u; uint4 v; int4 i; void main() { u.InterlockedAnd(0 * 4, v.x); u.InterlockedCompareStore(1 * 4, v.y, v.x); u.InterlockedAdd(2 * 4, v.x); u.InterlockedOr(3 * 4, v.x); u.InterlockedMax(4 * 4, i.x); u.InterlockedMin(5 * 4, i.x); u.InterlockedMax(6 * 4, v.x); u.InterlockedMin(7 * 4, v.x); u.InterlockedXor(8 * 4, v.x); } #endif 0x43425844, 0x24c6a30c, 0x2ce4437d, 0xdee8a0df, 0xd18cb4bc, 0x00000001, 0x000001ac, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000158, 0x00000050, 0x00000056, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300009d, 0x0011e000, 0x00000000, 0x080000a9, 0x0011e000, 0x00000000, 0x00004001, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0b0000ac, 0x0011e000, 0x00000000, 0x00004001, 0x00000004, 0x0020801a, 0x00000000, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x080000ad, 0x0011e000, 0x00000000, 0x00004001, 0x00000008, 0x0020800a, 0x00000000, 0x00000000, 0x080000aa, 0x0011e000, 0x00000000, 0x00004001, 0x0000000c, 0x0020800a, 0x00000000, 0x00000000, 0x080000ae, 0x0011e000, 0x00000000, 0x00004001, 0x00000010, 0x0020800a, 0x00000000, 0x00000001, 0x080000af, 0x0011e000, 0x00000000, 0x00004001, 0x00000014, 0x0020800a, 0x00000000, 0x00000001, 0x080000b0, 0x0011e000, 0x00000000, 0x00004001, 0x00000018, 0x0020800a, 0x00000000, 0x00000000, 0x080000b1, 0x0011e000, 0x00000000, 0x00004001, 0x0000001c, 0x0020800a, 0x00000000, 0x00000000, 0x080000ab, 0x0011e000, 0x00000000, 0x00004001, 0x00000020, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; static const DWORD cs_atomics_code[] = { #if 0 RWByteAddressBuffer u; RWByteAddressBuffer u2; uint4 v; int4 i; [numthreads(1, 1, 1)] void main() { uint r; u.InterlockedAnd(0 * 4, v.x, r); u2.Store(0 * 4, r); u.InterlockedCompareExchange(1 * 4, v.y, v.x, r); u2.Store(1 * 4, r); u.InterlockedAdd(2 * 4, v.x, r); u2.Store(2 * 4, r); u.InterlockedOr(3 * 4, v.x, r); u2.Store(3 * 4, r); u.InterlockedMax(4 * 4, i.x, r); u2.Store(4 * 4, r); u.InterlockedMin(5 * 4, i.x, r); u2.Store(5 * 4, r); u.InterlockedMax(6 * 4, v.x, r); u2.Store(6 * 4, r); u.InterlockedMin(7 * 4, v.x, r); u2.Store(7 * 4, r); u.InterlockedXor(8 * 4, v.x, r); u2.Store(8 * 4, r); } #endif 0x43425844, 0x859a96e3, 0x1a35e463, 0x1e89ce58, 0x5cfe430a, 0x00000001, 0x0000026c, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000218, 0x00050050, 0x00000086, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300009d, 0x0011e000, 0x00000000, 0x0300009d, 0x0011e000, 0x00000001, 0x02000068, 0x00000001, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x0a0000b5, 0x00100012, 0x00000000, 0x0011e000, 0x00000000, 0x00004001, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0d0000b9, 0x00100022, 0x00000000, 0x0011e000, 0x00000000, 0x00004001, 0x00000004, 0x0020801a, 0x00000000, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0a0000b4, 0x00100042, 0x00000000, 0x0011e000, 0x00000000, 0x00004001, 0x00000008, 0x0020800a, 0x00000000, 0x00000000, 0x0a0000b6, 0x00100082, 0x00000000, 0x0011e000, 0x00000000, 0x00004001, 0x0000000c, 0x0020800a, 0x00000000, 0x00000000, 0x070000a6, 0x0011e0f2, 0x00000001, 0x00004001, 0x00000000, 0x00100e46, 0x00000000, 0x0a0000ba, 0x00100012, 0x00000000, 0x0011e000, 0x00000000, 0x00004001, 0x00000010, 0x0020800a, 0x00000000, 0x00000001, 0x0a0000bb, 0x00100022, 0x00000000, 0x0011e000, 0x00000000, 0x00004001, 0x00000014, 0x0020800a, 0x00000000, 0x00000001, 0x0a0000bc, 0x00100042, 0x00000000, 0x0011e000, 0x00000000, 0x00004001, 0x00000018, 0x0020800a, 0x00000000, 0x00000000, 0x0a0000bd, 0x00100082, 0x00000000, 0x0011e000, 0x00000000, 0x00004001, 0x0000001c, 0x0020800a, 0x00000000, 0x00000000, 0x070000a6, 0x0011e0f2, 0x00000001, 0x00004001, 0x00000010, 0x00100e46, 0x00000000, 0x0a0000b7, 0x00100012, 0x00000000, 0x0011e000, 0x00000000, 0x00004001, 0x00000020, 0x0020800a, 0x00000000, 0x00000000, 0x070000a6, 0x0011e012, 0x00000001, 0x00004001, 0x00000020, 0x0010000a, 0x00000000, 0x0100003e, }; static const char * const instructions[] = { "atomic_and", "atomic_cmp_store", "atomic_iadd", "atomic_or", "atomic_imax", "atomic_imin", "atomic_umax", "atomic_umin", "atomic_xor", }; static const char * const imm_instructions[] = { "imm_atomic_and", "imm_atomic_cmp_exch", "imm_atomic_iadd", "imm_atomic_or", "imm_atomic_imax", "imm_atomic_imin", "imm_atomic_umax", "imm_atomic_umin", "imm_atomic_xor", }; static const struct test { struct uvec4 v; struct ivec4 i; unsigned int input[ARRAY_SIZE(instructions)]; unsigned int expected_result[ARRAY_SIZE(instructions)]; } tests[] = { {{1, 0}, {-1}, {0xffff, 0, 1, 0, 0, 0, 0, 0, 0xff}, { 1, 1, 2, 1, 0, ~0u, 1, 0, 0xfe}}, {{~0u, ~0u}, { 0}, {0xffff, 0xf, 1, 0, 0, 0, 0, 9, ~0u}, {0xffff, 0xf, 0, ~0u, 0, 0, ~0u, 9, 0}}, }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, 2 * sizeof(struct uvec4), NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_CSSetConstantBuffers(context, 0, 1, &cb); buffer_desc.ByteWidth = sizeof(tests->input); buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &in_buffer); ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &out_buffer); ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = buffer_desc.ByteWidth / sizeof(*tests->input); U(uav_desc).Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)in_buffer, &uav_desc, &in_uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)out_buffer, &uav_desc, &out_uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); set_viewport(context, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f); hr = ID3D11Device_CreatePixelShader(device, ps_atomics_code, sizeof(ps_atomics_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); hr = ID3D11Device_CreateComputeShader(device, cs_atomics_code, sizeof(cs_atomics_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); for (i = 0; i < ARRAY_SIZE(tests); ++i) { const struct test *test = &tests[i]; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &test->v, 0, 0); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)in_buffer, 0, NULL, test->input, 0, 0); ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, 0, NULL, NULL, 0, 1, &in_uav, NULL); draw_quad(&test_context); get_buffer_readback(in_buffer, &rb); for (j = 0; j < ARRAY_SIZE(instructions); ++j) { unsigned int value = get_readback_color(&rb, j, 0, 0); unsigned int expected = test->expected_result[j]; todo_wine_if(expected != test->input[j] && (!strcmp(instructions[j], "atomic_imax") || !strcmp(instructions[j], "atomic_imin"))) ok(value == expected, "Test %u: Got %#x (%d), expected %#x (%d) for '%s' " "with inputs (%u, %u), (%d), %#x (%d).\n", i, value, value, expected, expected, instructions[j], test->v.x, test->v.y, test->i.x, test->input[j], test->input[j]); } release_resource_readback(&rb); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)in_buffer, 0, NULL, test->input, 0, 0); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, out_uav, zero); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &in_uav, NULL); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 1, 1, &out_uav, NULL); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); get_buffer_readback(in_buffer, &rb); get_buffer_readback(out_buffer, &out_rb); for (j = 0; j < ARRAY_SIZE(instructions); ++j) { BOOL todo_instruction = !strcmp(imm_instructions[j], "imm_atomic_imax") || !strcmp(imm_instructions[j], "imm_atomic_imin"); unsigned int out_value = get_readback_color(&out_rb, j, 0, 0); unsigned int value = get_readback_color(&rb, j, 0, 0); unsigned int expected = test->expected_result[j]; todo_wine_if(expected != test->input[j] && todo_instruction) ok(value == expected, "Test %u: Got %#x (%d), expected %#x (%d) for '%s' " "with inputs (%u, %u), (%d), %#x (%d).\n", i, value, value, expected, expected, imm_instructions[j], test->v.x, test->v.y, test->i.x, test->input[j], test->input[j]); todo_wine_if(todo_instruction && out_value != test->input[j]) ok(out_value == test->input[j], "Got original value %u, expected %u for '%s'.\n", out_value, test->input[j], imm_instructions[j]); } release_resource_readback(&out_rb); release_resource_readback(&rb); } ID3D11Buffer_Release(cb); ID3D11Buffer_Release(in_buffer); ID3D11Buffer_Release(out_buffer); ID3D11ComputeShader_Release(cs); ID3D11PixelShader_Release(ps); ID3D11UnorderedAccessView_Release(in_uav); ID3D11UnorderedAccessView_Release(out_uav); release_test_context(&test_context); } static void test_sm4_ret_instruction(void) { struct d3d11_test_context test_context; ID3D11DeviceContext *context; ID3D11PixelShader *ps; struct uvec4 constant; ID3D11Device *device; ID3D11Buffer *cb; HRESULT hr; static const DWORD ps_code[] = { #if 0 uint c; float4 main() : SV_TARGET { if (c == 1) return float4(1, 0, 0, 1); if (c == 2) return float4(0, 1, 0, 1); if (c == 3) return float4(0, 0, 1, 1); return float4(1, 1, 1, 1); } #endif 0x43425844, 0x9ee6f808, 0xe74009f3, 0xbb1adaf2, 0x432e97b5, 0x00000001, 0x000001c4, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x0000014c, 0x00000040, 0x00000053, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x08000020, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000015, 0x08000020, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000002, 0x0304001f, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000015, 0x08000020, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000003, 0x0304001f, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x0100003e, 0x01000015, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x0100003e, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); memset(&constant, 0, sizeof(constant)); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constant), &constant); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xffffffff, 0); constant.x = 1; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff0000ff, 0); constant.x = 2; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); constant.x = 3; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xffff0000, 0); constant.x = 4; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xffffffff, 0); ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_primitive_restart(void) { struct d3d11_test_context test_context; ID3D11Buffer *ib32, *ib16, *vb; ID3D11DeviceContext *context; unsigned int stride, offset; ID3D11InputLayout *layout; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i; HRESULT hr; RECT rect; static const DWORD ps_code[] = { #if 0 struct vs_out { float4 position : SV_Position; float4 color : color; }; float4 main(vs_out input) : SV_TARGET { return input.color; } #endif 0x43425844, 0x119e48d1, 0x468aecb3, 0x0a405be5, 0x4e203b82, 0x00000001, 0x000000f4, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x6f6c6f63, 0xabab0072, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const DWORD vs_code[] = { #if 0 struct vs_out { float4 position : SV_Position; float4 color : color; }; void main(float4 position : POSITION, uint vertex_id : SV_VertexID, out vs_out output) { output.position = position; output.color = vertex_id < 4 ? float4(0.0, 1.0, 1.0, 1.0) : float4(1.0, 0.0, 0.0, 1.0); } #endif 0x43425844, 0x2fa57573, 0xdb71c15f, 0x2641b028, 0xa8f87ccc, 0x00000001, 0x00000198, 0x00000003, 0x0000002c, 0x00000084, 0x000000d8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000006, 0x00000001, 0x00000001, 0x00000101, 0x49534f50, 0x4e4f4954, 0x5f565300, 0x74726556, 0x44497865, 0xababab00, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x6f6c6f63, 0xabab0072, 0x52444853, 0x000000b8, 0x00010040, 0x0000002e, 0x0300005f, 0x001010f2, 0x00000000, 0x04000060, 0x00101012, 0x00000001, 0x00000006, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x02000068, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0700004f, 0x00100012, 0x00000000, 0x0010100a, 0x00000001, 0x00004001, 0x00000004, 0x0f000037, 0x001020f2, 0x00000001, 0x00100006, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"position", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const struct vec2 vertices[] = { {-1.00f, -1.0f}, {-1.00f, 1.0f}, {-0.25f, -1.0f}, {-0.25f, 1.0f}, { 0.25f, -1.0f}, { 0.25f, 1.0f}, { 1.00f, -1.0f}, { 1.00f, 1.0f}, }; static const float black[] = {0.0f, 0.0f, 0.0f, 0.0f}; static const unsigned short indices16[] = { 0, 1, 2, 3, 0xffff, 4, 5, 6, 7 }; static const unsigned int indices32[] = { 0, 1, 2, 3, 0xffffffff, 4, 5, 6, 7 }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create return pixel shader, hr %#x.\n", hr); ib16 = create_buffer(device, D3D11_BIND_INDEX_BUFFER, sizeof(indices16), indices16); ib32 = create_buffer(device, D3D11_BIND_INDEX_BUFFER, sizeof(indices32), indices32); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(vertices), vertices); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_IASetInputLayout(context, layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); stride = sizeof(*vertices); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, &stride, &offset); for (i = 0; i < 2; ++i) { if (!i) ID3D11DeviceContext_IASetIndexBuffer(context, ib32, DXGI_FORMAT_R32_UINT, 0); else ID3D11DeviceContext_IASetIndexBuffer(context, ib16, DXGI_FORMAT_R16_UINT, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, black); ID3D11DeviceContext_DrawIndexed(context, 9, 0, 0); SetRect(&rect, 0, 0, 240, 480); check_texture_sub_resource_color(test_context.backbuffer, 0, &rect, 0xffffff00, 1); SetRect(&rect, 240, 0, 400, 480); check_texture_sub_resource_color(test_context.backbuffer, 0, &rect, 0x00000000, 1); SetRect(&rect, 400, 0, 640, 480); check_texture_sub_resource_color(test_context.backbuffer, 0, &rect, 0xff0000ff, 1); } ID3D11Buffer_Release(ib16); ID3D11Buffer_Release(ib32); ID3D11Buffer_Release(vb); ID3D11InputLayout_Release(layout); ID3D11PixelShader_Release(ps); ID3D11VertexShader_Release(vs); release_test_context(&test_context); } static void test_resinfo_instruction(void) { struct shader { const DWORD *code; size_t size; }; struct d3d11_test_context test_context; D3D11_TEXTURE3D_DESC texture3d_desc; D3D11_TEXTURE2D_DESC texture_desc; const struct shader *current_ps; D3D_FEATURE_LEVEL feature_level; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; ID3D11Texture2D *rtv_texture; ID3D11RenderTargetView *rtv; ID3D11Resource *texture; struct uvec4 constant; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, type; ID3D11Buffer *cb; HRESULT hr; static const DWORD ps_2d_code[] = { #if 0 Texture2D t; uint type; uint level; float4 main() : SV_TARGET { if (!type) { float width, height, miplevels; t.GetDimensions(level, width, height, miplevels); return float4(width, height, miplevels, 0); } else { uint width, height, miplevels; t.GetDimensions(level, width, height, miplevels); return float4(width, height, miplevels, 0); } } #endif 0x43425844, 0x9c2db58d, 0x7218d757, 0x23255414, 0xaa86938e, 0x00000001, 0x00000168, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x000000f0, 0x00000040, 0x0000003c, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0400001f, 0x0020800a, 0x00000000, 0x00000000, 0x0800003d, 0x001000f2, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100346, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x00000000, 0x0100003e, 0x01000012, 0x0800103d, 0x001000f2, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x05000056, 0x00102072, 0x00000000, 0x00100346, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x00000000, 0x0100003e, 0x01000015, 0x0100003e, }; static const struct shader ps_2d = {ps_2d_code, sizeof(ps_2d_code)}; static const DWORD ps_2d_array_code[] = { #if 0 Texture2DArray t; uint type; uint level; float4 main() : SV_TARGET { if (!type) { float width, height, elements, miplevels; t.GetDimensions(level, width, height, elements, miplevels); return float4(width, height, elements, miplevels); } else { uint width, height, elements, miplevels; t.GetDimensions(level, width, height, elements, miplevels); return float4(width, height, elements, miplevels); } } #endif 0x43425844, 0x92cd8789, 0x38e359ac, 0xd65ab502, 0xa018a5ae, 0x00000001, 0x0000012c, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x000000b4, 0x00000040, 0x0000002d, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04004058, 0x00107000, 0x00000000, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0400001f, 0x0020800a, 0x00000000, 0x00000000, 0x0800003d, 0x001020f2, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x0100003e, 0x01000012, 0x0800103d, 0x001000f2, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x05000056, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x0100003e, 0x01000015, 0x0100003e, }; static const struct shader ps_2d_array = {ps_2d_array_code, sizeof(ps_2d_array_code)}; static const DWORD ps_3d_code[] = { #if 0 Texture3D t; uint type; uint level; float4 main() : SV_TARGET { if (!type) { float width, height, depth, miplevels; t.GetDimensions(level, width, height, depth, miplevels); return float4(width, height, depth, miplevels); } else { uint width, height, depth, miplevels; t.GetDimensions(level, width, height, depth, miplevels); return float4(width, height, depth, miplevels); } } #endif 0x43425844, 0xac1f73b9, 0x2bce1322, 0x82c599e6, 0xbff0d681, 0x00000001, 0x0000012c, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x000000b4, 0x00000040, 0x0000002d, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04002858, 0x00107000, 0x00000000, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0400001f, 0x0020800a, 0x00000000, 0x00000000, 0x0800003d, 0x001020f2, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x0100003e, 0x01000012, 0x0800103d, 0x001000f2, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x05000056, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x0100003e, 0x01000015, 0x0100003e, }; static const struct shader ps_3d = {ps_3d_code, sizeof(ps_3d_code)}; static const DWORD ps_cube_code[] = { #if 0 TextureCube t; uint type; uint level; float4 main() : SV_TARGET { if (!type) { float width, height, miplevels; t.GetDimensions(level, width, height, miplevels); return float4(width, height, miplevels, 0); } else { uint width, height, miplevels; t.GetDimensions(level, width, height, miplevels); return float4(width, height, miplevels, 0); } } #endif 0x43425844, 0x795eb161, 0xb8291400, 0xcc531086, 0x2a8143ce, 0x00000001, 0x00000168, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x000000f0, 0x00000040, 0x0000003c, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04003058, 0x00107000, 0x00000000, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0400001f, 0x0020800a, 0x00000000, 0x00000000, 0x0800003d, 0x001000f2, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100346, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x00000000, 0x0100003e, 0x01000012, 0x0800103d, 0x001000f2, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x05000056, 0x00102072, 0x00000000, 0x00100346, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x00000000, 0x0100003e, 0x01000015, 0x0100003e, }; static const struct shader ps_cube = {ps_cube_code, sizeof(ps_cube_code)}; static const DWORD ps_cube_array_code[] = { #if 0 TextureCubeArray t; uint type; uint level; float4 main() : SV_TARGET { if (!type) { float width, height, elements, miplevels; t.GetDimensions(level, width, height, elements, miplevels); return float4(width, height, miplevels, 0); } else { uint width, height, elements, miplevels; t.GetDimensions(level, width, height, elements, miplevels); return float4(width, height, miplevels, 0); } } #endif 0x43425844, 0x894d136f, 0xa1f5c746, 0xd771ac09, 0x6914e044, 0x00000001, 0x0000016c, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x000000f4, 0x00000041, 0x0000003d, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04005058, 0x00107000, 0x00000000, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0400001f, 0x0020800a, 0x00000000, 0x00000000, 0x0800003d, 0x00100072, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x00107b46, 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x00000000, 0x0100003e, 0x01000012, 0x0800103d, 0x00100072, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x00107b46, 0x00000000, 0x05000056, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x00000000, 0x0100003e, 0x01000015, 0x0100003e, }; static const struct shader ps_cube_array = {ps_cube_array_code, sizeof(ps_cube_array_code)}; static const struct ps_test { const struct shader *ps; struct { unsigned int width; unsigned int height; unsigned int depth; unsigned int miplevel_count; unsigned int array_size; unsigned int cube_count; } texture_desc; unsigned int miplevel; struct vec4 expected_result; } ps_tests[] = { {&ps_2d, {64, 64, 1, 1, 1, 0}, 0, {64.0f, 64.0f, 1.0f, 0.0f}}, {&ps_2d, {32, 16, 1, 3, 1, 0}, 0, {32.0f, 16.0f, 3.0f, 0.0f}}, {&ps_2d, {32, 16, 1, 3, 1, 0}, 1, {16.0f, 8.0f, 3.0f, 0.0f}}, {&ps_2d, {32, 16, 1, 3, 1, 0}, 2, { 8.0f, 4.0f, 3.0f, 0.0f}}, {&ps_2d_array, {64, 64, 1, 1, 6, 0}, 0, {64.0f, 64.0f, 6.0f, 1.0f}}, {&ps_2d_array, {32, 16, 1, 3, 9, 0}, 0, {32.0f, 16.0f, 9.0f, 3.0f}}, {&ps_2d_array, {32, 16, 1, 3, 7, 0}, 1, {16.0f, 8.0f, 7.0f, 3.0f}}, {&ps_2d_array, {32, 16, 1, 3, 3, 0}, 2, { 8.0f, 4.0f, 3.0f, 3.0f}}, {&ps_3d, {64, 64, 2, 1, 1, 0}, 0, {64.0f, 64.0f, 2.0f, 1.0f}}, {&ps_3d, {64, 64, 2, 2, 1, 0}, 1, {32.0f, 32.0f, 1.0f, 2.0f}}, {&ps_3d, {64, 64, 4, 1, 1, 0}, 0, {64.0f, 64.0f, 4.0f, 1.0f}}, {&ps_3d, {64, 64, 4, 2, 1, 0}, 1, {32.0f, 32.0f, 2.0f, 2.0f}}, {&ps_3d, { 8, 8, 8, 1, 1, 0}, 0, { 8.0f, 8.0f, 8.0f, 1.0f}}, {&ps_3d, { 8, 8, 8, 4, 1, 0}, 0, { 8.0f, 8.0f, 8.0f, 4.0f}}, {&ps_3d, { 8, 8, 8, 4, 1, 0}, 1, { 4.0f, 4.0f, 4.0f, 4.0f}}, {&ps_3d, { 8, 8, 8, 4, 1, 0}, 2, { 2.0f, 2.0f, 2.0f, 4.0f}}, {&ps_3d, { 8, 8, 8, 4, 1, 0}, 3, { 1.0f, 1.0f, 1.0f, 4.0f}}, {&ps_cube, { 4, 4, 1, 1, 6, 1}, 0, { 4.0f, 4.0f, 1.0f, 0.0f}}, {&ps_cube, {32, 32, 1, 1, 6, 1}, 0, {32.0f, 32.0f, 1.0f, 0.0f}}, {&ps_cube, {32, 32, 1, 3, 6, 1}, 0, {32.0f, 32.0f, 3.0f, 0.0f}}, {&ps_cube, {32, 32, 1, 3, 6, 1}, 1, {16.0f, 16.0f, 3.0f, 0.0f}}, {&ps_cube, {32, 32, 1, 3, 6, 1}, 2, { 8.0f, 8.0f, 3.0f, 0.0f}}, {&ps_cube_array, { 4, 4, 1, 1, 12, 2}, 0, { 4.0f, 4.0f, 1.0f, 0.0f}}, {&ps_cube_array, {32, 32, 1, 1, 12, 2}, 0, {32.0f, 32.0f, 1.0f, 0.0f}}, {&ps_cube_array, {32, 32, 1, 3, 12, 2}, 0, {32.0f, 32.0f, 3.0f, 0.0f}}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; feature_level = ID3D11Device_GetFeatureLevel(device); texture_desc.Width = 64; texture_desc.Height = 64; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rtv_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rtv_texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); memset(&constant, 0, sizeof(constant)); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constant), &constant); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ps = NULL; current_ps = NULL; for (i = 0; i < ARRAY_SIZE(ps_tests); ++i) { const struct ps_test *test = &ps_tests[i]; if (test->texture_desc.cube_count > 1 && feature_level < D3D_FEATURE_LEVEL_10_1) { skip("Test %u: Cube map array textures require feature level 10_1.\n", i); continue; } if (current_ps != test->ps) { if (ps) ID3D11PixelShader_Release(ps); current_ps = test->ps; hr = ID3D11Device_CreatePixelShader(device, current_ps->code, current_ps->size, NULL, &ps); ok(SUCCEEDED(hr), "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); } if (test->texture_desc.depth != 1) { texture3d_desc.Width = test->texture_desc.width; texture3d_desc.Height = test->texture_desc.height; texture3d_desc.Depth = test->texture_desc.depth; texture3d_desc.MipLevels = test->texture_desc.miplevel_count; texture3d_desc.Format = DXGI_FORMAT_R8_UNORM; texture3d_desc.Usage = D3D11_USAGE_DEFAULT; texture3d_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture3d_desc.CPUAccessFlags = 0; texture3d_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, (ID3D11Texture3D **)&texture); ok(SUCCEEDED(hr), "Test %u: Failed to create 3d texture, hr %#x.\n", i, hr); } else { texture_desc.Width = test->texture_desc.width; texture_desc.Height = test->texture_desc.height; texture_desc.MipLevels = test->texture_desc.miplevel_count; texture_desc.ArraySize = test->texture_desc.array_size; texture_desc.Format = DXGI_FORMAT_R8_UNORM; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.MiscFlags = 0; if (test->texture_desc.cube_count) texture_desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&texture); ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); } hr = ID3D11Device_CreateShaderResourceView(device, texture, NULL, &srv); ok(SUCCEEDED(hr), "Test %u: Failed to create shader resource view, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); for (type = 0; type < 2; ++type) { constant.x = type; constant.y = test->miplevel; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); check_texture_vec4(rtv_texture, &test->expected_result, 0); } ID3D11Resource_Release(texture); ID3D11ShaderResourceView_Release(srv); } ID3D11PixelShader_Release(ps); ID3D11Buffer_Release(cb); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(rtv_texture); release_test_context(&test_context); } static void test_sm5_bufinfo_instruction(void) { struct shader { const DWORD *code; size_t size; }; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; const struct shader *current_ps; ID3D11UnorderedAccessView *uav; ID3D11ShaderResourceView *srv; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Buffer *buffer; ID3D11Device *device; unsigned int i; HRESULT hr; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const DWORD ps_uav_structured_code[] = { #if 0 struct s { uint4 u; bool b; }; RWStructuredBuffer b; uint4 main(void) : SV_Target { uint count, stride; b.GetDimensions(count, stride); return uint4(count, stride, 0, 1); } #endif 0x43425844, 0xe1900f85, 0x13c1f338, 0xbb19865e, 0x366df28f, 0x00000001, 0x000000fc, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000084, 0x00000050, 0x00000021, 0x0100086a, 0x0400009e, 0x0011e000, 0x00000001, 0x00000014, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x87000079, 0x8000a302, 0x00199983, 0x00100012, 0x00000000, 0x0011ee46, 0x00000001, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x08000036, 0x001020e2, 0x00000000, 0x00004002, 0x00000000, 0x00000014, 0x00000000, 0x00000001, 0x0100003e, }; static const struct shader ps_uav_structured = {ps_uav_structured_code, sizeof(ps_uav_structured_code)}; static const DWORD ps_uav_structured32_code[] = { #if 0 struct s { uint4 u; bool4 b; }; RWStructuredBuffer b; uint4 main(void) : SV_Target { uint count, stride; b.GetDimensions(count, stride); return uint4(count, stride, 0, 1); } #endif 0x43425844, 0xdd87a805, 0x28090470, 0xe4fa7c4d, 0x57963f52, 0x00000001, 0x000000fc, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000084, 0x00000050, 0x00000021, 0x0100086a, 0x0400009e, 0x0011e000, 0x00000001, 0x00000020, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x87000079, 0x80010302, 0x00199983, 0x00100012, 0x00000000, 0x0011ee46, 0x00000001, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x08000036, 0x001020e2, 0x00000000, 0x00004002, 0x00000000, 0x00000020, 0x00000000, 0x00000001, 0x0100003e, }; static const struct shader ps_uav_structured32 = {ps_uav_structured32_code, sizeof(ps_uav_structured32_code)}; static const DWORD ps_srv_structured_code[] = { #if 0 StructuredBuffer b; uint4 main(void) : SV_Target { uint count, stride; b.GetDimensions(count, stride); return uint4(count, stride, 0, 1); } #endif 0x43425844, 0x313f910c, 0x2f60c646, 0x2d87455c, 0xb9988c2c, 0x00000001, 0x000000fc, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000084, 0x00000050, 0x00000021, 0x0100086a, 0x040000a2, 0x00107000, 0x00000000, 0x00000004, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x87000079, 0x80002302, 0x00199983, 0x00100012, 0x00000000, 0x00107e46, 0x00000000, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x08000036, 0x001020e2, 0x00000000, 0x00004002, 0x00000000, 0x00000004, 0x00000000, 0x00000001, 0x0100003e, }; static const struct shader ps_srv_structured = {ps_srv_structured_code, sizeof(ps_srv_structured_code)}; static const DWORD ps_uav_raw_code[] = { #if 0 RWByteAddressBuffer b; uint4 main(void) : SV_Target { uint width; b.GetDimensions(width); return width; } #endif 0x43425844, 0xb06e9715, 0x99733b00, 0xaa536550, 0x703a01c5, 0x00000001, 0x000000d8, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000060, 0x00000050, 0x00000018, 0x0100086a, 0x0300009d, 0x0011e000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x87000079, 0x800002c2, 0x00199983, 0x00100012, 0x00000000, 0x0011ee46, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x0100003e, }; static const struct shader ps_uav_raw = {ps_uav_raw_code, sizeof(ps_uav_raw_code)}; static const DWORD ps_srv_raw_code[] = { #if 0 ByteAddressBuffer b; uint4 main(void) : SV_Target { uint width; b.GetDimensions(width); return width; } #endif 0x43425844, 0x934bc27a, 0x3251cc9d, 0xa129bdd3, 0xf7cedcc4, 0x00000001, 0x000000d8, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000060, 0x00000050, 0x00000018, 0x0100086a, 0x030000a1, 0x00107000, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x87000079, 0x800002c2, 0x00199983, 0x00100012, 0x00000000, 0x00107e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x0100003e, }; static const struct shader ps_srv_raw = {ps_srv_raw_code, sizeof(ps_srv_raw_code)}; static const DWORD ps_uav_typed_code[] = { #if 0 RWBuffer b; uint4 main(void) : SV_Target { uint width; b.GetDimensions(width); return width; } #endif 0x43425844, 0x96b39f5f, 0x5fef24c7, 0xed404a41, 0x01c9d4fe, 0x00000001, 0x000000dc, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000064, 0x00000050, 0x00000019, 0x0100086a, 0x0400089c, 0x0011e000, 0x00000001, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x87000079, 0x80000042, 0x00155543, 0x00100012, 0x00000000, 0x0011ee46, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x0100003e, }; static const struct shader ps_uav_typed = {ps_uav_typed_code, sizeof(ps_uav_typed_code)}; static const DWORD ps_srv_typed_code[] = { #if 0 Buffer b; uint4 main(void) : SV_Target { uint width; b.GetDimensions(width); return width; } #endif 0x43425844, 0x6ae6dbb0, 0x6289d227, 0xaf4e708e, 0x111efed1, 0x00000001, 0x000000dc, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000064, 0x00000050, 0x00000019, 0x0100086a, 0x04000858, 0x00107000, 0x00000000, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x87000079, 0x80000042, 0x00155543, 0x00100012, 0x00000000, 0x00107e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x0100003e, }; static const struct shader ps_srv_typed = {ps_srv_typed_code, sizeof(ps_srv_typed_code)}; static const struct test { const struct shader *ps; BOOL uav; unsigned int buffer_size; unsigned int buffer_misc_flags; unsigned int buffer_structure_byte_stride; DXGI_FORMAT view_format; unsigned int view_element_idx; unsigned int view_element_count; struct uvec4 expected_result; } tests[] = { #define RAW D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS #define STRUCTURED D3D11_RESOURCE_MISC_BUFFER_STRUCTURED {&ps_uav_raw, TRUE, 100, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 0, 25, {100, 100, 100, 100}}, {&ps_uav_raw, TRUE, 512, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 64, 64, {256, 256, 256, 256}}, {&ps_srv_raw, FALSE, 100, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 0, 25, {100, 100, 100, 100}}, {&ps_srv_raw, FALSE, 500, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 64, 4, { 16, 16, 16, 16}}, {&ps_uav_structured, TRUE, 100, STRUCTURED, 20, DXGI_FORMAT_UNKNOWN, 0, 5, { 5, 20, 0, 1}}, {&ps_uav_structured, TRUE, 100, STRUCTURED, 20, DXGI_FORMAT_UNKNOWN, 0, 2, { 2, 20, 0, 1}}, {&ps_uav_structured32, TRUE, 320, STRUCTURED, 32, DXGI_FORMAT_UNKNOWN, 8, 2, { 2, 32, 0, 1}}, {&ps_srv_structured, FALSE, 100, STRUCTURED, 4, DXGI_FORMAT_UNKNOWN, 0, 5, { 5, 4, 0, 1}}, {&ps_srv_structured, FALSE, 100, STRUCTURED, 4, DXGI_FORMAT_UNKNOWN, 0, 2, { 2, 4, 0, 1}}, {&ps_srv_structured, FALSE, 400, STRUCTURED, 4, DXGI_FORMAT_UNKNOWN, 64, 2, { 2, 4, 0, 1}}, {&ps_uav_typed, TRUE, 200, 0, 0, DXGI_FORMAT_R32_FLOAT, 0, 50, { 50, 50, 50, 50}}, {&ps_uav_typed, TRUE, 400, 0, 0, DXGI_FORMAT_R32_FLOAT, 64, 1, { 1, 1, 1, 1}}, {&ps_uav_typed, TRUE, 100, 0, 0, DXGI_FORMAT_R16_FLOAT, 0, 50, { 50, 50, 50, 50}}, {&ps_uav_typed, TRUE, 400, 0, 0, DXGI_FORMAT_R16_FLOAT, 128, 1, { 1, 1, 1, 1}}, {&ps_srv_typed, FALSE, 200, 0, 0, DXGI_FORMAT_R32_FLOAT, 0, 50, { 50, 50, 50, 50}}, {&ps_srv_typed, FALSE, 400, 0, 0, DXGI_FORMAT_R32_FLOAT, 64, 1, { 1, 1, 1, 1}}, {&ps_srv_typed, FALSE, 100, 0, 0, DXGI_FORMAT_R16_FLOAT, 0, 50, { 50, 50, 50, 50}}, {&ps_srv_typed, FALSE, 400, 0, 0, DXGI_FORMAT_R16_FLOAT, 128, 2, { 2, 2, 2, 2}}, #undef RAW #undef STRUCTURED }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 64; texture_desc.Height = 64; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32G32B32A32_UINT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); ps = NULL; current_ps = NULL; for (i = 0; i < ARRAY_SIZE(tests); ++i) { const struct test *test = &tests[i]; if (current_ps != test->ps) { if (ps) ID3D11PixelShader_Release(ps); current_ps = test->ps; hr = ID3D11Device_CreatePixelShader(device, current_ps->code, current_ps->size, NULL, &ps); ok(SUCCEEDED(hr), "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); } buffer_desc.ByteWidth = test->buffer_size; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = test->buffer_misc_flags; buffer_desc.StructureByteStride = test->buffer_structure_byte_stride; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Test %u: Failed to create buffer, hr %#x.\n", i, hr); if (test->uav) { uav_desc.Format = test->view_format; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = test->view_element_idx; U(uav_desc).Buffer.NumElements = test->view_element_count; U(uav_desc).Buffer.Flags = 0; if (buffer_desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) U(uav_desc).Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_RAW; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(SUCCEEDED(hr), "Test %u: Failed to create unordered access view, hr %#x.\n", i, hr); srv = NULL; ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, 1, &rtv, NULL, 1, 1, &uav, NULL); } else { srv_desc.Format = test->view_format; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; U(srv_desc).BufferEx.FirstElement = test->view_element_idx; U(srv_desc).BufferEx.NumElements = test->view_element_count; U(srv_desc).BufferEx.Flags = 0; if (buffer_desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) U(srv_desc).BufferEx.Flags |= D3D11_BUFFEREX_SRV_FLAG_RAW; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)buffer, &srv_desc, &srv); ok(SUCCEEDED(hr), "Test %u: Failed to create shader resource view, hr %#x.\n", i, hr); uav = NULL; ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); } draw_quad(&test_context); check_texture_uvec4(texture, &test->expected_result); if (srv) ID3D11ShaderResourceView_Release(srv); if (uav) ID3D11UnorderedAccessView_Release(uav); ID3D11Buffer_Release(buffer); } ID3D11PixelShader_Release(ps); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_sampleinfo_instruction(void) { ID3D11Texture2D *float_rt_texture, *uint_rt_texture; ID3D11RenderTargetView *float_rtv, *uint_rtv, *rtv; ID3D11PixelShader *ps_float, *ps_uint, *ps_rt; ID3D11Texture2D *texture, *readback_texture; struct d3d11_test_context test_context; unsigned int sample_count, quality; D3D11_TEXTURE2D_DESC texture_desc; ID3D11RenderTargetView *rtvs[2]; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; struct uvec4 expected_uint; struct vec4 expected_float; ID3D11Device *device; HRESULT hr; static const DWORD ps_uint_code[] = { #if 0 Texture2DMS t; uint4 main() : SV_Target1 { uint width, height, sample_count; t.GetDimensions(width, height, sample_count); return sample_count; } #endif 0x43425844, 0x4342ad12, 0x19addd8c, 0x5cb87c48, 0xe604a242, 0x00000001, 0x000000d4, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x0000005c, 0x00000050, 0x00000017, 0x0100086a, 0x04002058, 0x00107000, 0x00000000, 0x00005555, 0x03000065, 0x001020f2, 0x00000001, 0x02000068, 0x00000001, 0x0500086f, 0x00100012, 0x00000000, 0x0010700a, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00100006, 0x00000000, 0x0100003e, }; static const DWORD ps_float_code[] = { #if 0 Texture2DMS t; float4 main() : SV_Target { uint width, height, sample_count; t.GetDimensions(width, height, sample_count); return sample_count; } #endif 0x43425844, 0x2b8aea46, 0x34ceda6f, 0xf98d222b, 0x235ebc0b, 0x00000001, 0x000000b8, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000040, 0x00000050, 0x00000010, 0x0100086a, 0x04002058, 0x00107000, 0x00000000, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x0500006f, 0x001020f2, 0x00000000, 0x0010700a, 0x00000000, 0x0100003e, }; static const DWORD ps_rt_code[] = { #if 0 float4 main() : SV_Target { return GetRenderTargetSampleCount(); } #endif 0x43425844, 0x74404d37, 0xad6f88e4, 0xb006ea57, 0xf07d9e2a, 0x00000001, 0x000000a4, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x0000002c, 0x00000050, 0x0000000b, 0x0100086a, 0x03000065, 0x001020f2, 0x00000000, 0x0400006f, 0x001020f2, 0x00000000, 0x0000e00a, 0x0100003e, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 64; texture_desc.Height = 64; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &float_rt_texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)float_rt_texture, NULL, &float_rtv); ok(hr == S_OK, "Failed to create rendertarget view, hr %#x.\n", hr); texture_desc.Format = DXGI_FORMAT_R32G32B32A32_UINT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &uint_rt_texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)uint_rt_texture, NULL, &uint_rtv); ok(hr == S_OK, "Failed to create rendertarget view, hr %#x.\n", hr); rtvs[0] = float_rtv; rtvs[1] = uint_rtv; ID3D11DeviceContext_OMSetRenderTargets(context, ARRAY_SIZE(rtvs), rtvs, NULL); hr = ID3D11Device_CreatePixelShader(device, ps_float_code, sizeof(ps_float_code), NULL, &ps_float); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_uint_code, sizeof(ps_uint_code), NULL, &ps_uint); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); for (sample_count = 2; sample_count <= 8; sample_count *= 2) { texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texture_desc.SampleDesc.Count = sample_count; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; hr = ID3D11Device_CheckMultisampleQualityLevels(device, texture_desc.Format, sample_count, &quality); ok(hr == S_OK, "Failed to check multisample quality levels, hr %#x.\n", hr); if (!quality) { skip("Sample count %u not supported.\n", sample_count); continue; } hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Failed to create texture, hr %#x, sample count %u.\n", hr, sample_count); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(hr == S_OK, "Failed to create shader resource view, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); ID3D11DeviceContext_PSSetShader(context, ps_float, NULL, 0); draw_quad(&test_context); ID3D11DeviceContext_PSSetShader(context, ps_uint, NULL, 0); draw_quad(&test_context); expected_float.x = expected_float.y = expected_float.z = expected_float.w = sample_count; check_texture_vec4(float_rt_texture, &expected_float, 0); expected_uint.x = expected_uint.y = expected_uint.z = expected_uint.w = sample_count; check_texture_uvec4(uint_rt_texture, &expected_uint); ID3D11Texture2D_Release(texture); ID3D11ShaderResourceView_Release(srv); } hr = ID3D11Device_CreatePixelShader(device, ps_rt_code, sizeof(ps_rt_code), NULL, &ps_rt); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); for (sample_count = 1; sample_count <= 8; sample_count *= 2) { texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; texture_desc.SampleDesc.Count = sample_count; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; hr = ID3D11Device_CheckMultisampleQualityLevels(device, texture_desc.Format, sample_count, &quality); ok(hr == S_OK, "Failed to check multisample quality levels, hr %#x.\n", hr); if (!quality) { skip("Sample count %u not supported.\n", sample_count); continue; } hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Failed to create texture, hr %#x, sample count %u.\n", hr, sample_count); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(hr == S_OK, "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); /* Some drivers (AMD Radeon HD 6310) return stale sample counts if we * don't rebind the pixel shader between runs with different sample * counts. */ ID3D11DeviceContext_PSSetShader(context, NULL, NULL, 0); ID3D11DeviceContext_PSSetShader(context, ps_rt, NULL, 0); draw_quad(&test_context); if (sample_count != 1) { texture_desc.SampleDesc.Count = 1; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &readback_texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); ID3D11DeviceContext_ResolveSubresource(context, (ID3D11Resource *)readback_texture, 0, (ID3D11Resource *)texture, 0, texture_desc.Format); } else { readback_texture = texture; ID3D11Texture2D_AddRef(readback_texture); } expected_float.x = expected_float.y = expected_float.z = expected_float.w = sample_count; check_texture_vec4(readback_texture, &expected_float, 0); ID3D11Texture2D_Release(readback_texture); ID3D11Texture2D_Release(texture); ID3D11RenderTargetView_Release(rtv); } ID3D11RenderTargetView_Release(float_rtv); ID3D11RenderTargetView_Release(uint_rtv); ID3D11Texture2D_Release(float_rt_texture); ID3D11Texture2D_Release(uint_rt_texture); ID3D11PixelShader_Release(ps_float); ID3D11PixelShader_Release(ps_uint); ID3D11PixelShader_Release(ps_rt); release_test_context(&test_context); } static void test_render_target_device_mismatch(void) { struct d3d11_test_context test_context; struct device_desc device_desc = {0}; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Device *device; ULONG refcount; if (!init_test_context(&test_context, NULL)) return; device = create_device(&device_desc); ok(!!device, "Failed to create device.\n"); ID3D11Device_GetImmediateContext(device, &context); rtv = (ID3D11RenderTargetView *)0xdeadbeef; ID3D11DeviceContext_OMGetRenderTargets(context, 1, &rtv, NULL); ok(!rtv, "Got unexpected render target view %p.\n", rtv); if (!enable_debug_layer) { ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, NULL); ID3D11DeviceContext_OMGetRenderTargets(context, 1, &rtv, NULL); ok(rtv == test_context.backbuffer_rtv, "Got unexpected render target view %p.\n", rtv); ID3D11RenderTargetView_Release(rtv); } rtv = NULL; ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); release_test_context(&test_context); } static void test_buffer_srv(void) { struct shader { const DWORD *code; size_t size; BOOL requires_raw_and_structured_buffers; }; struct buffer { unsigned int byte_count; unsigned int data_offset; const void *data; unsigned int structure_byte_stride; }; BOOL raw_and_structured_buffers_supported; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; struct d3d11_test_context test_context; D3D11_SUBRESOURCE_DATA resource_data; const struct buffer *current_buffer; const struct shader *current_shader; ID3D11ShaderResourceView *srv; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; DWORD color, expected_color; struct resource_readback rb; ID3D11Buffer *cb, *buffer; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, x, y; struct vec4 cb_size; HRESULT hr; static const DWORD ps_float4_code[] = { #if 0 Buffer b; float2 size; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; int2 coords; p.x = position.x / 640.0f; p.y = position.y / 480.0f; coords = int2(p.x * size.x, p.y * size.y); return b.Load(coords.y * size.x + coords.x); } #endif 0x43425844, 0xf10ea650, 0x311f5c38, 0x3a888b7f, 0x58230334, 0x00000001, 0x000001a0, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000104, 0x00000040, 0x00000041, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04000858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x08000038, 0x00100032, 0x00000000, 0x00101516, 0x00000000, 0x00208516, 0x00000000, 0x00000000, 0x0a000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00004002, 0x3b088889, 0x3acccccd, 0x00000000, 0x00000000, 0x05000043, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x0a000032, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0010001a, 0x00000000, 0x0500001b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0700002d, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00107e46, 0x00000000, 0x0100003e, }; static const struct shader ps_float4 = {ps_float4_code, sizeof(ps_float4_code)}; static const DWORD ps_structured_code[] = { #if 0 StructuredBuffer b; float2 size; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; int2 coords; p.x = position.x / 640.0f; p.y = position.y / 480.0f; coords = int2(p.x * size.x, p.y * size.y); return b[coords.y * size.x + coords.x]; } #endif 0x43425844, 0x246caabb, 0xf1e7d6b9, 0xcbe720dc, 0xcdc23036, 0x00000001, 0x000001c0, 0x00000004, 0x00000030, 0x00000064, 0x00000098, 0x000001b0, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000110, 0x00000040, 0x00000044, 0x0100486a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x040000a2, 0x00107000, 0x00000000, 0x00000010, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x08000038, 0x00100032, 0x00000000, 0x00101516, 0x00000000, 0x00208516, 0x00000000, 0x00000000, 0x0a000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00004002, 0x3b088889, 0x3acccccd, 0x00000000, 0x00000000, 0x05000043, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x0a000032, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0010001a, 0x00000000, 0x0500001c, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x090000a7, 0x001020f2, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, 0x00000000, 0x0100003e, 0x30494653, 0x00000008, 0x00000002, 0x00000000, }; static const struct shader ps_structured = {ps_structured_code, sizeof(ps_structured_code), TRUE}; static const DWORD rgba16[] = { 0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00, 0xffff0000, 0xffff00ff, 0xff000000, 0xff7f7f7f, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, }; static const DWORD rgba4[] = { 0xffffffff, 0xff0000ff, 0xff000000, 0xff00ff00, }; static const BYTE r4[] = { 0xde, 0xad, 0xba, 0xbe, }; static const struct vec4 rgba_float[] = { {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, }; static const struct buffer rgba16_buffer = {sizeof(rgba16), 0, &rgba16}; static const struct buffer rgba16_offset_buffer = {256 + sizeof(rgba16), 256, &rgba16}; static const struct buffer rgba4_buffer = {sizeof(rgba4), 0, &rgba4}; static const struct buffer r4_buffer = {sizeof(r4), 0, &r4}; static const struct buffer r4_offset_buffer = {256 + sizeof(r4), 256, &r4}; static const struct buffer float_buffer = {sizeof(rgba_float), 0, &rgba_float, sizeof(*rgba_float)}; static const struct buffer float_offset_buffer = {256 + sizeof(rgba_float), 256, &rgba_float, sizeof(*rgba_float)}; static const DWORD rgba16_colors2x2[] = { 0xff0000ff, 0xff0000ff, 0xff00ffff, 0xff00ffff, 0xff0000ff, 0xff0000ff, 0xff00ffff, 0xff00ffff, 0xff00ff00, 0xff00ff00, 0xffffff00, 0xffffff00, 0xff00ff00, 0xff00ff00, 0xffffff00, 0xffffff00, }; static const DWORD rgba16_colors1x1[] = { 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, }; static const DWORD rgba4_colors[] = { 0xffffffff, 0xffffffff, 0xff0000ff, 0xff0000ff, 0xffffffff, 0xffffffff, 0xff0000ff, 0xff0000ff, 0xff000000, 0xff000000, 0xff00ff00, 0xff00ff00, 0xff000000, 0xff000000, 0xff00ff00, 0xff00ff00, }; static const DWORD r4_colors[] = { 0xff0000de, 0xff0000de, 0xff0000ad, 0xff0000ad, 0xff0000de, 0xff0000de, 0xff0000ad, 0xff0000ad, 0xff0000ba, 0xff0000ba, 0xff0000be, 0xff0000be, 0xff0000ba, 0xff0000ba, 0xff0000be, 0xff0000be, }; static const DWORD zero_colors[16] = {0}; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; static const struct test { const struct shader *shader; const struct buffer *buffer; DXGI_FORMAT srv_format; unsigned int srv_first_element; unsigned int srv_element_count; struct vec2 size; const DWORD *expected_colors; } tests[] = { {&ps_float4, &rgba16_buffer, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 16, {4.0f, 4.0f}, rgba16}, {&ps_float4, &rgba16_offset_buffer, DXGI_FORMAT_R8G8B8A8_UNORM, 64, 16, {4.0f, 4.0f}, rgba16}, {&ps_float4, &rgba16_buffer, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 4, {2.0f, 2.0f}, rgba16_colors2x2}, {&ps_float4, &rgba16_buffer, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 1, {1.0f, 1.0f}, rgba16_colors1x1}, {&ps_float4, &rgba4_buffer, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 4, {2.0f, 2.0f}, rgba4_colors}, {&ps_float4, &r4_buffer, DXGI_FORMAT_R8_UNORM, 0, 4, {2.0f, 2.0f}, r4_colors}, {&ps_float4, &r4_offset_buffer, DXGI_FORMAT_R8_UNORM, 256, 4, {2.0f, 2.0f}, r4_colors}, {&ps_structured, &float_buffer, DXGI_FORMAT_UNKNOWN, 0, 4, {2.0f, 2.0f}, rgba4_colors}, {&ps_structured, &float_offset_buffer, DXGI_FORMAT_UNKNOWN, 16, 4, {2.0f, 2.0f}, rgba4_colors}, {&ps_float4, NULL, 0, 0, 0, {2.0f, 2.0f}, zero_colors}, {&ps_float4, NULL, 0, 0, 0, {1.0f, 1.0f}, zero_colors}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; raw_and_structured_buffers_supported = ID3D11Device_GetFeatureLevel(device) >= D3D_FEATURE_LEVEL_11_0 || check_compute_shaders_via_sm4_support(device); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(cb_size), NULL); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); buffer_desc.ByteWidth = 256; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); srv_desc.Format = DXGI_FORMAT_R8_UNORM; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; U(srv_desc).Buffer.FirstElement = 0; U(srv_desc).Buffer.NumElements = 0; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)buffer, &srv_desc, &srv); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ID3D11Buffer_Release(buffer); ps = NULL; srv = NULL; buffer = NULL; current_shader = NULL; current_buffer = NULL; for (i = 0; i < ARRAY_SIZE(tests); ++i) { const struct test *test = &tests[i]; if (test->shader->requires_raw_and_structured_buffers && !raw_and_structured_buffers_supported) { skip("Test %u: Raw and structured buffers are not supported.\n", i); continue; } /* Structured buffer views with an offset don't seem to work on WARP. */ if (test->srv_format == DXGI_FORMAT_UNKNOWN && test->srv_first_element && is_warp_device(device)) { skip("Test %u: Broken WARP.\n", i); continue; } if (current_shader != test->shader) { if (ps) ID3D11PixelShader_Release(ps); current_shader = test->shader; hr = ID3D11Device_CreatePixelShader(device, current_shader->code, current_shader->size, NULL, &ps); ok(SUCCEEDED(hr), "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); } if (current_buffer != test->buffer) { if (buffer) ID3D11Buffer_Release(buffer); current_buffer = test->buffer; if (current_buffer) { BYTE *data = NULL; buffer_desc.ByteWidth = current_buffer->byte_count; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = 0; if ((buffer_desc.StructureByteStride = current_buffer->structure_byte_stride)) buffer_desc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; resource_data.SysMemPitch = 0; resource_data.SysMemSlicePitch = 0; if (current_buffer->data_offset) { data = heap_alloc_zero(current_buffer->byte_count); ok(!!data, "Failed to allocate memory.\n"); memcpy(data + current_buffer->data_offset, current_buffer->data, current_buffer->byte_count - current_buffer->data_offset); resource_data.pSysMem = data; } else { resource_data.pSysMem = current_buffer->data; } hr = ID3D11Device_CreateBuffer(device, &buffer_desc, &resource_data, &buffer); ok(SUCCEEDED(hr), "Test %u: Failed to create buffer, hr %#x.\n", i, hr); heap_free(data); } else { buffer = NULL; } } if (srv) ID3D11ShaderResourceView_Release(srv); if (current_buffer) { srv_desc.Format = test->srv_format; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; U(srv_desc).Buffer.FirstElement = test->srv_first_element; U(srv_desc).Buffer.NumElements = test->srv_element_count; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)buffer, &srv_desc, &srv); ok(SUCCEEDED(hr), "Test %u: Failed to create shader resource view, hr %#x.\n", i, hr); } else { srv = NULL; } ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); cb_size.x = test->size.x; cb_size.y = test->size.y; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &cb_size, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 80 + x * 160, 60 + y * 120, 0); expected_color = test->expected_colors[y * 4 + x]; ok(compare_color(color, expected_color, 1), "Test %u: Got 0x%08x, expected 0x%08x at (%u, %u).\n", i, color, expected_color, x, y); } } release_resource_readback(&rb); } if (srv) ID3D11ShaderResourceView_Release(srv); if (buffer) ID3D11Buffer_Release(buffer); ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_unaligned_raw_buffer_access(const D3D_FEATURE_LEVEL feature_level) { D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; struct d3d11_test_context test_context; D3D11_SUBRESOURCE_DATA resource_data; D3D11_TEXTURE2D_DESC texture_desc; ID3D11UnorderedAccessView *uav; ID3D11ShaderResourceView *srv; D3D11_BUFFER_DESC buffer_desc; ID3D11Buffer *cb, *raw_buffer; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11RenderTargetView *rtv; ID3D11Texture2D *texture; ID3D11ComputeShader *cs; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i, data; struct uvec4 offset; HRESULT hr; static const unsigned int buffer_data[] = { 0xffffffff, 0x00000000, }; static const DWORD ps_code[] = { #if 0 ByteAddressBuffer buffer; uint offset; uint main() : SV_Target0 { return buffer.Load(offset); } #endif 0x43425844, 0xda171175, 0xb001721f, 0x60ef80eb, 0xe1fa7e75, 0x00000001, 0x000000e4, 0x00000004, 0x00000030, 0x00000040, 0x00000074, 0x000000d4, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000e01, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000058, 0x00000040, 0x00000016, 0x0100486a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x030000a1, 0x00107000, 0x00000000, 0x03000065, 0x00102012, 0x00000000, 0x080000a5, 0x00102012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00107006, 0x00000000, 0x0100003e, 0x30494653, 0x00000008, 0x00000002, 0x00000000, }; static const DWORD cs_code[] = { #if 0 RWByteAddressBuffer buffer; uint2 input; [numthreads(1, 1, 1)] void main() { buffer.Store(input.x, input.y); } #endif 0x43425844, 0x3c7103b0, 0xe6313979, 0xbcfb0c11, 0x3958af0c, 0x00000001, 0x000000b4, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000060, 0x00050050, 0x00000018, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300009d, 0x0011e000, 0x00000000, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x090000a6, 0x0011e012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0100003e, }; static const float black[] = {0.0f, 0.0f, 0.0f, 0.0f}; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; if (feature_level < D3D_FEATURE_LEVEL_11_0 && !check_compute_shaders_via_sm4_support(device)) { hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); if (SUCCEEDED(hr)) ID3D11PixelShader_Release(ps); skip("Raw buffers are not supported.\n"); release_test_context(&test_context); return; } if (is_intel_device(device)) { /* Offsets for raw buffer reads and writes should be 4 bytes aligned. * This test checks what happens when offsets are not properly aligned. * The behavior seems to be undefined on Intel hardware. */ win_skip("Skipping the test on Intel hardware.\n"); release_test_context(&test_context); return; } hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); memset(&offset, 0, sizeof(offset)); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(offset), &offset.x); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_R32_UINT; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); buffer_desc.ByteWidth = sizeof(buffer_data); buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; resource_data.pSysMem = buffer_data; resource_data.SysMemPitch = 0; resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, &resource_data, &raw_buffer); ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); srv_desc.Format = DXGI_FORMAT_R32_TYPELESS; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; U(srv_desc).BufferEx.FirstElement = 0; U(srv_desc).BufferEx.NumElements = buffer_desc.ByteWidth / sizeof(unsigned int); U(srv_desc).BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)raw_buffer, &srv_desc, &srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); offset.x = 0; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, black); draw_quad(&test_context); check_texture_color(texture, buffer_data[0], 0); offset.x = 1; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, black); draw_quad(&test_context); check_texture_color(texture, buffer_data[0], 0); offset.x = 2; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, black); draw_quad(&test_context); check_texture_color(texture, buffer_data[0], 0); offset.x = 3; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, black); draw_quad(&test_context); check_texture_color(texture, buffer_data[0], 0); offset.x = 4; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, black); draw_quad(&test_context); check_texture_color(texture, buffer_data[1], 0); offset.x = 7; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, black); draw_quad(&test_context); check_texture_color(texture, buffer_data[1], 0); if (feature_level < D3D_FEATURE_LEVEL_11_0) { skip("Feature level 11_0 required for unaligned UAV test.\n"); goto done; } ID3D11Buffer_Release(raw_buffer); buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &raw_buffer); ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = buffer_desc.ByteWidth / sizeof(unsigned int); U(uav_desc).Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)raw_buffer, &uav_desc, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateComputeShader(device, cs_code, sizeof(cs_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_CSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); offset.x = 0; offset.y = 0xffffffff; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_ClearUnorderedAccessViewFloat(context, uav, black); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); get_buffer_readback(raw_buffer, &rb); for (i = 0; i < ARRAY_SIZE(buffer_data); ++i) { data = get_readback_color(&rb, i, 0, 0); ok(data == buffer_data[i], "Got unexpected result %#x at %u.\n", data, i); } release_resource_readback(&rb); offset.x = 1; offset.y = 0xffffffff; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_ClearUnorderedAccessViewFloat(context, uav, black); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); get_buffer_readback(raw_buffer, &rb); for (i = 0; i < ARRAY_SIZE(buffer_data); ++i) { data = get_readback_color(&rb, i, 0, 0); ok(data == buffer_data[i], "Got unexpected result %#x at %u.\n", data, i); } release_resource_readback(&rb); offset.x = 2; offset.y = 0xffffffff; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_ClearUnorderedAccessViewFloat(context, uav, black); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); get_buffer_readback(raw_buffer, &rb); for (i = 0; i < ARRAY_SIZE(buffer_data); ++i) { data = get_readback_color(&rb, i, 0, 0); ok(data == buffer_data[i], "Got unexpected result %#x at %u.\n", data, i); } release_resource_readback(&rb); offset.x = 3; offset.y = 0xffffffff; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_ClearUnorderedAccessViewFloat(context, uav, black); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); get_buffer_readback(raw_buffer, &rb); for (i = 0; i < ARRAY_SIZE(buffer_data); ++i) { data = get_readback_color(&rb, i, 0, 0); ok(data == buffer_data[i], "Got unexpected result %#x at %u.\n", data, i); } release_resource_readback(&rb); ID3D11DeviceContext_ClearUnorderedAccessViewFloat(context, uav, black); offset.x = 3; offset.y = 0xffff; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); offset.x = 4; offset.y = 0xa; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &offset, 0, 0); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); get_buffer_readback(raw_buffer, &rb); data = get_readback_color(&rb, 0, 0, 0); ok(data == 0xffff, "Got unexpected result %#x.\n", data); data = get_readback_color(&rb, 1, 0, 0); ok(data == 0xa, "Got unexpected result %#x.\n", data); release_resource_readback(&rb); ID3D11ComputeShader_Release(cs); ID3D11UnorderedAccessView_Release(uav); done: ID3D11Buffer_Release(cb); ID3D11Buffer_Release(raw_buffer); ID3D11PixelShader_Release(ps); ID3D11RenderTargetView_Release(rtv); ID3D11ShaderResourceView_Release(srv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static unsigned int read_uav_counter(ID3D11DeviceContext *context, ID3D11Buffer *staging_buffer, ID3D11UnorderedAccessView *uav) { D3D11_MAPPED_SUBRESOURCE map_desc; unsigned int counter; ID3D11DeviceContext_CopyStructureCount(context, staging_buffer, 0, uav); if (FAILED(ID3D11DeviceContext_Map(context, (ID3D11Resource *)staging_buffer, 0, D3D11_MAP_READ, 0, &map_desc))) return 0xdeadbeef; counter = *(unsigned int *)map_desc.pData; ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)staging_buffer, 0); return counter; } static int compare_id(const void *a, const void *b) { return *(int *)a - *(int *)b; } static void test_uav_counters(void) { ID3D11Buffer *buffer, *buffer2, *staging_buffer; ID3D11ComputeShader *cs_producer, *cs_consumer; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; struct d3d11_test_context test_context; ID3D11UnorderedAccessView *uav, *uav2; unsigned int data, id[128], i; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Device *device; D3D11_BOX box; HRESULT hr; static const DWORD cs_producer_code[] = { #if 0 RWStructuredBuffer u; [numthreads(4, 1, 1)] void main(uint3 dispatch_id : SV_DispatchThreadID) { uint counter = u.IncrementCounter(); u[counter] = dispatch_id.x; } #endif 0x43425844, 0x013163a8, 0xe7d371b8, 0x4f71e39a, 0xd479e584, 0x00000001, 0x000000c8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000074, 0x00050050, 0x0000001d, 0x0100086a, 0x0480009e, 0x0011e000, 0x00000000, 0x00000004, 0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000004, 0x00000001, 0x00000001, 0x050000b2, 0x00100012, 0x00000000, 0x0011e000, 0x00000000, 0x080000a8, 0x0011e012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0002000a, 0x0100003e, }; static const DWORD cs_consumer_code[] = { #if 0 RWStructuredBuffer u; RWStructuredBuffer u2; [numthreads(4, 1, 1)] void main() { uint counter = u.DecrementCounter(); u2[counter] = u[counter]; } #endif 0x43425844, 0x957ef3dd, 0x9f317559, 0x09c8f12d, 0xdbfd98c8, 0x00000001, 0x00000100, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000ac, 0x00050050, 0x0000002b, 0x0100086a, 0x0480009e, 0x0011e000, 0x00000000, 0x00000004, 0x0400009e, 0x0011e000, 0x00000001, 0x00000004, 0x02000068, 0x00000001, 0x0400009b, 0x00000004, 0x00000001, 0x00000001, 0x050000b3, 0x00100012, 0x00000000, 0x0011e000, 0x00000000, 0x8b0000a7, 0x80002302, 0x00199983, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0011e006, 0x00000000, 0x090000a8, 0x0011e012, 0x00000001, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0010001a, 0x00000000, 0x0100003e, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateComputeShader(device, cs_producer_code, sizeof(cs_producer_code), NULL, &cs_producer); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); hr = ID3D11Device_CreateComputeShader(device, cs_consumer_code, sizeof(cs_consumer_code), NULL, &cs_consumer); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); memset(&buffer_desc, 0, sizeof(buffer_desc)); buffer_desc.ByteWidth = sizeof(unsigned int); buffer_desc.Usage = D3D11_USAGE_STAGING; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &staging_buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); buffer_desc.ByteWidth = 1024; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; buffer_desc.StructureByteStride = sizeof(unsigned int); hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_UNKNOWN; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = buffer_desc.ByteWidth / sizeof(unsigned int); U(uav_desc).Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer2); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer2, NULL, &uav2); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); data = read_uav_counter(context, staging_buffer, uav); ok(!data, "Got unexpected initial value %u.\n", data); data = 8; ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, &data); data = read_uav_counter(context, staging_buffer, uav); ok(data == 8, "Got unexpected value %u.\n", data); data = ~0u; ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, &data); data = read_uav_counter(context, staging_buffer, uav); ok(data == 8, "Got unexpected value %u.\n", data); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); data = read_uav_counter(context, staging_buffer, uav); ok(data == 8, "Got unexpected value %u.\n", data); ID3D11DeviceContext_CSSetShader(context, cs_producer, NULL, 0); data = 0; ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, &data); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 1, 1, &uav2, NULL); data = read_uav_counter(context, staging_buffer, uav); ok(!data, "Got unexpected value %u.\n", data); /* produce */ ID3D11DeviceContext_Dispatch(context, 16, 1, 1); data = read_uav_counter(context, staging_buffer, uav); ok(data == 64, "Got unexpected value %u.\n", data); get_buffer_readback(buffer, &rb); memcpy(id, rb.map_desc.pData, 64 * sizeof(*id)); release_resource_readback(&rb); qsort(id, 64, sizeof(*id), compare_id); for (i = 0; i < 64; ++i) { if (id[i] != i) break; } ok(i == 64, "Got unexpected id %u at %u.\n", id[i], i); /* consume */ ID3D11DeviceContext_CSSetShader(context, cs_consumer, NULL, 0); ID3D11DeviceContext_Dispatch(context, 16, 1, 1); data = read_uav_counter(context, staging_buffer, uav); ok(!data, "Got unexpected value %u.\n", data); get_buffer_readback(buffer2, &rb); memcpy(id, rb.map_desc.pData, 64 * sizeof(*id)); release_resource_readback(&rb); qsort(id, 64, sizeof(*id), compare_id); for (i = 0; i < 64; ++i) { if (id[i] != i) break; } ok(i == 64, "Got unexpected id %u at %u.\n", id[i], i); /* produce on CPU */ for (i = 0; i < 8; ++i) id[i] = 0xdeadbeef; set_box(&box, 0, 0, 0, 8 * sizeof(*id), 1, 1); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)buffer, 0, &box, id, 0, 0); data = 8; ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, &data); data = read_uav_counter(context, staging_buffer, uav); ok(data == 8, "Got unexpected value %u.\n", data); /* consume */ ID3D11DeviceContext_Dispatch(context, 1, 1, 1); data = read_uav_counter(context, staging_buffer, uav); ok(data == 4, "Got unexpected value %u.\n", data); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); data = read_uav_counter(context, staging_buffer, uav); ok(!data, "Got unexpected value %u.\n", data); get_buffer_readback(buffer2, &rb); for (i = 0; i < 8; ++i) { data = get_readback_color(&rb, i, 0, 0); ok(data == 0xdeadbeef, "Got data %u at %u.\n", data, i); } release_resource_readback(&rb); ID3D11Buffer_Release(buffer); ID3D11Buffer_Release(buffer2); ID3D11Buffer_Release(staging_buffer); ID3D11ComputeShader_Release(cs_producer); ID3D11ComputeShader_Release(cs_consumer); ID3D11UnorderedAccessView_Release(uav); ID3D11UnorderedAccessView_Release(uav2); release_test_context(&test_context); } static void test_dispatch_indirect(void) { struct stats { unsigned int dispatch_count; unsigned int thread_count; unsigned int max_x; unsigned int max_y; unsigned int max_z; }; ID3D11Buffer *append_buffer, *stats_buffer, *args_buffer, *staging_buffer; ID3D11UnorderedAccessView *uav, *stats_uav; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; ID3D11ComputeShader *cs_append, *cs_stats; struct d3d11_test_context test_context; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Device *device; unsigned int data, i; struct stats *stats; HRESULT hr; static const DWORD cs_append_code[] = { #if 0 struct dispatch_args { uint x, y, z; }; AppendStructuredBuffer u; [numthreads(1, 1, 1)] void main() { dispatch_args args = {4, 2, 1}; u.Append(args); args.y = 1; u.Append(args); args.x = 3; u.Append(args); } #endif 0x43425844, 0x954de75a, 0x8bb1b78b, 0x84ded464, 0x9d9532b7, 0x00000001, 0x00000158, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000104, 0x00050050, 0x00000041, 0x0100086a, 0x0400009e, 0x0011e000, 0x00000000, 0x0000000c, 0x02000068, 0x00000001, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x050000b2, 0x00100012, 0x00000000, 0x0011e000, 0x00000000, 0x0c0000a8, 0x0011e072, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x00004002, 0x00000004, 0x00000002, 0x00000001, 0x00000000, 0x050000b2, 0x00100012, 0x00000000, 0x0011e000, 0x00000000, 0x0c0000a8, 0x0011e072, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x00004002, 0x00000004, 0x00000001, 0x00000001, 0x00000000, 0x050000b2, 0x00100012, 0x00000000, 0x0011e000, 0x00000000, 0x0c0000a8, 0x0011e072, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x00004002, 0x00000003, 0x00000001, 0x00000001, 0x00000000, 0x0100003e, }; static const DWORD cs_stats_code[] = { #if 0 struct stats { uint dispatch_count; uint thread_count; uint max_x; uint max_y; uint max_z; }; RWStructuredBuffer u; [numthreads(1, 1, 1)] void main(uint3 id : SV_DispatchThreadID) { if (all(!id)) InterlockedAdd(u[0].dispatch_count, 1); InterlockedAdd(u[0].thread_count, 1); InterlockedMax(u[0].max_x, id.x); InterlockedMax(u[0].max_y, id.y); InterlockedMax(u[0].max_z, id.z); } #endif 0x43425844, 0xbd3f2e4e, 0xb0f61ff7, 0xa8e10584, 0x2f61aec9, 0x00000001, 0x000001bc, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000168, 0x00050050, 0x0000005a, 0x0100086a, 0x0400009e, 0x0011e000, 0x00000000, 0x00000014, 0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x09000020, 0x00100072, 0x00000000, 0x00020246, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010002a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a, 0x00000000, 0x0a0000ad, 0x0011e000, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004001, 0x00000001, 0x01000015, 0x0a0000ad, 0x0011e000, 0x00000000, 0x00004002, 0x00000000, 0x00000004, 0x00000000, 0x00000000, 0x00004001, 0x00000001, 0x090000b0, 0x0011e000, 0x00000000, 0x00004002, 0x00000000, 0x00000008, 0x00000000, 0x00000000, 0x0002000a, 0x090000b0, 0x0011e000, 0x00000000, 0x00004002, 0x00000000, 0x0000000c, 0x00000000, 0x00000000, 0x0002001a, 0x090000b0, 0x0011e000, 0x00000000, 0x00004002, 0x00000000, 0x00000010, 0x00000000, 0x00000000, 0x0002002a, 0x0100003e, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const unsigned int zero[4] = {0, 0, 0, 0}; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateComputeShader(device, cs_append_code, sizeof(cs_append_code), NULL, &cs_append); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); hr = ID3D11Device_CreateComputeShader(device, cs_stats_code, sizeof(cs_stats_code), NULL, &cs_stats); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); memset(&buffer_desc, 0, sizeof(buffer_desc)); buffer_desc.ByteWidth = sizeof(unsigned int); buffer_desc.Usage = D3D11_USAGE_STAGING; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &staging_buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); buffer_desc.ByteWidth = 60; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; buffer_desc.StructureByteStride = 3 * sizeof(unsigned int); hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &append_buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_UNKNOWN; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 5; U(uav_desc).Buffer.Flags = D3D11_BUFFER_UAV_FLAG_APPEND; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)append_buffer, &uav_desc, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); /* We use a separate buffer because D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS * and D3D11_RESOURCE_MISC_BUFFER_STRUCTURED are mutually exclusive flags. */ buffer_desc.BindFlags = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &args_buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); buffer_desc.ByteWidth = sizeof(*stats); buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; buffer_desc.StructureByteStride = sizeof(*stats); hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &stats_buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)stats_buffer, NULL, &stats_uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); data = read_uav_counter(context, staging_buffer, uav); ok(!data, "Got unexpected initial value %u.\n", data); data = 8; ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, &data); data = read_uav_counter(context, staging_buffer, uav); ok(data == 8, "Got unexpected value %u.\n", data); ID3D11DeviceContext_CSSetShader(context, cs_append, NULL, 0); data = 0; ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, &data); ID3D11DeviceContext_Dispatch(context, 1, 1, 1); data = read_uav_counter(context, staging_buffer, uav); ok(data == 3, "Got unexpected value %u.\n", data); ID3D11DeviceContext_CopyResource(context, (ID3D11Resource *)args_buffer, (ID3D11Resource *)append_buffer); ID3D11DeviceContext_CSSetShader(context, cs_stats, NULL, 0); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, stats_uav, zero); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &stats_uav, NULL); data = read_uav_counter(context, staging_buffer, uav); for (i = 0; i < data; ++i) ID3D11DeviceContext_DispatchIndirect(context, args_buffer, i * 3 * sizeof(unsigned int)); get_buffer_readback(stats_buffer, &rb); stats = rb.map_desc.pData; ok(stats->dispatch_count == 3, "Got unexpected dispatch count %u.\n", stats->dispatch_count); ok(stats->thread_count == 15, "Got unexpected thread count %u.\n", stats->thread_count); ok(stats->max_x == 3, "Got unexpected max x %u.\n", stats->max_x); ok(stats->max_y == 1, "Got unexpected max y %u.\n", stats->max_y); ok(stats->max_z == 0, "Got unexpected max z %u.\n", stats->max_z); release_resource_readback(&rb); ID3D11Buffer_Release(append_buffer); ID3D11Buffer_Release(args_buffer); ID3D11Buffer_Release(staging_buffer); ID3D11Buffer_Release(stats_buffer); ID3D11ComputeShader_Release(cs_append); ID3D11ComputeShader_Release(cs_stats); ID3D11UnorderedAccessView_Release(uav); ID3D11UnorderedAccessView_Release(stats_uav); release_test_context(&test_context); } static void test_compute_shader_registers(void) { struct data { unsigned int group_id[3]; unsigned int group_index; unsigned int dispatch_id[3]; unsigned int thread_id[3]; }; struct d3d11_test_context test_context; unsigned int i, x, y, group_x, group_y; ID3D11UnorderedAccessView *uav; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Buffer *cb, *buffer; struct uvec4 dimensions; ID3D11ComputeShader *cs; const struct data *data; ID3D11Device *device; HRESULT hr; static const DWORD cs_code[] = { #if 0 struct data { uint3 group_id; uint group_index; uint3 dispatch_id; uint3 group_thread_id; }; RWStructuredBuffer u; uint2 dim; [numthreads(3, 2, 1)] void main(uint3 group_id : SV_GroupID, uint group_index : SV_GroupIndex, uint3 dispatch_id : SV_DispatchThreadID, uint3 group_thread_id : SV_GroupThreadID) { uint i = dispatch_id.x + dispatch_id.y * 3 * dim.x; u[i].group_id = group_id; u[i].group_index = group_index; u[i].dispatch_id = dispatch_id; u[i].group_thread_id = group_thread_id; } #endif 0x43425844, 0xf0bce218, 0xfc1e8267, 0xe6d57544, 0x342df592, 0x00000001, 0x000001a4, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000150, 0x00050050, 0x00000054, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0400009e, 0x0011e000, 0x00000000, 0x00000028, 0x0200005f, 0x00024000, 0x0200005f, 0x00021072, 0x0200005f, 0x00022072, 0x0200005f, 0x00020072, 0x02000068, 0x00000002, 0x0400009b, 0x00000003, 0x00000002, 0x00000001, 0x04000036, 0x00100072, 0x00000000, 0x00021246, 0x04000036, 0x00100082, 0x00000000, 0x0002400a, 0x08000026, 0x0000d000, 0x00100012, 0x00000001, 0x0002001a, 0x0020800a, 0x00000000, 0x00000000, 0x08000023, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000003, 0x0002000a, 0x090000a8, 0x0011e0f2, 0x00000000, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x00100e46, 0x00000000, 0x04000036, 0x00100072, 0x00000000, 0x00020246, 0x04000036, 0x00100082, 0x00000000, 0x0002200a, 0x090000a8, 0x0011e0f2, 0x00000000, 0x0010000a, 0x00000001, 0x00004001, 0x00000010, 0x00100e46, 0x00000000, 0x080000a8, 0x0011e032, 0x00000000, 0x0010000a, 0x00000001, 0x00004001, 0x00000020, 0x00022596, 0x0100003e, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; buffer_desc.ByteWidth = 10240; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; buffer_desc.StructureByteStride = 40; assert(sizeof(struct data) == buffer_desc.StructureByteStride); hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, NULL, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(dimensions), NULL); hr = ID3D11Device_CreateComputeShader(device, cs_code, sizeof(cs_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_CSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); dimensions.x = 2; dimensions.y = 3; dimensions.z = 1; dimensions.w = 0; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &dimensions, 0, 0); ID3D11DeviceContext_Dispatch(context, dimensions.x, dimensions.y, dimensions.z); get_buffer_readback(buffer, &rb); i = 0; data = rb.map_desc.pData; for (y = 0; y < dimensions.y; ++y) { for (group_y = 0; group_y < 2; ++group_y) { for (x = 0; x < dimensions.x; ++x) { for (group_x = 0; group_x < 3; ++group_x) { const unsigned int dispatch_id[2] = {x * 3 + group_x, y * 2 + group_y}; const unsigned int group_index = group_y * 3 + group_x; const struct data *d = &data[i]; ok(d->group_id[0] == x && d->group_id[1] == y && !d->group_id[2], "Got group id (%u, %u, %u), expected (%u, %u, %u) at %u (%u, %u, %u, %u).\n", d->group_id[0], d->group_id[1], d->group_id[2], x, y, 0, i, x, y, group_x, group_y); ok(d->group_index == group_index, "Got group index %u, expected %u at %u (%u, %u, %u, %u).\n", d->group_index, group_index, i, x, y, group_x, group_y); ok(d->dispatch_id[0] == dispatch_id[0] && d->dispatch_id[1] == dispatch_id[1] && !d->dispatch_id[2], "Got dispatch id (%u, %u, %u), expected (%u, %u, %u) " "at %u (%u, %u, %u, %u).\n", d->dispatch_id[0], d->dispatch_id[1], d->dispatch_id[2], dispatch_id[0], dispatch_id[1], 0, i, x, y, group_x, group_y); ok(d->thread_id[0] == group_x && d->thread_id[1] == group_y && !d->thread_id[2], "Got group thread id (%u, %u, %u), expected (%u, %u, %u) " "at %u (%u, %u, %u, %u).\n", d->thread_id[0], d->thread_id[1], d->thread_id[2], group_x, group_y, 0, i, x, y, group_x, group_y); ++i; } } } } release_resource_readback(&rb); ID3D11Buffer_Release(cb); ID3D11Buffer_Release(buffer); ID3D11ComputeShader_Release(cs); ID3D11UnorderedAccessView_Release(uav); release_test_context(&test_context); } static void test_tgsm(void) { D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; struct d3d11_test_context test_context; ID3D11UnorderedAccessView *uav, *uav2; struct resource_readback rb, rb2; unsigned int i, data, expected; ID3D11Buffer *buffer, *buffer2; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; ID3D11ComputeShader *cs; ID3D11Device *device; float float_data; HRESULT hr; static const DWORD raw_tgsm_code[] = { #if 0 RWByteAddressBuffer u; groupshared uint m; [numthreads(32, 1, 1)] void main(uint local_idx : SV_GroupIndex, uint group_id : SV_GroupID) { if (!local_idx) m = group_id.x; GroupMemoryBarrierWithGroupSync(); InterlockedAdd(m, group_id.x); GroupMemoryBarrierWithGroupSync(); if (!local_idx) u.Store(4 * group_id.x, m); } #endif 0x43425844, 0x467df6d9, 0x5f56edda, 0x5c96b787, 0x60c91fb8, 0x00000001, 0x00000148, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000f4, 0x00050050, 0x0000003d, 0x0100086a, 0x0300009d, 0x0011e000, 0x00000000, 0x0200005f, 0x00024000, 0x0200005f, 0x00021012, 0x02000068, 0x00000001, 0x0400009f, 0x0011f000, 0x00000000, 0x00000004, 0x0400009b, 0x00000020, 0x00000001, 0x00000001, 0x0200001f, 0x0002400a, 0x060000a6, 0x0011f012, 0x00000000, 0x00004001, 0x00000000, 0x0002100a, 0x01000015, 0x010018be, 0x060000ad, 0x0011f000, 0x00000000, 0x00004001, 0x00000000, 0x0002100a, 0x010018be, 0x0200001f, 0x0002400a, 0x06000029, 0x00100012, 0x00000000, 0x0002100a, 0x00004001, 0x00000002, 0x070000a5, 0x00100022, 0x00000000, 0x00004001, 0x00000000, 0x0011f006, 0x00000000, 0x070000a6, 0x0011e012, 0x00000000, 0x0010000a, 0x00000000, 0x0010001a, 0x00000000, 0x01000015, 0x0100003e, }; static const DWORD structured_tgsm_code[] = { #if 0 #define GROUP_SIZE 32 RWByteAddressBuffer u; RWByteAddressBuffer u2; groupshared uint m[GROUP_SIZE]; [numthreads(GROUP_SIZE, 1, 1)] void main(uint local_idx : SV_GroupIndex, uint group_id : SV_GroupID) { uint sum, original, i; if (!local_idx) { for (i = 0; i < GROUP_SIZE; ++i) m[i] = 2 * group_id.x; } GroupMemoryBarrierWithGroupSync(); InterlockedAdd(m[local_idx], 1); GroupMemoryBarrierWithGroupSync(); for (i = 0, sum = 0; i < GROUP_SIZE; sum += m[i++]); u.InterlockedExchange(4 * group_id.x, sum, original); u2.Store(4 * group_id.x, original); } #endif 0x43425844, 0x9d906c94, 0x81f5ad92, 0x11e860b2, 0x3623c824, 0x00000001, 0x000002c0, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x0000026c, 0x00050050, 0x0000009b, 0x0100086a, 0x0300009d, 0x0011e000, 0x00000000, 0x0300009d, 0x0011e000, 0x00000001, 0x0200005f, 0x00024000, 0x0200005f, 0x00021012, 0x02000068, 0x00000002, 0x050000a0, 0x0011f000, 0x00000000, 0x00000004, 0x00000020, 0x0400009b, 0x00000020, 0x00000001, 0x00000001, 0x0200001f, 0x0002400a, 0x06000029, 0x00100012, 0x00000000, 0x0002100a, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100042, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000020, 0x03040003, 0x0010002a, 0x00000000, 0x090000a8, 0x0011f012, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x0010000a, 0x00000000, 0x0700001e, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x01000015, 0x010018be, 0x04000036, 0x00100012, 0x00000000, 0x0002400a, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0x00000000, 0x070000ad, 0x0011f000, 0x00000000, 0x00100046, 0x00000000, 0x00004001, 0x00000001, 0x010018be, 0x08000036, 0x00100032, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x07000050, 0x00100042, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000020, 0x03040003, 0x0010002a, 0x00000000, 0x0700001e, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x00004001, 0x00000001, 0x090000a7, 0x00100042, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x0011f006, 0x00000000, 0x0700001e, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0010002a, 0x00000000, 0x05000036, 0x00100032, 0x00000000, 0x00100046, 0x00000001, 0x01000016, 0x06000029, 0x00100022, 0x00000000, 0x0002100a, 0x00004001, 0x00000002, 0x090000b8, 0x00100012, 0x00000001, 0x0011e000, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x070000a6, 0x0011e012, 0x00000001, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0100003e, }; static const DWORD structured_tgsm_float_code[] = { #if 0 #define GROUP_SIZE 32 struct data { float f; uint u; }; RWBuffer u; RWBuffer u2; groupshared data m[GROUP_SIZE]; [numthreads(GROUP_SIZE, 1, 1)] void main(uint local_idx : SV_GroupIndex, uint group_id : SV_GroupID, uint thread_id : SV_DispatchThreadID) { uint i; if (!local_idx) { for (i = 0; i < GROUP_SIZE; ++i) { m[i].f = group_id.x; m[i].u = group_id.x; } } GroupMemoryBarrierWithGroupSync(); for (i = 0; i < local_idx; ++i) { m[local_idx].f += group_id.x; m[local_idx].u += group_id.x; } u[thread_id.x] = m[local_idx].f; u2[thread_id.x] = m[local_idx].u; } #endif 0x43425844, 0xaadf1a71, 0x16f60224, 0x89b6ce76, 0xb66fb96f, 0x00000001, 0x000002ac, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000258, 0x00050050, 0x00000096, 0x0100086a, 0x0400089c, 0x0011e000, 0x00000000, 0x00005555, 0x0400089c, 0x0011e000, 0x00000001, 0x00004444, 0x0200005f, 0x00024000, 0x0200005f, 0x00021012, 0x0200005f, 0x00020012, 0x02000068, 0x00000002, 0x050000a0, 0x0011f000, 0x00000000, 0x00000008, 0x00000020, 0x0400009b, 0x00000020, 0x00000001, 0x00000001, 0x0200001f, 0x0002400a, 0x04000056, 0x00100012, 0x00000000, 0x0002100a, 0x04000036, 0x00100022, 0x00000000, 0x0002100a, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100082, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000020, 0x03040003, 0x0010003a, 0x00000000, 0x090000a8, 0x0011f032, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x00100046, 0x00000000, 0x0700001e, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x01000015, 0x010018be, 0x04000056, 0x00100012, 0x00000000, 0x0002100a, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x06000050, 0x00100042, 0x00000000, 0x0010001a, 0x00000000, 0x0002400a, 0x03040003, 0x0010002a, 0x00000000, 0x080000a7, 0x001000c2, 0x00000000, 0x0002400a, 0x00004001, 0x00000000, 0x0011f406, 0x00000000, 0x07000000, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0010002a, 0x00000000, 0x0600001e, 0x00100022, 0x00000001, 0x0010003a, 0x00000000, 0x0002100a, 0x080000a8, 0x0011f032, 0x00000000, 0x0002400a, 0x00004001, 0x00000000, 0x00100046, 0x00000001, 0x0700001e, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x080000a7, 0x00100032, 0x00000000, 0x0002400a, 0x00004001, 0x00000000, 0x0011f046, 0x00000000, 0x060000a4, 0x0011e0f2, 0x00000000, 0x00020006, 0x00100006, 0x00000000, 0x060000a4, 0x0011e0f2, 0x00000001, 0x00020006, 0x00100556, 0x00000000, 0x0100003e, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const unsigned int zero[4] = {0}; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; buffer_desc.ByteWidth = 1024; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = buffer_desc.ByteWidth / sizeof(unsigned int); U(uav_desc).Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateComputeShader(device, raw_tgsm_code, sizeof(raw_tgsm_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, zero); ID3D11DeviceContext_Dispatch(context, 64, 1, 1); get_buffer_readback(buffer, &rb); for (i = 0; i < 64; ++i) { data = get_readback_color(&rb, i, 0, 0); expected = 33 * i; ok(data == expected, "Got %u, expected %u (index %u).\n", data, expected, i); } release_resource_readback(&rb); ID3D11Buffer_Release(buffer); ID3D11ComputeShader_Release(cs); ID3D11UnorderedAccessView_Release(uav); hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer2); ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer2, &uav_desc, &uav2); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateComputeShader(device, structured_tgsm_code, sizeof(structured_tgsm_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 1, 1, &uav2, NULL); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, zero); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav2, zero); ID3D11DeviceContext_Dispatch(context, 32, 1, 1); get_buffer_readback(buffer, &rb); get_buffer_readback(buffer2, &rb2); for (i = 0; i < 32; ++i) { expected = 64 * i + 32; data = get_readback_color(&rb, i, 0, 0); ok(data == expected, "Got %u, expected %u (index %u).\n", data, expected, i); data = get_readback_color(&rb2, i, 0, 0); ok(data == expected || !data, "Got %u, expected %u (index %u).\n", data, expected, i); } release_resource_readback(&rb); release_resource_readback(&rb2); ID3D11Buffer_Release(buffer); ID3D11Buffer_Release(buffer2); ID3D11ComputeShader_Release(cs); ID3D11UnorderedAccessView_Release(uav); ID3D11UnorderedAccessView_Release(uav2); buffer_desc.MiscFlags = 0; U(uav_desc).Buffer.Flags = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_R32_FLOAT; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer2); ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_R32_UINT; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer2, &uav_desc, &uav2); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreateComputeShader(device, structured_tgsm_float_code, sizeof(structured_tgsm_float_code), NULL, &cs); ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, NULL); ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 1, 1, &uav2, NULL); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, zero); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav2, zero); ID3D11DeviceContext_Dispatch(context, 3, 1, 1); get_buffer_readback(buffer, &rb); get_buffer_readback(buffer2, &rb2); for (i = 0; i < 96; ++i) { expected = (i % 32 + 1) * (i / 32); float_data = get_readback_float(&rb, i, 0); ok(float_data == expected, "Got %.8e, expected %u (index %u).\n", float_data, expected, i); data = get_readback_color(&rb2, i, 0, 0); ok(data == expected, "Got %u, expected %u (index %u).\n", data, expected, i); } release_resource_readback(&rb); release_resource_readback(&rb2); ID3D11Buffer_Release(buffer); ID3D11Buffer_Release(buffer2); ID3D11ComputeShader_Release(cs); ID3D11UnorderedAccessView_Release(uav); ID3D11UnorderedAccessView_Release(uav2); release_test_context(&test_context); } static void test_geometry_shader(void) { static const struct { struct vec4 position; unsigned int color; } vertex[] = { {{0.0f, 0.0f, 1.0f, 1.0f}, 0xffffff00}, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"SV_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; #if 0 struct vs_data { float4 pos : SV_POSITION; float4 color : COLOR; }; void main(in struct vs_data vs_input, out struct vs_data vs_output) { vs_output.pos = vs_input.pos; vs_output.color = vs_input.color; } #endif static const DWORD vs_code[] = { 0x43425844, 0xd5b32785, 0x35332906, 0x4d05e031, 0xf66a58af, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; #if 0 struct gs_data { float4 pos : SV_POSITION; float4 color : COLOR; }; [maxvertexcount(4)] void main(point struct gs_data vin[1], inout TriangleStream vout) { float offset = 0.2 * vin[0].pos.w; gs_data v; v.color = vin[0].color; v.pos = float4(vin[0].pos.x - offset, vin[0].pos.y - offset, vin[0].pos.z, 1.0); vout.Append(v); v.pos = float4(vin[0].pos.x - offset, vin[0].pos.y + offset, vin[0].pos.z, 1.0); vout.Append(v); v.pos = float4(vin[0].pos.x + offset, vin[0].pos.y - offset, vin[0].pos.z, 1.0); vout.Append(v); v.pos = float4(vin[0].pos.x + offset, vin[0].pos.y + offset, vin[0].pos.z, 1.0); vout.Append(v); } #endif static const DWORD gs_code[] = { 0x43425844, 0x70616045, 0x96756e1f, 0x1caeecb8, 0x3749528c, 0x00000001, 0x0000034c, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000270, 0x00020040, 0x0000009c, 0x05000061, 0x002010f2, 0x00000001, 0x00000000, 0x00000001, 0x0400005f, 0x002010f2, 0x00000001, 0x00000001, 0x02000068, 0x00000001, 0x0100085d, 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x0200005e, 0x00000004, 0x0f000032, 0x00100032, 0x00000000, 0x80201ff6, 0x00000041, 0x00000000, 0x00000000, 0x00004002, 0x3e4ccccd, 0x3e4ccccd, 0x00000000, 0x00000000, 0x00201046, 0x00000000, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000000, 0x06000036, 0x00102042, 0x00000000, 0x0020102a, 0x00000000, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x3f800000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x01000013, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0e000032, 0x00100052, 0x00000000, 0x00201ff6, 0x00000000, 0x00000000, 0x00004002, 0x3e4ccccd, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00201106, 0x00000000, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010002a, 0x00000000, 0x06000036, 0x00102042, 0x00000000, 0x0020102a, 0x00000000, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x3f800000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x01000013, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010001a, 0x00000000, 0x06000036, 0x00102042, 0x00000000, 0x0020102a, 0x00000000, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x3f800000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x01000013, 0x05000036, 0x00102032, 0x00000000, 0x00100086, 0x00000000, 0x06000036, 0x00102042, 0x00000000, 0x0020102a, 0x00000000, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x3f800000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x01000013, 0x0100003e, }; static const DWORD gs_5_0_code[] = { 0x43425844, 0x57251c23, 0x4971d115, 0x8fee0b13, 0xba149ea1, 0x00000001, 0x00000384, 0x00000003, 0x0000002c, 0x00000080, 0x000000dc, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x3547534f, 0x00000054, 0x00000002, 0x00000008, 0x00000000, 0x00000040, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000000, 0x0000004c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x58454853, 0x000002a0, 0x00020050, 0x000000a8, 0x0100086a, 0x05000061, 0x002010f2, 0x00000001, 0x00000000, 0x00000001, 0x0400005f, 0x002010f2, 0x00000001, 0x00000001, 0x02000068, 0x00000001, 0x0100085d, 0x0300008f, 0x00110000, 0x00000000, 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x0200005e, 0x00000004, 0x0f000032, 0x00100032, 0x00000000, 0x80201ff6, 0x00000041, 0x00000000, 0x00000000, 0x00004002, 0x3e4ccccd, 0x3e4ccccd, 0x00000000, 0x00000000, 0x00201046, 0x00000000, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000000, 0x06000036, 0x00102042, 0x00000000, 0x0020102a, 0x00000000, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x3f800000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x03000075, 0x00110000, 0x00000000, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0e000032, 0x00100052, 0x00000000, 0x00201ff6, 0x00000000, 0x00000000, 0x00004002, 0x3e4ccccd, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00201106, 0x00000000, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010002a, 0x00000000, 0x06000036, 0x00102042, 0x00000000, 0x0020102a, 0x00000000, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x3f800000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x03000075, 0x00110000, 0x00000000, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x05000036, 0x00102022, 0x00000000, 0x0010001a, 0x00000000, 0x06000036, 0x00102042, 0x00000000, 0x0020102a, 0x00000000, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x3f800000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x03000075, 0x00110000, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00100086, 0x00000000, 0x06000036, 0x00102042, 0x00000000, 0x0020102a, 0x00000000, 0x00000000, 0x05000036, 0x00102082, 0x00000000, 0x00004001, 0x3f800000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x03000075, 0x00110000, 0x00000000, 0x0100003e, }; #if 0 struct ps_data { float4 pos : SV_POSITION; float4 color : COLOR; }; float4 main(struct ps_data ps_input) : SV_Target { return ps_input.color; } #endif static const DWORD ps_code[] = { 0x43425844, 0x89803e59, 0x3f798934, 0xf99181df, 0xf5556512, 0x00000001, 0x000000f4, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const float red[] = {1.0f, 0.0f, 0.0f, 1.0f}; struct d3d11_test_context test_context; ID3D11InputLayout *input_layout; ID3D11DeviceContext *context; unsigned int stride, offset; struct resource_readback rb; ID3D11GeometryShader *gs; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *vb; DWORD color; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(vertex), vertex); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); if (ID3D11Device_GetFeatureLevel(device) >= D3D_FEATURE_LEVEL_11_0) hr = ID3D11Device_CreateGeometryShader(device, gs_5_0_code, sizeof(gs_5_0_code), NULL, &gs); else hr = ID3D11Device_CreateGeometryShader(device, gs_code, sizeof(gs_code), NULL, &gs); ok(SUCCEEDED(hr), "Failed to create geometry shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); stride = sizeof(*vertex); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, &stride, &offset); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); ID3D11DeviceContext_Draw(context, 1, 0); get_texture_readback(test_context.backbuffer, 0, &rb); color = get_readback_color(&rb, 320, 190, 0); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 255, 240, 0); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 320, 240, 0); ok(compare_color(color, 0xffffff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 385, 240, 0); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 320, 290, 0); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); release_resource_readback(&rb); ID3D11PixelShader_Release(ps); ID3D11GeometryShader_Release(gs); ID3D11VertexShader_Release(vs); ID3D11Buffer_Release(vb); ID3D11InputLayout_Release(input_layout); release_test_context(&test_context); } struct triangle { struct vec4 v[3]; }; #define check_triangles(buffer, triangles, count) check_triangles_(__LINE__, buffer, triangles, count) static void check_triangles_(unsigned int line, ID3D11Buffer *buffer, const struct triangle *triangles, unsigned int triangle_count) { const struct triangle *current, *expected; struct resource_readback rb; unsigned int i, j, offset; BOOL all_match = TRUE; get_buffer_readback(buffer, &rb); for (i = 0; i < triangle_count; ++i) { current = get_readback_data(&rb, i, 0, 0, sizeof(*current)); expected = &triangles[i]; offset = ~0u; for (j = 0; j < ARRAY_SIZE(expected->v); ++j) { if (compare_vec4(¤t->v[0], &expected->v[j], 0)) { offset = j; break; } } if (offset == ~0u) { all_match = FALSE; break; } for (j = 0; j < ARRAY_SIZE(expected->v); ++j) { if (!compare_vec4(¤t->v[j], &expected->v[(j + offset) % 3], 0)) { all_match = FALSE; break; } } if (!all_match) break; } ok_(__FILE__, line)(all_match, "Triangle %u vertices {%.8e, %.8e, %.8e, %.8e}, " "{%.8e, %.8e, %.8e, %.8e}, {%.8e, %.8e, %.8e, %.8e} " "do not match {%.8e, %.8e, %.8e, %.8e}, {%.8e, %.8e, %.8e, %.8e}, " "{%.8e, %.8e, %.8e, %.8e}.\n", i, current->v[0].x, current->v[0].y, current->v[0].z, current->v[0].w, current->v[1].x, current->v[1].y, current->v[1].z, current->v[1].w, current->v[2].x, current->v[2].y, current->v[2].z, current->v[2].w, expected->v[0].x, expected->v[0].y, expected->v[0].z, expected->v[0].w, expected->v[1].x, expected->v[1].y, expected->v[1].z, expected->v[1].w, expected->v[2].x, expected->v[2].y, expected->v[2].z, expected->v[2].w); release_resource_readback(&rb); } static void test_quad_tessellation(void) { #if 0 struct point_data { float4 position : SV_POSITION; }; struct patch_constant_data { float edges[4] : SV_TessFactor; float inside[2] : SV_InsideTessFactor; }; float4 tess_factors; float2 inside_tess_factors; patch_constant_data patch_constant(InputPatch input) { patch_constant_data output; output.edges[0] = tess_factors.x; output.edges[1] = tess_factors.y; output.edges[2] = tess_factors.z; output.edges[3] = tess_factors.w; output.inside[0] = inside_tess_factors.x; output.inside[1] = inside_tess_factors.y; return output; } [domain("quad")] [outputcontrolpoints(4)] [outputtopology("triangle_ccw")] [partitioning("integer")] [patchconstantfunc("patch_constant")] point_data hs_main(InputPatch input, uint i : SV_OutputControlPointID) { return input[i]; } [domain("quad")] point_data ds_main(patch_constant_data input, float2 tess_coord : SV_DomainLocation, const OutputPatch patch) { point_data output; float4 a = lerp(patch[0].position, patch[1].position, tess_coord.x); float4 b = lerp(patch[2].position, patch[3].position, tess_coord.x); output.position = lerp(a, b, tess_coord.y); return output; } #endif static const DWORD hs_quad_ccw_code[] = { 0x43425844, 0xdf8df700, 0x58b08fb1, 0xbd23d2c3, 0xcf884094, 0x00000001, 0x000002b8, 0x00000004, 0x00000030, 0x00000064, 0x00000098, 0x0000015c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x47534350, 0x000000bc, 0x00000006, 0x00000008, 0x00000098, 0x00000000, 0x0000000b, 0x00000003, 0x00000000, 0x00000e01, 0x00000098, 0x00000001, 0x0000000b, 0x00000003, 0x00000001, 0x00000e01, 0x00000098, 0x00000002, 0x0000000b, 0x00000003, 0x00000002, 0x00000e01, 0x00000098, 0x00000003, 0x0000000b, 0x00000003, 0x00000003, 0x00000e01, 0x000000a6, 0x00000000, 0x0000000c, 0x00000003, 0x00000004, 0x00000e01, 0x000000a6, 0x00000001, 0x0000000c, 0x00000003, 0x00000005, 0x00000e01, 0x545f5653, 0x46737365, 0x6f746361, 0x56530072, 0x736e495f, 0x54656469, 0x46737365, 0x6f746361, 0xabab0072, 0x58454853, 0x00000154, 0x00030050, 0x00000055, 0x01000071, 0x01002093, 0x01002094, 0x01001895, 0x01000896, 0x01002097, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x01000073, 0x04000067, 0x00102012, 0x00000000, 0x0000000b, 0x06000036, 0x00102012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000001, 0x0000000c, 0x06000036, 0x00102012, 0x00000001, 0x0020801a, 0x00000000, 0x00000000, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000002, 0x0000000d, 0x06000036, 0x00102012, 0x00000002, 0x0020802a, 0x00000000, 0x00000000, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000003, 0x0000000e, 0x06000036, 0x00102012, 0x00000003, 0x0020803a, 0x00000000, 0x00000000, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000004, 0x0000000f, 0x06000036, 0x00102012, 0x00000004, 0x0020800a, 0x00000000, 0x00000001, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000005, 0x00000010, 0x06000036, 0x00102012, 0x00000005, 0x0020801a, 0x00000000, 0x00000001, 0x0100003e, }; static const DWORD ds_quad_code[] = { 0x43425844, 0xeb6b7631, 0x07f5469e, 0xed0cbf4a, 0x7158b3a6, 0x00000001, 0x00000284, 0x00000004, 0x00000030, 0x00000064, 0x00000128, 0x0000015c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x47534350, 0x000000bc, 0x00000006, 0x00000008, 0x00000098, 0x00000000, 0x0000000b, 0x00000003, 0x00000000, 0x00000001, 0x00000098, 0x00000001, 0x0000000b, 0x00000003, 0x00000001, 0x00000001, 0x00000098, 0x00000002, 0x0000000b, 0x00000003, 0x00000002, 0x00000001, 0x00000098, 0x00000003, 0x0000000b, 0x00000003, 0x00000003, 0x00000001, 0x000000a6, 0x00000000, 0x0000000c, 0x00000003, 0x00000004, 0x00000001, 0x000000a6, 0x00000001, 0x0000000c, 0x00000003, 0x00000005, 0x00000001, 0x545f5653, 0x46737365, 0x6f746361, 0x56530072, 0x736e495f, 0x54656469, 0x46737365, 0x6f746361, 0xabab0072, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x58454853, 0x00000120, 0x00040050, 0x00000048, 0x01002093, 0x01001895, 0x0100086a, 0x0200005f, 0x0001c032, 0x0400005f, 0x002190f2, 0x00000004, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x02000068, 0x00000002, 0x0a000000, 0x001000f2, 0x00000000, 0x80219e46, 0x00000041, 0x00000002, 0x00000000, 0x00219e46, 0x00000003, 0x00000000, 0x09000032, 0x001000f2, 0x00000000, 0x0001c006, 0x00100e46, 0x00000000, 0x00219e46, 0x00000002, 0x00000000, 0x0a000000, 0x001000f2, 0x00000001, 0x80219e46, 0x00000041, 0x00000000, 0x00000000, 0x00219e46, 0x00000001, 0x00000000, 0x09000032, 0x001000f2, 0x00000001, 0x0001c006, 0x00100e46, 0x00000001, 0x00219e46, 0x00000000, 0x00000000, 0x08000000, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x80100e46, 0x00000041, 0x00000001, 0x08000032, 0x001020f2, 0x00000000, 0x0001c556, 0x00100e46, 0x00000000, 0x00100e46, 0x00000001, 0x0100003e, }; #if 0 ... [outputtopology("triangle_cw")] ... #endif static const DWORD hs_quad_cw_code[] = { 0x43425844, 0x1ab30cc8, 0x94174771, 0x61f4cdd0, 0xa287f62c, 0x00000001, 0x000002b8, 0x00000004, 0x00000030, 0x00000064, 0x00000098, 0x0000015c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x47534350, 0x000000bc, 0x00000006, 0x00000008, 0x00000098, 0x00000000, 0x0000000b, 0x00000003, 0x00000000, 0x00000e01, 0x00000098, 0x00000001, 0x0000000b, 0x00000003, 0x00000001, 0x00000e01, 0x00000098, 0x00000002, 0x0000000b, 0x00000003, 0x00000002, 0x00000e01, 0x00000098, 0x00000003, 0x0000000b, 0x00000003, 0x00000003, 0x00000e01, 0x000000a6, 0x00000000, 0x0000000c, 0x00000003, 0x00000004, 0x00000e01, 0x000000a6, 0x00000001, 0x0000000c, 0x00000003, 0x00000005, 0x00000e01, 0x545f5653, 0x46737365, 0x6f746361, 0x56530072, 0x736e495f, 0x54656469, 0x46737365, 0x6f746361, 0xabab0072, 0x58454853, 0x00000154, 0x00030050, 0x00000055, 0x01000071, 0x01002093, 0x01002094, 0x01001895, 0x01000896, 0x01001897, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x01000073, 0x04000067, 0x00102012, 0x00000000, 0x0000000b, 0x06000036, 0x00102012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000001, 0x0000000c, 0x06000036, 0x00102012, 0x00000001, 0x0020801a, 0x00000000, 0x00000000, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000002, 0x0000000d, 0x06000036, 0x00102012, 0x00000002, 0x0020802a, 0x00000000, 0x00000000, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000003, 0x0000000e, 0x06000036, 0x00102012, 0x00000003, 0x0020803a, 0x00000000, 0x00000000, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000004, 0x0000000f, 0x06000036, 0x00102012, 0x00000004, 0x0020800a, 0x00000000, 0x00000001, 0x0100003e, 0x01000073, 0x04000067, 0x00102012, 0x00000005, 0x00000010, 0x06000036, 0x00102012, 0x00000005, 0x0020801a, 0x00000000, 0x00000001, 0x0100003e, }; #if 0 struct point_data { float4 pos : SV_POSITION; }; [maxvertexcount(3)] void main(triangle point_data vin[3], inout TriangleStream vout) { for (uint i = 0; i < 3; ++i) vout.Append(vin[i]); } #endif static const DWORD gs_code[] = { 0x43425844, 0x8e49d18d, 0x6d08d6e5, 0xb7015628, 0xf9351fdd, 0x00000001, 0x00000164, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x000000c8, 0x00020040, 0x00000032, 0x05000061, 0x002010f2, 0x00000003, 0x00000000, 0x00000001, 0x02000068, 0x00000001, 0x0100185d, 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x0200005e, 0x00000003, 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000003, 0x03040003, 0x0010001a, 0x00000000, 0x07000036, 0x001020f2, 0x00000000, 0x00a01e46, 0x0010000a, 0x00000000, 0x00000000, 0x01000013, 0x0700001e, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x0100003e, }; static const D3D11_SO_DECLARATION_ENTRY so_declaration[] = { {0, "SV_POSITION", 0, 0, 4, 0}, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const struct vec4 green = {0.0f, 1.0f, 0.0f, 1.0f}; static const struct vec4 white = {1.0f, 1.0f, 1.0f, 1.0f}; static const BYTE zero_data[1024]; static const struct triangle expected_quad_ccw[] = { {{{-1.0f, -1.0f, 0.0f, 1.0f}, { 1.0f, -1.0f, 0.0f, 1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f}}}, {{{-1.0f, 1.0f, 0.0f, 1.0f}, { 1.0f, -1.0f, 0.0f, 1.0f}, { 1.0f, 1.0f, 0.0f, 1.0f}}}, {{{ 0.0f, 0.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 0.0f, 0.0f}}}, }; static const struct triangle expected_quad_cw[] = { {{{-1.0f, -1.0f, 0.0f, 1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f}, { 1.0f, -1.0f, 0.0f, 1.0f}}}, {{{-1.0f, 1.0f, 0.0f, 1.0f}, { 1.0f, 1.0f, 0.0f, 1.0f}, { 1.0f, -1.0f, 0.0f, 1.0f}}}, {{{ 0.0f, 0.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 0.0f, 0.0f}}}, }; struct { float tess_factors[4]; float inside_tess_factors[2]; DWORD padding[2]; } constant; D3D11_QUERY_DATA_SO_STATISTICS so_statistics; struct d3d11_test_context test_context; ID3D11DeviceContext *context; ID3D11Buffer *cb, *so_buffer; D3D11_QUERY_DESC query_desc; ID3D11Asynchronous *query; ID3D11GeometryShader *gs; ID3D11DomainShader *ds; const UINT offset = 0; ID3D11HullShader *hs; ID3D11Device *device; unsigned int i; HRESULT hr; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; draw_color_quad(&test_context, &white); check_texture_color(test_context.backbuffer, 0xffffffff, 0); set_quad_color(&test_context, &green); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST); so_buffer = create_buffer(device, D3D11_BIND_STREAM_OUTPUT, sizeof(zero_data), zero_data); hr = ID3D11Device_CreateGeometryShaderWithStreamOutput(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, 0, NULL, &gs); ok(SUCCEEDED(hr), "Failed to create geometry shader with stream output, hr %#x.\n", hr); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); for (i = 0; i < ARRAY_SIZE(constant.tess_factors); ++i) constant.tess_factors[i] = 1.0f; for (i = 0; i < ARRAY_SIZE(constant.inside_tess_factors); ++i) constant.inside_tess_factors[i] = 1.0f; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constant), &constant); ID3D11DeviceContext_HSSetConstantBuffers(context, 0, 1, &cb); hr = ID3D11Device_CreateHullShader(device, hs_quad_ccw_code, sizeof(hs_quad_ccw_code), NULL, &hs); ok(SUCCEEDED(hr), "Failed to create hull shader, hr %#x.\n", hr); ID3D11DeviceContext_HSSetShader(context, hs, NULL, 0); hr = ID3D11Device_CreateDomainShader(device, ds_quad_code, sizeof(ds_quad_code), NULL, &ds); ok(SUCCEEDED(hr), "Failed to create domain shader, hr %#x.\n", hr); ID3D11DeviceContext_DSSetShader(context, ds, NULL, 0); ID3D11DeviceContext_SOSetTargets(context, 1, &so_buffer, &offset); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(test_context.backbuffer, 0xffffffff, 0); ID3D11DeviceContext_SOSetTargets(context, 0, NULL, NULL); check_triangles(so_buffer, expected_quad_ccw, ARRAY_SIZE(expected_quad_ccw)); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)so_buffer, 0, NULL, zero_data, 0, 0); ID3D11HullShader_Release(hs); hr = ID3D11Device_CreateHullShader(device, hs_quad_cw_code, sizeof(hs_quad_cw_code), NULL, &hs); ok(SUCCEEDED(hr), "Failed to create hull shader, hr %#x.\n", hr); ID3D11DeviceContext_HSSetShader(context, hs, NULL, 0); ID3D11DeviceContext_SOSetTargets(context, 1, &so_buffer, &offset); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); ID3D11DeviceContext_SOSetTargets(context, 0, NULL, NULL); check_triangles(so_buffer, expected_quad_cw, ARRAY_SIZE(expected_quad_cw)); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)so_buffer, 0, NULL, zero_data, 0, 0); ID3D11DeviceContext_SOSetTargets(context, 1, &so_buffer, &offset); query_desc.Query = D3D11_QUERY_SO_STATISTICS_STREAM0; query_desc.MiscFlags = 0; hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)&query); ok(hr == S_OK, "Failed to create query, hr %#x.\n", hr); ID3D11DeviceContext_Begin(context, query); set_quad_color(&test_context, &white); for (i = 0; i < ARRAY_SIZE(constant.tess_factors); ++i) constant.tess_factors[i] = 2.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(test_context.backbuffer, 0xffffffff, 0); set_quad_color(&test_context, &green); constant.tess_factors[0] = 0.0f; /* A patch is discarded. */ ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(test_context.backbuffer, 0xffffffff, 0); ID3D11DeviceContext_End(context, query); get_query_data(context, query, &so_statistics, sizeof(so_statistics)); ok(so_statistics.NumPrimitivesWritten == 8, "Got unexpected primitives written %u.\n", (unsigned int)so_statistics.NumPrimitivesWritten); ok(so_statistics.PrimitivesStorageNeeded == 8, "Got unexpected primitives storage needed %u.\n", (unsigned int)so_statistics.PrimitivesStorageNeeded); ID3D11DeviceContext_Begin(context, query); constant.tess_factors[0] = 5.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); ID3D11DeviceContext_End(context, query); get_query_data(context, query, &so_statistics, sizeof(so_statistics)); ok(so_statistics.NumPrimitivesWritten == 11, "Got unexpected primitives written %u.\n", (unsigned int)so_statistics.NumPrimitivesWritten); ok(so_statistics.PrimitivesStorageNeeded == 11, "Got unexpected primitives storage needed %u.\n", (unsigned int)so_statistics.PrimitivesStorageNeeded); ID3D11Asynchronous_Release(query); ID3D11Buffer_Release(so_buffer); ID3D11GeometryShader_Release(gs); ID3D11DomainShader_Release(ds); ID3D11HullShader_Release(hs); ID3D11Buffer_Release(cb); release_test_context(&test_context); } #define check_so_desc(a, b, c, d, e, f, g, h) check_so_desc_(__LINE__, a, b, c, d, e, f, g, h) static void check_so_desc_(unsigned int line, ID3D11Device *device, const DWORD *code, size_t code_size, const D3D11_SO_DECLARATION_ENTRY *entry, unsigned int entry_count, unsigned int *strides, unsigned int stride_count, unsigned int rasterizer_stream) { ID3D11GeometryShader *gs; HRESULT hr; hr = ID3D11Device_CreateGeometryShaderWithStreamOutput(device, code, code_size, entry, entry_count, strides, stride_count, rasterizer_stream, NULL, &gs); ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#x.\n", hr); if (SUCCEEDED(hr)) ID3D11GeometryShader_Release(gs); } #define check_invalid_so_desc(a, b, c, d, e, f, g, h) check_invalid_so_desc_(__LINE__, a, b, c, d, e, f, g, h) static void check_invalid_so_desc_(unsigned int line, ID3D11Device *device, const DWORD *code, size_t code_size, const D3D11_SO_DECLARATION_ENTRY *entry, unsigned int entry_count, unsigned int *strides, unsigned int stride_count, unsigned int rasterizer_stream) { ID3D11GeometryShader *gs = (ID3D11GeometryShader *)0xdeadbeef; HRESULT hr; hr = ID3D11Device_CreateGeometryShaderWithStreamOutput(device, code, code_size, entry, entry_count, strides, stride_count, rasterizer_stream, NULL, &gs); ok_(__FILE__, line)(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ok_(__FILE__, line)(!gs, "Got unexpected geometry shader %p.\n", gs); if (SUCCEEDED(hr)) ID3D11GeometryShader_Release(gs); } static void test_stream_output(void) { UINT stride[D3D11_SO_BUFFER_SLOT_COUNT]; struct d3d11_test_context test_context; unsigned int i, count; ID3D11Device *device; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const DWORD vs_code[] = { #if 0 struct data { float4 position : SV_Position; float4 attrib1 : ATTRIB1; float3 attrib2 : attrib2; float2 attrib3 : ATTriB3; float attrib4 : ATTRIB4; }; void main(in data i, out data o) { o = i; } #endif 0x43425844, 0x3f5b621f, 0x8f390786, 0x7235c8d6, 0xc1181ad3, 0x00000001, 0x00000278, 0x00000003, 0x0000002c, 0x000000d8, 0x00000184, 0x4e475349, 0x000000a4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x0000008c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x00000093, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000707, 0x0000009a, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x0000008c, 0x00000004, 0x00000000, 0x00000003, 0x00000004, 0x00000101, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52545441, 0x61004249, 0x69727474, 0x54410062, 0x42697254, 0xababab00, 0x4e47534f, 0x000000a4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000008c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000093, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000807, 0x0000009a, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x0000008c, 0x00000004, 0x00000000, 0x00000003, 0x00000003, 0x00000b04, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52545441, 0x61004249, 0x69727474, 0x54410062, 0x42697254, 0xababab00, 0x52444853, 0x000000ec, 0x00010040, 0x0000003b, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x0300005f, 0x00101072, 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101012, 0x00000004, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102072, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x03000065, 0x00102042, 0x00000003, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x05000036, 0x00102072, 0x00000002, 0x00101246, 0x00000002, 0x05000036, 0x00102032, 0x00000003, 0x00101046, 0x00000003, 0x05000036, 0x00102042, 0x00000003, 0x0010100a, 0x00000004, 0x0100003e, }; static const DWORD gs_code[] = { #if 0 struct data { float4 position : SV_Position; float4 attrib1 : ATTRIB1; float3 attrib2 : attrib2; float2 attrib3 : ATTriB3; float attrib4 : ATTRIB4; }; [maxvertexcount(1)] void main(point data i[1], inout PointStream o) { o.Append(i[0]); } #endif 0x43425844, 0x59c61884, 0x3eef167b, 0x82618c33, 0x243cb630, 0x00000001, 0x000002a0, 0x00000003, 0x0000002c, 0x000000d8, 0x00000184, 0x4e475349, 0x000000a4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x0000008c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x00000093, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000707, 0x0000009a, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x0000008c, 0x00000004, 0x00000000, 0x00000003, 0x00000003, 0x00000404, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52545441, 0x61004249, 0x69727474, 0x54410062, 0x42697254, 0xababab00, 0x4e47534f, 0x000000a4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000008c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000093, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000807, 0x0000009a, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x0000008c, 0x00000004, 0x00000000, 0x00000003, 0x00000003, 0x00000b04, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52545441, 0x61004249, 0x69727474, 0x54410062, 0x42697254, 0xababab00, 0x52444853, 0x00000114, 0x00020040, 0x00000045, 0x05000061, 0x002010f2, 0x00000001, 0x00000000, 0x00000001, 0x0400005f, 0x002010f2, 0x00000001, 0x00000001, 0x0400005f, 0x00201072, 0x00000001, 0x00000002, 0x0400005f, 0x00201032, 0x00000001, 0x00000003, 0x0400005f, 0x00201042, 0x00000001, 0x00000003, 0x0100085d, 0x0100085c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102072, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x03000065, 0x00102042, 0x00000003, 0x0200005e, 0x00000001, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000000, 0x00000000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x06000036, 0x00102072, 0x00000002, 0x00201246, 0x00000000, 0x00000002, 0x06000036, 0x00102072, 0x00000003, 0x00201246, 0x00000000, 0x00000003, 0x01000013, 0x0100003e, }; static const D3D11_SO_DECLARATION_ENTRY so_declaration[] = { {0, "SV_Position", 0, 0, 4, 0}, }; static const D3D11_SO_DECLARATION_ENTRY invalid_gap_declaration[] = { {0, "SV_Position", 0, 0, 4, 0}, {0, NULL, 0, 0, 0, 0}, }; static const D3D11_SO_DECLARATION_ENTRY valid_so_declarations[][12] = { /* SemanticName and SemanticIndex */ { {0, "sv_position", 0, 0, 4, 0}, {0, "attrib", 1, 0, 4, 0}, }, { {0, "sv_position", 0, 0, 4, 0}, {0, "ATTRIB", 1, 0, 4, 0}, }, /* Gaps */ { {0, "SV_POSITION", 0, 0, 4, 0}, {0, NULL, 0, 0, 8, 0}, {0, "ATTRIB", 1, 0, 4, 0}, }, { {0, "SV_POSITION", 0, 0, 4, 0}, {0, NULL, 0, 0, 4, 0}, {0, NULL, 0, 0, 4, 0}, {0, "ATTRIB", 1, 0, 4, 0}, }, /* ComponentCount */ { {0, "ATTRIB", 1, 0, 4, 0}, }, { {0, "ATTRIB", 2, 0, 3, 0}, }, { {0, "ATTRIB", 3, 0, 2, 0}, }, { {0, "ATTRIB", 4, 0, 1, 0}, }, /* ComponentIndex */ { {0, "ATTRIB", 1, 1, 3, 0}, }, { {0, "ATTRIB", 1, 2, 2, 0}, }, { {0, "ATTRIB", 1, 3, 1, 0}, }, { {0, "ATTRIB", 3, 1, 1, 0}, }, /* OutputSlot */ { {0, "attrib", 1, 0, 4, 0}, }, { {0, "attrib", 1, 0, 4, 1}, }, { {0, "attrib", 1, 0, 4, 2}, }, { {0, "attrib", 1, 0, 4, 3}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 1}, {0, NULL, 0, 0, 1, 1}, {0, "attrib", 3, 0, 2, 2}, {0, NULL, 0, 0, 2, 2}, {0, "attrib", 4, 0, 1, 3}, {0, NULL, 0, 0, 7, 3}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 1}, {0, NULL, 0, 0, 1, 1}, {0, "attrib", 3, 0, 2, 2}, {0, NULL, 0, 0, 1, 2}, {0, NULL, 0, 0, 1, 2}, {0, "attrib", 4, 0, 1, 3}, {0, NULL, 0, 0, 3, 3}, {0, NULL, 0, 0, 1, 3}, {0, NULL, 0, 0, 1, 3}, {0, NULL, 0, 0, 1, 3}, {0, NULL, 0, 0, 1, 3}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 0}, {0, "attrib", 3, 0, 2, 0}, {0, NULL, 0, 0, 1, 0}, {0, "attrib", 4, 0, 1, 0}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 0}, {0, "attrib", 3, 0, 2, 3}, {0, NULL, 0, 0, 1, 3}, {0, "attrib", 4, 0, 1, 3}, }, /* Multiple occurrences of the same output */ { {0, "ATTRIB", 1, 0, 2, 0}, {0, "ATTRIB", 1, 2, 2, 1}, }, { {0, "ATTRIB", 1, 0, 1, 0}, {0, "ATTRIB", 1, 1, 3, 0}, }, }; static const D3D11_SO_DECLARATION_ENTRY invalid_so_declarations[][12] = { /* SemanticName and SemanticIndex */ { {0, "SV_Position", 0, 0, 4, 0}, {0, "ATTRIB", 0, 0, 4, 0}, }, { {0, "sv_position", 0, 0, 4, 0}, {0, "ATTRIB_", 1, 0, 4, 0}, }, /* Gaps */ { {0, "SV_POSITION", 0, 0, 4, 0}, {0, NULL, 0, 1, 8, 0}, {0, "ATTRIB", 1, 0, 4, 0}, }, { {0, "SV_POSITION", 0, 0, 4, 0}, {0, NULL, 1, 0, 8, 0}, {0, "ATTRIB", 1, 0, 4, 0}, }, /* Buffer stride */ { {0, "SV_POSITION", 0, 0, 4, 0}, {0, NULL, 0, 0, 8, 0}, {0, NULL, 0, 0, 8, 0}, {0, "ATTRIB", 1, 0, 4, 0}, }, /* ComponentCount */ { {0, "ATTRIB", 2, 0, 5, 0}, }, { {0, "ATTRIB", 2, 0, 4, 0}, }, { {0, "ATTRIB", 3, 0, 3, 0}, }, { {0, "ATTRIB", 4, 0, 2, 0}, }, /* ComponentIndex */ { {0, "ATTRIB", 1, 1, 4, 0}, }, { {0, "ATTRIB", 1, 2, 3, 0}, }, { {0, "ATTRIB", 1, 3, 2, 0}, }, { {0, "ATTRIB", 1, 4, 0, 0}, }, { {0, "ATTRIB", 1, 4, 1, 0}, }, { {0, "ATTRIB", 3, 2, 1, 0}, }, { {0, "ATTRIB", 3, 2, 0, 0}, }, /* OutputSlot */ { {0, "attrib", 1, 0, 4, 4}, }, { {0, "attrib", 1, 0, 4, 4}, }, { {0, "attrib", 1, 0, 4, 4}, }, { {0, "attrib", 1, 0, 4, 4}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 1}, {0, NULL, 0, 0, 1, 1}, {0, "attrib", 3, 0, 2, 2}, {0, NULL, 0, 0, 2, 2}, {0, "attrib", 4, 0, 1, 3}, {0, NULL, 0, 0, 3, 4}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 0}, {0, "attrib", 3, 0, 2, 0}, {0, NULL, 0, 0, 1, 0}, {0, "attrib", 4, 0, 1, 0}, {0, NULL, 0, 0, 3, 3}, {0, NULL, 0, 0, 1, 3}, {0, NULL, 0, 0, 1, 3}, {0, NULL, 0, 0, 1, 3}, {0, NULL, 0, 0, 1, 3}, }, { {0, "attrib", 1, 0, 4, 0}, {0, NULL, 0, 0, 3, 1}, {0, NULL, 0, 0, 1, 1}, {0, NULL, 0, 0, 1, 2}, {0, "attrib", 2, 0, 3, 3}, {0, NULL, 0, 0, 1, 3}, }, { {0, "attrib", 2, 0, 3, 3}, {0, NULL, 0, 0, 3, 1}, {0, NULL, 0, 0, 1, 3}, {0, "attrib", 1, 0, 4, 0}, {0, NULL, 0, 0, 1, 2}, {0, NULL, 0, 0, 1, 1}, }, /* Stream */ { {1, "attrib", 1, 0, 4, 0}, }, { {4, "attrib", 1, 0, 4, 0}, }, /* Multiple occurrences of the same output */ { {0, "ATTRIB", 1, 0, 4, 0}, {0, "ATTRIB", 1, 0, 4, 1}, }, { {0, "ATTRIB", 1, 0, 4, 0}, {0, "ATTRIB", 1, 0, 3, 0}, }, }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; for (i = 0; i < ARRAY_SIZE(stride); ++i) stride[i] = 64; check_so_desc(device, gs_code, sizeof(gs_code), NULL, 0, NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, gs_code, sizeof(gs_code), NULL, 0, stride, 1, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), stride, 1, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, vs_code, sizeof(vs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, vs_code, sizeof(vs_code), so_declaration, ARRAY_SIZE(so_declaration), stride, 1, D3D11_SO_NO_RASTERIZED_STREAM); check_invalid_so_desc(device, gs_code, sizeof(gs_code), so_declaration, 0, stride, 1, D3D11_SO_NO_RASTERIZED_STREAM); check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_gap_declaration, ARRAY_SIZE(invalid_gap_declaration), stride, 1, D3D11_SO_NO_RASTERIZED_STREAM); check_invalid_so_desc(device, vs_code, sizeof(vs_code), so_declaration, 0, NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM); check_invalid_so_desc(device, vs_code, sizeof(vs_code), NULL, 0, NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM); for (i = 0; i < ARRAY_SIZE(valid_so_declarations); ++i) { unsigned int max_output_slot = 0; for (count = 0; count < ARRAY_SIZE(valid_so_declarations[i]); ++count) { const D3D11_SO_DECLARATION_ENTRY *e = &valid_so_declarations[i][count]; max_output_slot = max(max_output_slot, e->OutputSlot); if (!e->Stream && !e->SemanticName && !e->SemanticIndex && !e->ComponentCount) break; } /* Buffer strides are required for all buffers. */ if (!max_output_slot) { check_so_desc(device, gs_code, sizeof(gs_code), valid_so_declarations[i], count, NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, gs_code, sizeof(gs_code), valid_so_declarations[i], count, stride, 1, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, gs_code, sizeof(gs_code), valid_so_declarations[i], count, stride, 2, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, gs_code, sizeof(gs_code), valid_so_declarations[i], count, stride, 3, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, gs_code, sizeof(gs_code), valid_so_declarations[i], count, stride, 4, D3D11_SO_NO_RASTERIZED_STREAM); } else { check_so_desc(device, gs_code, sizeof(gs_code), valid_so_declarations[i], count, NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, gs_code, sizeof(gs_code), valid_so_declarations[i], count, stride, max_output_slot + 1, D3D11_SO_NO_RASTERIZED_STREAM); } } for (i = 0; i < ARRAY_SIZE(invalid_so_declarations); ++i) { for (count = 0; count < ARRAY_SIZE(invalid_so_declarations[i]); ++count) { const D3D11_SO_DECLARATION_ENTRY *e = &invalid_so_declarations[i][count]; if (!e->Stream && !e->SemanticName && !e->SemanticIndex && !e->ComponentCount) break; } check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_so_declarations[i], count, stride, 1, D3D11_SO_NO_RASTERIZED_STREAM); check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_so_declarations[i], count, stride, 2, D3D11_SO_NO_RASTERIZED_STREAM); check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_so_declarations[i], count, stride, 3, D3D11_SO_NO_RASTERIZED_STREAM); check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_so_declarations[i], count, stride, 4, D3D11_SO_NO_RASTERIZED_STREAM); } /* Buffer strides */ stride[1] = 63; check_invalid_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), &stride[1], 1, D3D11_SO_NO_RASTERIZED_STREAM); check_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), stride, 2, D3D11_SO_NO_RASTERIZED_STREAM); stride[1] = 1; check_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), stride, 2, D3D11_SO_NO_RASTERIZED_STREAM); stride[0] = 0; check_invalid_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), stride, 1, D3D11_SO_NO_RASTERIZED_STREAM); /* Rasterizer stream */ for (i = 0; i < D3D11_SO_STREAM_COUNT; ++i) check_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, i); check_invalid_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, D3D11_SO_STREAM_COUNT); release_test_context(&test_context); } static void test_fl10_stream_output_desc(void) { UINT stride[D3D11_SO_BUFFER_SLOT_COUNT]; struct d3d11_test_context test_context; unsigned int i, count; ID3D11Device *device; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_10_0; static const DWORD vs_code[] = { #if 0 struct data { float4 position : SV_Position; float4 attrib1 : ATTRIB1; float3 attrib2 : attrib2; float2 attrib3 : ATTriB3; float attrib4 : ATTRIB4; }; void main(in data i, out data o) { o = i; } #endif 0x43425844, 0x3f5b621f, 0x8f390786, 0x7235c8d6, 0xc1181ad3, 0x00000001, 0x00000278, 0x00000003, 0x0000002c, 0x000000d8, 0x00000184, 0x4e475349, 0x000000a4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x0000008c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x00000093, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000707, 0x0000009a, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x0000008c, 0x00000004, 0x00000000, 0x00000003, 0x00000004, 0x00000101, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52545441, 0x61004249, 0x69727474, 0x54410062, 0x42697254, 0xababab00, 0x4e47534f, 0x000000a4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000008c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000093, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000807, 0x0000009a, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x0000008c, 0x00000004, 0x00000000, 0x00000003, 0x00000003, 0x00000b04, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52545441, 0x61004249, 0x69727474, 0x54410062, 0x42697254, 0xababab00, 0x52444853, 0x000000ec, 0x00010040, 0x0000003b, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x0300005f, 0x00101072, 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101012, 0x00000004, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102072, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x03000065, 0x00102042, 0x00000003, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x05000036, 0x00102072, 0x00000002, 0x00101246, 0x00000002, 0x05000036, 0x00102032, 0x00000003, 0x00101046, 0x00000003, 0x05000036, 0x00102042, 0x00000003, 0x0010100a, 0x00000004, 0x0100003e, }; static const DWORD gs_code[] = { #if 0 struct data { float4 position : SV_Position; float4 attrib1 : ATTRIB1; float3 attrib2 : attrib2; float2 attrib3 : ATTriB3; float attrib4 : ATTRIB4; }; [maxvertexcount(1)] void main(point data i[1], inout PointStream o) { o.Append(i[0]); } #endif 0x43425844, 0x59c61884, 0x3eef167b, 0x82618c33, 0x243cb630, 0x00000001, 0x000002a0, 0x00000003, 0x0000002c, 0x000000d8, 0x00000184, 0x4e475349, 0x000000a4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x0000008c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x00000093, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000707, 0x0000009a, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x0000008c, 0x00000004, 0x00000000, 0x00000003, 0x00000003, 0x00000404, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52545441, 0x61004249, 0x69727474, 0x54410062, 0x42697254, 0xababab00, 0x4e47534f, 0x000000a4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000008c, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000093, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000807, 0x0000009a, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x0000008c, 0x00000004, 0x00000000, 0x00000003, 0x00000003, 0x00000b04, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52545441, 0x61004249, 0x69727474, 0x54410062, 0x42697254, 0xababab00, 0x52444853, 0x00000114, 0x00020040, 0x00000045, 0x05000061, 0x002010f2, 0x00000001, 0x00000000, 0x00000001, 0x0400005f, 0x002010f2, 0x00000001, 0x00000001, 0x0400005f, 0x00201072, 0x00000001, 0x00000002, 0x0400005f, 0x00201032, 0x00000001, 0x00000003, 0x0400005f, 0x00201042, 0x00000001, 0x00000003, 0x0100085d, 0x0100085c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102072, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x03000065, 0x00102042, 0x00000003, 0x0200005e, 0x00000001, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000000, 0x00000000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x06000036, 0x00102072, 0x00000002, 0x00201246, 0x00000000, 0x00000002, 0x06000036, 0x00102072, 0x00000003, 0x00201246, 0x00000000, 0x00000003, 0x01000013, 0x0100003e, }; static const D3D11_SO_DECLARATION_ENTRY so_declaration[] = { {0, "SV_Position", 0, 0, 4, 0}, }; static const D3D11_SO_DECLARATION_ENTRY invalid_gap_declaration[] = { {0, "SV_Position", 0, 0, 4, 0}, {0, NULL, 0, 0, 0, 0}, }; static const D3D11_SO_DECLARATION_ENTRY valid_so_declarations[][12] = { /* Gaps */ { {0, "SV_POSITION", 0, 0, 4, 0}, {0, NULL, 0, 0, 8, 0}, {0, "ATTRIB", 1, 0, 4, 0}, }, { {0, "SV_POSITION", 0, 0, 4, 0}, {0, NULL, 0, 0, 4, 0}, {0, NULL, 0, 0, 4, 0}, {0, "ATTRIB", 1, 0, 4, 0}, }, /* OutputSlot */ { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 0}, {0, "attrib", 3, 0, 2, 0}, {0, "attrib", 4, 0, 1, 0}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 1}, {0, "attrib", 3, 0, 2, 2}, {0, "attrib", 4, 0, 1, 3}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 3}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 0}, {0, "attrib", 3, 0, 2, 0}, {0, NULL, 0, 0, 1, 0}, {0, "attrib", 4, 0, 1, 0}, }, /* Multiple occurrences of the same output */ { {0, "ATTRIB", 1, 0, 2, 0}, {0, "ATTRIB", 1, 2, 2, 1}, }, { {0, "ATTRIB", 1, 0, 1, 0}, {0, "ATTRIB", 1, 1, 3, 0}, }, }; static const D3D11_SO_DECLARATION_ENTRY invalid_so_declarations[][12] = { /* OutputSlot */ { {0, "attrib", 1, 0, 4, 0}, {0, NULL, 0, 0, 4, 0}, {0, "attrib", 4, 0, 1, 3}, }, { {0, "attrib", 1, 0, 4, 0}, {0, NULL, 0, 0, 4, 0}, {0, NULL, 0, 0, 4, 0}, {0, "attrib", 4, 0, 1, 3}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 0}, {0, "attrib", 3, 0, 2, 0}, {0, "attrib", 4, 0, 1, 1}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 2, 0, 3, 0}, {0, "attrib", 3, 0, 2, 3}, {0, NULL, 0, 0, 1, 3}, {0, "attrib", 4, 0, 1, 3}, }, { {0, "attrib", 1, 0, 4, 0}, {0, "attrib", 1, 0, 3, 1}, {0, "attrib", 1, 0, 2, 2}, {0, "attrib", 1, 0, 1, 3}, {0, NULL, 0, 0, 3, 3}, }, }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; for (i = 0; i < ARRAY_SIZE(stride); ++i) stride[i] = 64; check_so_desc(device, gs_code, sizeof(gs_code), NULL, 0, NULL, 0, 0); todo_wine check_invalid_so_desc(device, gs_code, sizeof(gs_code), NULL, 0, stride, 1, 0); check_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, 0); check_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), stride, 1, 0); check_so_desc(device, vs_code, sizeof(vs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, 0); check_so_desc(device, vs_code, sizeof(vs_code), so_declaration, ARRAY_SIZE(so_declaration), stride, 1, 0); check_invalid_so_desc(device, gs_code, sizeof(gs_code), so_declaration, 0, stride, 1, 0); check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_gap_declaration, ARRAY_SIZE(invalid_gap_declaration), stride, 1, 0); check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_gap_declaration, ARRAY_SIZE(invalid_gap_declaration), NULL, 0, 0); check_invalid_so_desc(device, vs_code, sizeof(vs_code), so_declaration, 0, NULL, 0, 0); check_invalid_so_desc(device, vs_code, sizeof(vs_code), NULL, 0, NULL, 0, 0); for (i = 0; i < ARRAY_SIZE(valid_so_declarations); ++i) { for (count = 0; count < ARRAY_SIZE(valid_so_declarations[i]); ++count) { const D3D11_SO_DECLARATION_ENTRY *e = &valid_so_declarations[i][count]; if (!e->Stream && !e->SemanticName && !e->SemanticIndex && !e->ComponentCount) break; } check_so_desc(device, gs_code, sizeof(gs_code), valid_so_declarations[i], count, NULL, 0, 0); } for (i = 0; i < ARRAY_SIZE(invalid_so_declarations); ++i) { for (count = 0; count < ARRAY_SIZE(invalid_so_declarations[i]); ++count) { const D3D11_SO_DECLARATION_ENTRY *e = &invalid_so_declarations[i][count]; if (!e->Stream && !e->SemanticName && !e->SemanticIndex && !e->ComponentCount) break; } check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_so_declarations[i], count, stride, 1, 0); check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_so_declarations[i], count, stride, 2, 0); check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_so_declarations[i], count, stride, 3, 0); check_invalid_so_desc(device, gs_code, sizeof(gs_code), invalid_so_declarations[i], count, stride, 4, 0); } /* Buffer strides */ stride[1] = 63; check_invalid_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), &stride[1], 1, 0); check_invalid_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), stride, 2, 0); stride[0] = 0; check_invalid_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), stride, 1, 0); /* Rasterizer stream */ check_invalid_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM); for (i = 1; i < D3D11_SO_STREAM_COUNT; ++i) check_invalid_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, i); check_so_desc(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, 0); release_test_context(&test_context); } static void test_stream_output_resume(void) { struct d3d11_test_context test_context; ID3D11Buffer *cb, *so_buffer, *buffer; unsigned int i, j, idx, offset; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11GeometryShader *gs; const struct vec4 *data; ID3D11Device *device; HRESULT hr; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const DWORD gs_code[] = { #if 0 float4 constant; struct vertex { float4 position : SV_POSITION; }; struct element { float4 position : SV_POSITION; float4 so_output : so_output; }; [maxvertexcount(3)] void main(triangle vertex input[3], inout PointStream output) { element o; o.so_output = constant; o.position = input[0].position; output.Append(o); o.position = input[1].position; output.Append(o); o.position = input[2].position; output.Append(o); } #endif 0x43425844, 0x4c16e500, 0xa0dc6126, 0x261156f3, 0xf01eedc8, 0x00000001, 0x000001b8, 0x00000003, 0x0000002c, 0x00000060, 0x000000b8, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x6f5f6f73, 0x75707475, 0xabab0074, 0x52444853, 0x000000f8, 0x00020040, 0x0000003e, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x05000061, 0x002010f2, 0x00000003, 0x00000000, 0x00000001, 0x0100185d, 0x0100085c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x0200005e, 0x00000003, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000000, 0x00000000, 0x06000036, 0x001020f2, 0x00000001, 0x00208e46, 0x00000000, 0x00000000, 0x01000013, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000001, 0x00000000, 0x06000036, 0x001020f2, 0x00000001, 0x00208e46, 0x00000000, 0x00000000, 0x01000013, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000002, 0x00000000, 0x06000036, 0x001020f2, 0x00000001, 0x00208e46, 0x00000000, 0x00000000, 0x01000013, 0x0100003e, }; static const D3D11_SO_DECLARATION_ENTRY so_declaration[] = { {0, "so_output", 0, 0, 4, 0}, }; static const struct vec4 constants[] = { {0.5f, 0.250f, 0.0f, 0.0f}, {0.0f, 0.125f, 0.0f, 1.0f}, {1.0f, 1.000f, 1.0f, 0.0f} }; static const struct vec4 green = {0.0f, 1.0f, 0.0f, 1.0f}; static const struct vec4 white = {1.0f, 1.0f, 1.0f, 1.0f}; static const struct vec4 red = {1.0f, 0.0f, 0.0f, 1.0f}; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateGeometryShaderWithStreamOutput(device, gs_code, sizeof(gs_code), so_declaration, ARRAY_SIZE(so_declaration), NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &gs); ok(SUCCEEDED(hr), "Failed to create geometry shader with stream output, hr %#x.\n", hr); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constants[0]), &constants[0]); so_buffer = create_buffer(device, D3D11_BIND_STREAM_OUTPUT, 1024, NULL); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); ID3D11DeviceContext_GSSetConstantBuffers(context, 0, 1, &cb); offset = 0; ID3D11DeviceContext_SOSetTargets(context, 1, &so_buffer, &offset); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &white.x); check_texture_color(test_context.backbuffer, 0xffffffff, 0); draw_color_quad(&test_context, &red); check_texture_color(test_context.backbuffer, 0xffffffff, 0); ID3D11DeviceContext_GSSetShader(context, NULL, NULL, 0); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constants[1], 0, 0); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); draw_color_quad(&test_context, &red); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); ID3D11DeviceContext_GSSetShader(context, NULL, NULL, 0); draw_color_quad(&test_context, &red); check_texture_color(test_context.backbuffer, 0xff0000ff, 0); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constants[2], 0, 0); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); draw_color_quad(&test_context, &white); check_texture_color(test_context.backbuffer, 0xff0000ff, 0); ID3D11DeviceContext_GSSetShader(context, NULL, NULL, 0); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); buffer = NULL; ID3D11DeviceContext_SOSetTargets(context, 1, &buffer, &offset); ID3D11DeviceContext_GSSetShader(context, NULL, NULL, 0); draw_color_quad(&test_context, &white); check_texture_color(test_context.backbuffer, 0xffffffff, 0); idx = 0; get_buffer_readback(so_buffer, &rb); for (i = 0; i < ARRAY_SIZE(constants); ++i) { for (j = 0; j < 6; ++j) /* 2 triangles */ { data = get_readback_vec4(&rb, idx++, 0); ok(compare_vec4(data, &constants[i], 0), "Got unexpected result {%.8e, %.8e, %.8e, %.8e} at %u (%u, %u).\n", data->x, data->y, data->z, data->w, idx, i, j); } } release_resource_readback(&rb); ID3D11Buffer_Release(cb); ID3D11Buffer_Release(so_buffer); ID3D11GeometryShader_Release(gs); release_test_context(&test_context); } static void test_stream_output_components(void) { const D3D11_SO_DECLARATION_ENTRY *current_so_declaration; struct d3d11_test_context test_context; ID3D11InputLayout *input_layout[2]; ID3D11Buffer *vb[2], *so_buffer; ID3D11DeviceContext *context; struct resource_readback rb; unsigned int stride, offset; ID3D11GeometryShader *gs; ID3D11VertexShader *vs; ID3D11PixelShader *ps; ID3D11Device *device; const float *result; unsigned int i, j; HRESULT hr; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const DWORD vs_code[] = { #if 0 struct vertex { float4 position : POSITION; float4 color : COLOR; float4 color2 : COLOR2; }; void main(in vertex i, out vertex o) { o = i; } #endif 0x43425844, 0x95991b76, 0x4898640b, 0xe36ad9d6, 0xfbfe78b4, 0x00000001, 0x00000194, 0x00000003, 0x0000002c, 0x00000094, 0x000000fc, 0x4e475349, 0x00000060, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000059, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x00000059, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x00000060, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000059, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000059, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x0000000f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x52444853, 0x00000090, 0x00010040, 0x00000024, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x0300005f, 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x05000036, 0x001020f2, 0x00000002, 0x00101e46, 0x00000002, 0x0100003e, }; static const DWORD gs_code[] = { #if 0 struct vertex { float4 position : POSITION; float4 color : COLOR; float4 color2 : COLOR2; }; [maxvertexcount(1)] void main(point vertex input[1], inout PointStream output) { output.Append(input[0]); } #endif 0x43425844, 0x218f7d27, 0x555fa7f1, 0x282c545f, 0x3989c843, 0x00000001, 0x000001c0, 0x00000003, 0x0000002c, 0x00000094, 0x000000fc, 0x4e475349, 0x00000060, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000059, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x00000059, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x00000060, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000059, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000059, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x0000000f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x52444853, 0x000000bc, 0x00020040, 0x0000002f, 0x0400005f, 0x002010f2, 0x00000001, 0x00000000, 0x0400005f, 0x002010f2, 0x00000001, 0x00000001, 0x0400005f, 0x002010f2, 0x00000001, 0x00000002, 0x0100085d, 0x0100085c, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x0200005e, 0x00000001, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000000, 0x00000000, 0x06000036, 0x001020f2, 0x00000001, 0x00201e46, 0x00000000, 0x00000001, 0x06000036, 0x001020f2, 0x00000002, 0x00201e46, 0x00000000, 0x00000002, 0x01000013, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 float4 main(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target { return float4(position.xy, texcoord); } #endif 0x43425844, 0xa15616bc, 0x6862ab1c, 0x28b915c0, 0xdb0df67c, 0x00000001, 0x0000011c, 0x00000003, 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x505f5653, 0x7469736f, 0x006e6f69, 0x43584554, 0x44524f4f, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000005c, 0x00000040, 0x00000017, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03001062, 0x00101032, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x001020c2, 0x00000000, 0x00101406, 0x00000001, 0x0100003e, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc2[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const D3D11_SO_DECLARATION_ENTRY so_declaration[] = { {0, "POSITION", 0, 0, 4, 0}, {0, "COLOR", 0, 0, 3, 0}, {0, "COLOR", 2, 0, 2, 0}, }; static const D3D11_SO_DECLARATION_ENTRY so_declaration2[] = { {0, "POSITION", 0, 0, 1, 0}, {0, "POSITION", 0, 1, 1, 0}, {0, "POSITION", 0, 2, 1, 0}, {0, "POSITION", 0, 3, 1, 0}, {0, "COLOR", 0, 0, 1, 0}, {0, "COLOR", 0, 1, 1, 0}, {0, "COLOR", 0, 2, 1, 0}, {0, "COLOR", 2, 0, 1, 0}, {0, "COLOR", 2, 1, 1, 0}, }; static const D3D11_SO_DECLARATION_ENTRY so_declaration3[] = { {0, "COLOR", 0, 2, 2, 0}, {0, "COLOR", 2, 3, 1, 0}, }; static const struct { struct vec4 position; struct vec3 color; struct vec2 color2; } vb_data[] = { {{-1.0f, -1.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, {0.5f, 1.0f}}, {{-1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}}, {{ 1.0f, -1.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 1.0f}, {0.5f, 0.4f}}, {{ 1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 0.0f}, {0.1f, 0.6f}}, }; static const struct { struct vec4 position; struct vec4 color; struct vec4 color2; } vb_data2[] = { {{-1.0f, -1.0f, 0.0f, 1.0f}, {1.0f, 2.0f, 3.0f, 4.0f}, {5.0f, 6.0f, 7.0f, 8.0f}}, {{-1.0f, 1.0f, 0.0f, 1.0f}, {9.0f, 1.1f, 1.2f, 1.3f}, {1.4f, 1.5f, 1.6f, 1.7f}}, {{ 1.0f, -1.0f, 0.0f, 1.0f}, {1.8f, 1.9f, 2.0f, 2.1f}, {2.2f, 2.3f, 2.4f, 2.5f}}, {{ 1.0f, 1.0f, 0.0f, 1.0f}, {2.5f, 2.6f, 2.7f, 2.8f}, {2.9f, 3.0f, 3.1f, 3.2f}}, }; static const unsigned int vb_stride[] = {sizeof(*vb_data), sizeof(*vb_data2)}; static const float expected_data[] = { -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.5f, 0.4f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.1f, 0.6f, }; static const float expected_data2[] = { -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 2.0f, 3.0f, 5.0f, 6.0f, -1.0f, 1.0f, 0.0f, 1.0f, 9.0f, 1.1f, 1.2f, 1.4f, 1.5f, 1.0f, -1.0f, 0.0f, 1.0f, 1.8f, 1.9f, 2.0f, 2.2f, 2.3f, 1.0f, 1.0f, 0.0f, 1.0f, 2.5f, 2.6f, 2.7f, 2.9f, 3.0f, }; static const float expected_data3[] = { 3.0f, 4.0f, 8.0f, 1.2f, 1.3f, 1.7f, 2.0f, 2.1f, 2.5f, 2.7f, 2.8f, 3.2f, }; static const struct { BOOL with_ps; unsigned int vb_idx; const D3D11_SO_DECLARATION_ENTRY *so_declaration; unsigned int so_entry_count; const float *expected_data; unsigned int expected_data_size; } tests[] = { {TRUE, 0, so_declaration, ARRAY_SIZE(so_declaration), expected_data, ARRAY_SIZE(expected_data)}, {TRUE, 1, so_declaration, ARRAY_SIZE(so_declaration), expected_data2, ARRAY_SIZE(expected_data2)}, {TRUE, 0, so_declaration2, ARRAY_SIZE(so_declaration2), expected_data, ARRAY_SIZE(expected_data)}, {TRUE, 1, so_declaration2, ARRAY_SIZE(so_declaration2), expected_data2, ARRAY_SIZE(expected_data2)}, {TRUE, 1, so_declaration3, ARRAY_SIZE(so_declaration3), expected_data3, ARRAY_SIZE(expected_data3)}, {FALSE, 0, so_declaration, ARRAY_SIZE(so_declaration), expected_data, ARRAY_SIZE(expected_data)}, {FALSE, 1, so_declaration, ARRAY_SIZE(so_declaration), expected_data2, ARRAY_SIZE(expected_data2)}, {FALSE, 0, so_declaration2, ARRAY_SIZE(so_declaration2), expected_data, ARRAY_SIZE(expected_data)}, {FALSE, 1, so_declaration2, ARRAY_SIZE(so_declaration2), expected_data2, ARRAY_SIZE(expected_data2)}, {FALSE, 1, so_declaration3, ARRAY_SIZE(so_declaration3), expected_data3, ARRAY_SIZE(expected_data3)}, }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; vb[0] = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(vb_data), vb_data); vb[1] = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(vb_data2), vb_data2); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout[0]); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); hr = ID3D11Device_CreateInputLayout(device, layout_desc2, ARRAY_SIZE(layout_desc2), vs_code, sizeof(vs_code), &input_layout[1]); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); so_buffer = create_buffer(device, D3D11_BIND_STREAM_OUTPUT, 1024, NULL); gs = NULL; current_so_declaration = NULL; for (i = 0; i < ARRAY_SIZE(tests); ++i) { ID3D11DeviceContext_PSSetShader(context, tests[i].with_ps ? ps : NULL, NULL, 0); if (current_so_declaration != tests[i].so_declaration) { if (gs) ID3D11GeometryShader_Release(gs); hr = ID3D11Device_CreateGeometryShaderWithStreamOutput(device, gs_code, sizeof(gs_code), tests[i].so_declaration, tests[i].so_entry_count, NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &gs); ok(SUCCEEDED(hr), "Failed to create geometry shader with stream output, hr %#x.\n", hr); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); current_so_declaration = tests[i].so_declaration; } ID3D11DeviceContext_IASetInputLayout(context, input_layout[tests[i].vb_idx]); stride = vb_stride[tests[i].vb_idx]; offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb[tests[i].vb_idx], &stride, &offset); offset = 0; ID3D11DeviceContext_SOSetTargets(context, 1, &so_buffer, &offset); ID3D11DeviceContext_Draw(context, 4, 0); get_buffer_readback(so_buffer, &rb); result = rb.map_desc.pData; for (j = 0; j < tests[i].expected_data_size; ++j) { float expected_value = tests[i].expected_data[j]; ok(compare_float(result[j], expected_value, 2), "Test %u: Got %.8e, expected %.8e at %u.\n", i, result[j], expected_value, j); } release_resource_readback(&rb); } for (i = 0; i < ARRAY_SIZE(vb); ++i) ID3D11Buffer_Release(vb[i]); ID3D11Buffer_Release(so_buffer); ID3D11VertexShader_Release(vs); ID3D11GeometryShader_Release(gs); ID3D11PixelShader_Release(ps); for (i = 0; i < ARRAY_SIZE(input_layout); ++i) ID3D11InputLayout_Release(input_layout[i]); release_test_context(&test_context); } static void test_stream_output_vs(void) { const D3D11_SO_DECLARATION_ENTRY *current_so_declaration; struct d3d11_test_context test_context; ID3D11InputLayout *input_layout; ID3D11Buffer *vb, *so_buffer; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11GeometryShader *gs; ID3D11VertexShader *vs; ID3D11Device *device; const float *result; unsigned int offset; unsigned int i, j; HRESULT hr; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const DWORD vs_code[] = { #if 0 struct vertex { float4 position : POSITION; float4 color0 : COLOR0; float4 color1 : COLOR1; }; vertex main(in vertex i) { return i; } #endif 0x43425844, 0xa67e993e, 0x1632c139, 0x02a7725f, 0xfb0221cd, 0x00000001, 0x00000194, 0x00000003, 0x0000002c, 0x00000094, 0x000000fc, 0x4e475349, 0x00000060, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000059, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x00000059, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x00000060, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000059, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000059, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x0000000f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x52444853, 0x00000090, 0x00010040, 0x00000024, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x0300005f, 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x05000036, 0x001020f2, 0x00000002, 0x00101e46, 0x00000002, 0x0100003e, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const D3D11_SO_DECLARATION_ENTRY all_so_decl[] = { {0, "POSITION", 0, 0, 4, 0}, {0, "COLOR", 0, 0, 3, 0}, {0, "COLOR", 1, 0, 2, 0}, }; static const D3D11_SO_DECLARATION_ENTRY position_so_decl[] = { {0, "POSITION", 0, 0, 4, 0}, }; static const D3D11_SO_DECLARATION_ENTRY position2_so_decl[] = { {0, "POSITION", 0, 0, 2, 0}, }; static const struct { struct vec4 position; struct vec4 color0; struct vec4 color1; } vb_data[] = { {{-1.0f, -1.0f, 0.0f, 1.0f}, {1.0f, 2.0f, 3.0f, 4.0f}, {5.0f, 6.0f, 7.0f, 8.0f}}, {{-1.0f, 1.0f, 0.0f, 1.0f}, {9.0f, 1.1f, 1.2f, 1.3f}, {1.4f, 1.5f, 1.6f, 1.7f}}, {{ 1.0f, -1.0f, 0.0f, 1.0f}, {1.8f, 1.9f, 2.0f, 2.1f}, {2.2f, 2.3f, 2.4f, 2.5f}}, {{ 1.0f, 1.0f, 0.0f, 1.0f}, {2.5f, 2.6f, 2.7f, 2.8f}, {2.9f, 3.0f, 3.1f, 3.2f}}, }; static const unsigned int vb_stride[] = {sizeof(*vb_data)}; static const float expected_data[] = { -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 2.0f, 3.0f, 5.0f, 6.0f, -1.0f, 1.0f, 0.0f, 1.0f, 9.0f, 1.1f, 1.2f, 1.4f, 1.5f, 1.0f, -1.0f, 0.0f, 1.0f, 1.8f, 1.9f, 2.0f, 2.2f, 2.3f, 1.0f, 1.0f, 0.0f, 1.0f, 2.5f, 2.6f, 2.7f, 2.9f, 3.0f, }; static const float expected_data2[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, }; static const float expected_data3[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, }; static const struct { const D3D11_SO_DECLARATION_ENTRY *so_declaration; unsigned int so_entry_count; const float *expected_data; unsigned int expected_data_size; } tests[] = { {all_so_decl, ARRAY_SIZE(all_so_decl), expected_data, ARRAY_SIZE(expected_data)}, {position_so_decl, ARRAY_SIZE(position_so_decl), expected_data2, ARRAY_SIZE(expected_data2)}, {position2_so_decl, ARRAY_SIZE(position2_so_decl), expected_data3, ARRAY_SIZE(expected_data3)}, }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(vb_data), vb_data); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); so_buffer = create_buffer(device, D3D11_BIND_STREAM_OUTPUT, 1024, NULL); ID3D11DeviceContext_IASetInputLayout(context, input_layout); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, vb_stride, &offset); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); gs = NULL; current_so_declaration = NULL; for (i = 0; i < ARRAY_SIZE(tests); ++i) { if (current_so_declaration != tests[i].so_declaration) { if (gs) ID3D11GeometryShader_Release(gs); hr = ID3D11Device_CreateGeometryShaderWithStreamOutput(device, vs_code, sizeof(vs_code), tests[i].so_declaration, tests[i].so_entry_count, NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &gs); ok(hr == S_OK, "Failed to create geometry shader with stream output, hr %#x.\n", hr); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); current_so_declaration = tests[i].so_declaration; } offset = 0; ID3D11DeviceContext_SOSetTargets(context, 1, &so_buffer, &offset); ID3D11DeviceContext_Draw(context, 4, 0); get_buffer_readback(so_buffer, &rb); result = rb.map_desc.pData; for (j = 0; j < tests[i].expected_data_size; ++j) { float expected_value = tests[i].expected_data[j]; ok(compare_float(result[j], expected_value, 2), "Test %u: Got %.8e, expected %.8e at %u.\n", i, result[j], expected_value, j); } release_resource_readback(&rb); } ID3D11Buffer_Release(vb); ID3D11Buffer_Release(so_buffer); ID3D11VertexShader_Release(vs); ID3D11GeometryShader_Release(gs); ID3D11InputLayout_Release(input_layout); release_test_context(&test_context); } static void test_gather(void) { struct { int width, height; int offset_x, offset_y; } constant; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11ShaderResourceView *srv; ID3D11Texture2D *texture, *rt; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; struct resource_readback rb; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int x, y; ID3D11Buffer *cb; HRESULT hr; static const DWORD gather4_code[] = { #if 0 SamplerState s; Texture2D t; int2 size; float4 main(float4 position : SV_Position) : SV_Target { return t.Gather(s, position.xy / size); } #endif 0x43425844, 0xca1ee692, 0xb122f477, 0x8c467d38, 0x0f5a233a, 0x00000001, 0x00000154, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000b8, 0x00000041, 0x0000002e, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0600002b, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x0700000e, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00100046, 0x00000000, 0x0900006d, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x0010600a, 0x00000000, 0x0100003e, }; static const DWORD gather4_offset_code[] = { #if 0 SamplerState s; Texture2D t; int2 size; float4 main(float4 position : SV_Position) : SV_Target { return t.Gather(s, position.xy / size, int2(1, 1)); } #endif 0x43425844, 0xe5ab2216, 0x90748ece, 0x7ccf2123, 0x4edbba7c, 0x00000001, 0x00000158, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000bc, 0x00000041, 0x0000002f, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0600002b, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x0700000e, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00100046, 0x00000000, 0x8a00006d, 0x00002201, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x0010600a, 0x00000000, 0x0100003e, }; static const DWORD gather4_green_code[] = { #if 0 SamplerState s; Texture2D t; int2 size; float4 main(float4 position : SV_Position) : SV_Target { return t.GatherGreen(s, position.xy / size); } #endif 0x43425844, 0x2b0ad2d9, 0x8ad30b52, 0xc418477f, 0xe5211693, 0x00000001, 0x0000015c, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000c0, 0x00000050, 0x00000030, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0600002b, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x0700000e, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00100046, 0x00000000, 0x8b00006d, 0x800000c2, 0x00155543, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x0010601a, 0x00000000, 0x0100003e, }; static const DWORD gather4_po_code[] = { #if 0 SamplerState s; Texture2D t; int2 size; int2 offset; float4 main(float4 position : SV_Position) : SV_Target { return t.Gather(s, position.xy / size, offset); } #endif 0x43425844, 0xe19bdd35, 0x44514fb3, 0xfaa8727f, 0xc1092da0, 0x00000001, 0x00000168, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000cc, 0x00000050, 0x00000033, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0600002b, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x0700000e, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00100046, 0x00000000, 0x8e00007f, 0x800000c2, 0x00155543, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00208ae6, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x0010600a, 0x00000000, 0x0100003e, }; static const struct vec4 texture_data[] = { {0.0f, 0.0f}, {1.0f, 1.0f}, {2.0f, 2.0f}, {3.0f, 3.0f}, {4.0f, 0.1f}, {5.0f, 1.1f}, {6.0f, 2.1f}, {7.0f, 3.1f}, {8.0f, 0.2f}, {9.0f, 1.2f}, {0.5f, 2.2f}, {1.5f, 3.2f}, {2.5f, 0.3f}, {3.5f, 1.3f}, {4.5f, 2.3f}, {5.5f, 3.3f}, }; static const struct vec4 expected_gather4[] = { {4.0f, 5.0f, 1.0f, 0.0f}, {5.0f, 6.0f, 2.0f, 1.0f}, {6.0f, 7.0f, 3.0f, 2.0f}, {7.0f, 7.0f, 3.0f, 3.0f}, {8.0f, 9.0f, 5.0f, 4.0f}, {9.0f, 0.5f, 6.0f, 5.0f}, {0.5f, 1.5f, 7.0f, 6.0f}, {1.5f, 1.5f, 7.0f, 7.0f}, {2.5f, 3.5f, 9.0f, 8.0f}, {3.5f, 4.5f, 0.5f, 9.0f}, {4.5f, 5.5f, 1.5f, 0.5f}, {5.5f, 5.5f, 1.5f, 1.5f}, {2.5f, 3.5f, 3.5f, 2.5f}, {3.5f, 4.5f, 4.5f, 3.5f}, {4.5f, 5.5f, 5.5f, 4.5f}, {5.5f, 5.5f, 5.5f, 5.5f}, }; static const struct vec4 expected_gather4_offset[] = { {9.0f, 0.5f, 6.0f, 5.0f}, {0.5f, 1.5f, 7.0f, 6.0f}, {1.5f, 1.5f, 7.0f, 7.0f}, {1.5f, 1.5f, 7.0f, 7.0f}, {3.5f, 4.5f, 0.5f, 9.0f}, {4.5f, 5.5f, 1.5f, 0.5f}, {5.5f, 5.5f, 1.5f, 1.5f}, {5.5f, 5.5f, 1.5f, 1.5f}, {3.5f, 4.5f, 4.5f, 3.5f}, {4.5f, 5.5f, 5.5f, 4.5f}, {5.5f, 5.5f, 5.5f, 5.5f}, {5.5f, 5.5f, 5.5f, 5.5f}, {3.5f, 4.5f, 4.5f, 3.5f}, {4.5f, 5.5f, 5.5f, 4.5f}, {5.5f, 5.5f, 5.5f, 5.5f}, {5.5f, 5.5f, 5.5f, 5.5f}, }; static const struct vec4 expected_gather4_green[] = { {0.1f, 1.1f, 1.0f, 0.0f}, {1.1f, 2.1f, 2.0f, 1.0f}, {2.1f, 3.1f, 3.0f, 2.0f}, {3.1f, 3.1f, 3.0f, 3.0f}, {0.2f, 1.2f, 1.1f, 0.1f}, {1.2f, 2.2f, 2.1f, 1.1f}, {2.2f, 3.2f, 3.1f, 2.1f}, {3.2f, 3.2f, 3.1f, 3.1f}, {0.3f, 1.3f, 1.2f, 0.2f}, {1.3f, 2.3f, 2.2f, 1.2f}, {2.3f, 3.3f, 3.2f, 2.2f}, {3.3f, 3.3f, 3.2f, 3.2f}, {0.3f, 1.3f, 1.3f, 0.3f}, {1.3f, 2.3f, 2.3f, 1.3f}, {2.3f, 3.3f, 3.3f, 2.3f}, {3.3f, 3.3f, 3.3f, 3.3f}, }; static const struct vec4 white = {1.0f, 1.0f, 1.0f, 1.0f}; static const D3D11_SUBRESOURCE_DATA resource_data = {&texture_data, sizeof(texture_data) / 4}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; if (ID3D11Device_GetFeatureLevel(device) < D3D_FEATURE_LEVEL_10_1) { skip("Shader model 4.1 required for gather4 instruction.\n"); release_test_context(&test_context); return; } texture_desc.Width = 4; texture_desc.Height = 4; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rt); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rt, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); constant.width = texture_desc.Width; constant.height = texture_desc.Height; constant.offset_x = 1; constant.offset_y = 1; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constant), &constant); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); hr = ID3D11Device_CreatePixelShader(device, gather4_code, sizeof(gather4_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, &white.x); draw_quad(&test_context); get_texture_readback(rt, 0, &rb); for (y = 0; y < texture_desc.Height; ++y) { for (x = 0; x < texture_desc.Width; ++x) { const struct vec4 *expected = &expected_gather4[y * texture_desc.Width + x]; const struct vec4 *got = get_readback_vec4(&rb, x, y); ok(compare_vec4(got, expected, 0), "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", got->x, got->y, got->z, got->w, expected->x, expected->y, expected->z, expected->w); } } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); hr = ID3D11Device_CreatePixelShader(device, gather4_offset_code, sizeof(gather4_offset_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, &white.x); draw_quad(&test_context); get_texture_readback(rt, 0, &rb); for (y = 0; y < texture_desc.Height; ++y) { for (x = 0; x < texture_desc.Width; ++x) { const struct vec4 *expected = &expected_gather4_offset[y * texture_desc.Width + x]; const struct vec4 *got = get_readback_vec4(&rb, x, y); ok(compare_vec4(got, expected, 0), "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", got->x, got->y, got->z, got->w, expected->x, expected->y, expected->z, expected->w); } } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); if (ID3D11Device_GetFeatureLevel(device) < D3D_FEATURE_LEVEL_11_0) { skip("Shader model 5 required for GatherGreen()/gather4_po.\n"); goto done; } hr = ID3D11Device_CreatePixelShader(device, gather4_green_code, sizeof(gather4_green_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, &white.x); draw_quad(&test_context); get_texture_readback(rt, 0, &rb); for (y = 0; y < texture_desc.Height; ++y) { for (x = 0; x < texture_desc.Width; ++x) { const struct vec4 *expected = &expected_gather4_green[y * texture_desc.Width + x]; const struct vec4 *got = get_readback_vec4(&rb, x, y); ok(compare_vec4(got, expected, 0), "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", got->x, got->y, got->z, got->w, expected->x, expected->y, expected->z, expected->w); } } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); hr = ID3D11Device_CreatePixelShader(device, gather4_po_code, sizeof(gather4_po_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, &white.x); draw_quad(&test_context); get_texture_readback(rt, 0, &rb); for (y = 0; y < texture_desc.Height; ++y) { for (x = 0; x < texture_desc.Width; ++x) { const struct vec4 *expected = &expected_gather4_offset[y * texture_desc.Width + x]; const struct vec4 *got = get_readback_vec4(&rb, x, y); ok(compare_vec4(got, expected, 0), "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", got->x, got->y, got->z, got->w, expected->x, expected->y, expected->z, expected->w); } } release_resource_readback(&rb); constant.offset_x = 0; constant.offset_y = 0; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, &white.x); draw_quad(&test_context); get_texture_readback(rt, 0, &rb); for (y = 0; y < texture_desc.Height; ++y) { for (x = 0; x < texture_desc.Width; ++x) { const struct vec4 *expected = &expected_gather4[y * texture_desc.Width + x]; const struct vec4 *got = get_readback_vec4(&rb, x, y); ok(compare_vec4(got, expected, 0), "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", got->x, got->y, got->z, got->w, expected->x, expected->y, expected->z, expected->w); } } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); done: ID3D11Buffer_Release(cb); ID3D11Texture2D_Release(rt); ID3D11Texture2D_Release(texture); ID3D11RenderTargetView_Release(rtv); ID3D11ShaderResourceView_Release(srv); release_test_context(&test_context); } static void test_gather_c(void) { struct { int width, height; int offset_x, offset_y; float compare_value; int padding[3]; } constant; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; D3D11_SAMPLER_DESC sampler_desc; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; ID3D11ShaderResourceView *srv; ID3D11Texture2D *texture, *rt; ID3D11DeviceContext *context; ID3D11SamplerState *sampler; ID3D11RenderTargetView *rtv; struct resource_readback rb; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int x, y; ID3D11Buffer *cb; HRESULT hr; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const DWORD gather4_c_code[] = { #if 0 SamplerComparisonState s; Texture2D t; int2 size; int2 offset; float compare; float4 main(float4 position : SV_Position) : SV_Target { return t.GatherCmp(s, position.xy / size, compare); } #endif 0x43425844, 0xd3d04479, 0x901e9208, 0x7074fd0c, 0xbcadb2da, 0x00000001, 0x00000168, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000cc, 0x00000050, 0x00000033, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300085a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0600002b, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x0700000e, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00100046, 0x00000000, 0x8e00007e, 0x800000c2, 0x00155543, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x0010600a, 0x00000000, 0x0020800a, 0x00000000, 0x00000001, 0x0100003e, }; static const DWORD gather4_po_c_code[] = { #if 0 SamplerComparisonState s; Texture2D t; int2 size; int2 offset; float compare; float4 main(float4 position : SV_Position) : SV_Target { return t.GatherCmp(s, position.xy / size, compare, offset); } #endif 0x43425844, 0x501de13e, 0x472d2d20, 0x6df0fee4, 0xef27d9e6, 0x00000001, 0x00000174, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000d8, 0x00000050, 0x00000036, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300085a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0600002b, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x0700000e, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00100046, 0x00000000, 0x91000080, 0x800000c2, 0x00155543, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00208ae6, 0x00000000, 0x00000000, 0x00107e46, 0x00000000, 0x0010600a, 0x00000000, 0x0020800a, 0x00000000, 0x00000001, 0x0100003e, }; static const float texture_data[] = { 0.00f, 0.10f, 0.20f, 0.30f, 0.40f, 0.50f, 0.60f, 0.70f, 0.80f, 0.90f, 0.05f, 0.15f, 0.25f, 0.35f, 0.45f, 0.55f, }; static const struct vec4 expected_gather4_c[] = { {0.0f, 1.00, 0.00, 0.0f}, {1.0f, 1.00, 0.00, 0.0f}, {1.0f, 1.00, 0.00, 0.0f}, {1.0f, 1.00, 0.00, 0.0f}, {1.0f, 1.00, 1.00, 0.0f}, {1.0f, 0.00, 1.00, 1.0f}, {0.0f, 0.00, 1.00, 1.0f}, {0.0f, 0.00, 1.00, 1.0f}, {0.0f, 0.00, 1.00, 1.0f}, {0.0f, 0.00, 0.00, 1.0f}, {0.0f, 1.00, 0.00, 0.0f}, {1.0f, 1.00, 0.00, 0.0f}, {0.0f, 0.00, 0.00, 0.0f}, {0.0f, 0.00, 0.00, 0.0f}, {0.0f, 1.00, 1.00, 0.0f}, {1.0f, 1.00, 1.00, 1.0f}, }; static const struct vec4 expected_gather4_po_c[] = { {1.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, }; static const struct vec4 white = {1.0f, 1.0f, 1.0f, 1.0f}; static const D3D11_SUBRESOURCE_DATA resource_data = {&texture_data, sizeof(texture_data) / 4}; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; sampler_desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = D3D11_FLOAT32_MAX; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); texture_desc.Width = 4; texture_desc.Height = 4; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rt); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rt, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); constant.width = texture_desc.Width; constant.height = texture_desc.Height; constant.offset_x = 1; constant.offset_y = 1; constant.compare_value = 0.5f; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constant), &constant); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); texture_desc.Format = DXGI_FORMAT_R32_TYPELESS; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); srv_desc.Format = DXGI_FORMAT_R32_FLOAT; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; U(srv_desc).Texture2D.MostDetailedMip = 0; U(srv_desc).Texture2D.MipLevels = 1; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, &srv_desc, &srv); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); hr = ID3D11Device_CreatePixelShader(device, gather4_c_code, sizeof(gather4_c_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, &white.x); draw_quad(&test_context); get_texture_readback(rt, 0, &rb); for (y = 0; y < texture_desc.Height; ++y) { for (x = 0; x < texture_desc.Width; ++x) { const struct vec4 *expected = &expected_gather4_c[y * texture_desc.Width + x]; const struct vec4 *got = get_readback_vec4(&rb, x, y); ok(compare_vec4(got, expected, 0), "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", got->x, got->y, got->z, got->w, expected->x, expected->y, expected->z, expected->w); } } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); hr = ID3D11Device_CreatePixelShader(device, gather4_po_c_code, sizeof(gather4_po_c_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, &white.x); draw_quad(&test_context); get_texture_readback(rt, 0, &rb); for (y = 0; y < texture_desc.Height; ++y) { for (x = 0; x < texture_desc.Width; ++x) { const struct vec4 *expected = &expected_gather4_po_c[y * texture_desc.Width + x]; const struct vec4 *got = get_readback_vec4(&rb, x, y); ok(compare_vec4(got, expected, 0), "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", got->x, got->y, got->z, got->w, expected->x, expected->y, expected->z, expected->w); } } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); ID3D11ShaderResourceView_Release(srv); ID3D11Texture2D_Release(texture); ID3D11Buffer_Release(cb); ID3D11Texture2D_Release(rt); ID3D11RenderTargetView_Release(rtv); ID3D11SamplerState_Release(sampler); release_test_context(&test_context); } static float clamp_depth_bias(float bias, float clamp) { if (clamp > 0.0f) return min(bias, clamp); if (clamp < 0.0f) return max(bias, clamp); return bias; } static void test_depth_bias(void) { struct vec3 vertices[] = { {-1.0f, -1.0f, 0.5f}, {-1.0f, 1.0f, 0.5f}, { 1.0f, -1.0f, 0.5f}, { 1.0f, 1.0f, 0.5f}, }; struct d3d11_test_context test_context; D3D11_RASTERIZER_DESC rasterizer_desc; struct swapchain_desc swapchain_desc; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; double m, bias, depth, data; struct resource_readback rb; ID3D11DepthStencilView *dsv; unsigned int expected_value; ID3D11RasterizerState *rs; ID3D11Texture2D *texture; unsigned int format_idx; unsigned int y, i, j, k; unsigned int shift = 0; ID3D11Device *device; float *depth_values; DXGI_FORMAT format; const UINT32 *u32; const UINT16 *u16; UINT32 u32_value; HRESULT hr; static const struct { float z; float exponent; } quads[] = { {0.125f, -3.0f}, {0.250f, -2.0f}, {0.500f, -1.0f}, {1.000f, 0.0f}, }; static const int bias_tests[] = { -10000, -1000, -100, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 50, 100, 200, 500, 1000, 10000, }; static const float bias_clamp_tests[] = { 0.0f, -1e-5f, 1e-5f, }; static const float quad_slopes[] = { 0.0f, 0.5f, 1.0f }; static const float slope_scaled_bias_tests[] = { 0.0f, 0.5f, 1.0f, 2.0f, 128.0f, 1000.0f, 10000.0f, }; static const DXGI_FORMAT formats[] = { DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_D16_UNORM, }; swapchain_desc.windowed = TRUE; swapchain_desc.buffer_count = 1; swapchain_desc.width = 200; swapchain_desc.height = 200; swapchain_desc.swap_effect = DXGI_SWAP_EFFECT_DISCARD; swapchain_desc.flags = 0; if (!init_test_context_ext(&test_context, NULL, &swapchain_desc)) return; device = test_context.device; context = test_context.immediate_context; memset(&rasterizer_desc, 0, sizeof(rasterizer_desc)); rasterizer_desc.FillMode = D3D11_FILL_SOLID; rasterizer_desc.CullMode = D3D11_CULL_NONE; rasterizer_desc.FrontCounterClockwise = FALSE; rasterizer_desc.DepthBias = 0; rasterizer_desc.DepthBiasClamp = 0.0f; rasterizer_desc.SlopeScaledDepthBias = 0.0f; rasterizer_desc.DepthClipEnable = TRUE; depth_values = heap_calloc(swapchain_desc.height, sizeof(*depth_values)); ok(!!depth_values, "Failed to allocate memory.\n"); for (format_idx = 0; format_idx < ARRAY_SIZE(formats); ++format_idx) { format = formats[format_idx]; ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = format; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, NULL, &dsv); ok(SUCCEEDED(hr), "Failed to create render depth stencil view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, dsv); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); draw_quad_z(&test_context, 1.0f); switch (format) { case DXGI_FORMAT_D32_FLOAT: check_texture_float(texture, 1.0f, 0); break; case DXGI_FORMAT_D24_UNORM_S8_UINT: /* FIXME: Depth/stencil byte order is reversed in wined3d. */ shift = get_texture_color(texture, 0, 0) == 0xffffff ? 0 : 8; todo_wine check_texture_color(texture, 0xffffff, 1); break; case DXGI_FORMAT_D16_UNORM: get_texture_readback(texture, 0, &rb); check_readback_data_u16(&rb, NULL, 0xffffu, 0); release_resource_readback(&rb); break; default: trace("Unhandled format %#x.\n", format); break; } draw_quad(&test_context); /* DepthBias */ for (i = 0; i < ARRAY_SIZE(quads); ++i) { for (j = 0; j < ARRAY_SIZE(vertices); ++j) vertices[j].z = quads[i].z; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)test_context.vb, 0, NULL, vertices, 0, 0); for (j = 0; j < ARRAY_SIZE(bias_tests); ++j) { rasterizer_desc.DepthBias = bias_tests[j]; for (k = 0; k < ARRAY_SIZE(bias_clamp_tests); ++k) { rasterizer_desc.DepthBiasClamp = bias_clamp_tests[k]; ID3D11Device_CreateRasterizerState(device, &rasterizer_desc, &rs); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ID3D11DeviceContext_RSSetState(context, rs); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); draw_quad(&test_context); switch (format) { case DXGI_FORMAT_D32_FLOAT: bias = rasterizer_desc.DepthBias * pow(2.0f, quads[i].exponent - 23.0f); bias = clamp_depth_bias(bias, rasterizer_desc.DepthBiasClamp); depth = min(max(0.0f, quads[i].z + bias), 1.0f); check_texture_float(texture, depth, 2); break; case DXGI_FORMAT_D24_UNORM_S8_UINT: bias = clamp_depth_bias(rasterizer_desc.DepthBias / 16777215.0f, rasterizer_desc.DepthBiasClamp); depth = min(max(0.0f, quads[i].z + bias), 1.0f); get_texture_readback(texture, 0, &rb); check_readback_data_u24(&rb, NULL, shift, depth * 16777215.0f + 0.5f, 1); release_resource_readback(&rb); break; case DXGI_FORMAT_D16_UNORM: bias = clamp_depth_bias(rasterizer_desc.DepthBias / 65535.0f, rasterizer_desc.DepthBiasClamp); depth = min(max(0.0f, quads[i].z + bias), 1.0f); get_texture_readback(texture, 0, &rb); check_readback_data_u16(&rb, NULL, depth * 65535.0f + 0.5f, 1); release_resource_readback(&rb); break; default: break; } ID3D11RasterizerState_Release(rs); } } } /* SlopeScaledDepthBias */ rasterizer_desc.DepthBias = 0; for (i = 0; i < ARRAY_SIZE(quad_slopes); ++i) { for (j = 0; j < ARRAY_SIZE(vertices); ++j) vertices[j].z = j == 1 || j == 3 ? 0.0f : quad_slopes[i]; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)test_context.vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_RSSetState(context, NULL); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); draw_quad(&test_context); get_texture_readback(texture, 0, &rb); for (y = 0; y < texture_desc.Height; ++y) { switch (format) { case DXGI_FORMAT_D32_FLOAT: depth_values[y] = get_readback_float(&rb, 0, y); break; case DXGI_FORMAT_D24_UNORM_S8_UINT: u32 = get_readback_data(&rb, 0, y, 0, sizeof(*u32)); u32_value = *u32 >> shift; depth_values[y] = u32_value / 16777215.0f; break; case DXGI_FORMAT_D16_UNORM: u16 = get_readback_data(&rb, 0, y, 0, sizeof(*u16)); depth_values[y] = *u16 / 65535.0f; break; default: break; } } release_resource_readback(&rb); for (j = 0; j < ARRAY_SIZE(slope_scaled_bias_tests); ++j) { rasterizer_desc.SlopeScaledDepthBias = slope_scaled_bias_tests[j]; for (k = 0; k < ARRAY_SIZE(bias_clamp_tests); ++k) { BOOL all_match = TRUE; rasterizer_desc.DepthBiasClamp = bias_clamp_tests[k]; ID3D11Device_CreateRasterizerState(device, &rasterizer_desc, &rs); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ID3D11DeviceContext_RSSetState(context, rs); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); draw_quad(&test_context); m = quad_slopes[i] / texture_desc.Height; bias = clamp_depth_bias(rasterizer_desc.SlopeScaledDepthBias * m, rasterizer_desc.DepthBiasClamp); get_texture_readback(texture, 0, &rb); for (y = 0; y < texture_desc.Height && all_match; ++y) { depth = min(max(0.0f, depth_values[y] + bias), 1.0f); switch (format) { case DXGI_FORMAT_D32_FLOAT: data = get_readback_float(&rb, 0, y); all_match = compare_float(data, depth, 64); ok(all_match, "Got depth %.8e, expected %.8e.\n", data, depth); break; case DXGI_FORMAT_D24_UNORM_S8_UINT: u32 = get_readback_data(&rb, 0, y, 0, sizeof(*u32)); u32_value = *u32 >> shift; expected_value = depth * 16777215.0f + 0.5f; all_match = compare_uint(u32_value, expected_value, 3); ok(all_match, "Got value %#x (%.8e), expected %#x (%.8e).\n", u32_value, u32_value / 16777215.0f, expected_value, expected_value / 16777215.0f); break; case DXGI_FORMAT_D16_UNORM: u16 = get_readback_data(&rb, 0, y, 0, sizeof(*u16)); expected_value = depth * 65535.0f + 0.5f; all_match = compare_uint(*u16, expected_value, 1); ok(all_match, "Got value %#x (%.8e), expected %#x (%.8e).\n", *u16, *u16 / 65535.0f, expected_value, expected_value / 65535.0f); break; default: break; } } release_resource_readback(&rb); ID3D11RasterizerState_Release(rs); } } } ID3D11Texture2D_Release(texture); ID3D11DepthStencilView_Release(dsv); } heap_free(depth_values); release_test_context(&test_context); } static void test_fractional_viewports(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11InputLayout *input_layout; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11RenderTargetView *rtv; ID3D11VertexShader *vs; ID3D11PixelShader *ps; unsigned int i, x, y; ID3D11Device *device; ID3D11Texture2D *rt; UINT offset, stride; ID3D11Buffer *vb; HRESULT hr; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const DWORD vs_code[] = { #if 0 void main(in float4 in_position : POSITION, in float2 in_texcoord : TEXCOORD, out float4 position : SV_Position, out float2 texcoord : TEXCOORD) { position = in_position; texcoord = in_texcoord; } #endif 0x43425844, 0x4df282ca, 0x85c8bbfc, 0xd44ad19f, 0x1158be97, 0x00000001, 0x00000148, 0x00000003, 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044, 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000c03, 0x505f5653, 0x7469736f, 0x006e6f69, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102032, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x00102032, 0x00000001, 0x00101046, 0x00000001, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 float4 main(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target { return float4(position.xy, texcoord); } #endif 0x43425844, 0xa15616bc, 0x6862ab1c, 0x28b915c0, 0xdb0df67c, 0x00000001, 0x0000011c, 0x00000003, 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x505f5653, 0x7469736f, 0x006e6f69, 0x43584554, 0x44524f4f, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000005c, 0x00000040, 0x00000017, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03001062, 0x00101032, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x001020c2, 0x00000000, 0x00101406, 0x00000001, 0x0100003e, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; static const struct { struct vec2 position; struct vec2 texcoord; } quad[] = { {{-1.0f, -1.0f}, {0.0f, 0.0f}}, {{-1.0f, 1.0f}, {0.0f, 1.0f}}, {{ 1.0f, -1.0f}, {1.0f, 0.0f}}, {{ 1.0f, 1.0f}, {1.0f, 1.0f}}, }; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const float viewport_offsets[] = { 0.0f, 1.0f / 2.0f, 1.0f / 4.0f, 1.0f / 8.0f, 1.0f / 16.0f, 1.0f / 32.0f, 1.0f / 64.0f, 1.0f / 128.0f, 1.0f / 256.0f, 63.0f / 128.0f, }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; texture_desc.Width = 4; texture_desc.Height = 4; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rt); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rt, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(quad), quad); ID3D11DeviceContext_IASetInputLayout(context, input_layout); ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); stride = sizeof(*quad); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &vb, &stride, &offset); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); for (i = 0; i < ARRAY_SIZE(viewport_offsets); ++i) { set_viewport(context, viewport_offsets[i], viewport_offsets[i], texture_desc.Width, texture_desc.Height, 0.0f, 1.0f); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, white); ID3D11DeviceContext_Draw(context, 4, 0); get_texture_readback(rt, 0, &rb); for (y = 0; y < texture_desc.Height; ++y) { for (x = 0; x < texture_desc.Width; ++x) { const struct vec4 *v = get_readback_vec4(&rb, x, y); struct vec4 expected = {x + 0.5f, y + 0.5f, (x + 0.5f - viewport_offsets[i]) / texture_desc.Width, 1.0f - (y + 0.5f - viewport_offsets[i]) / texture_desc.Height}; ok(compare_float(v->x, expected.x, 0) && compare_float(v->y, expected.y, 0), "Got fragcoord {%.8e, %.8e}, expected {%.8e, %.8e} at (%u, %u), offset %.8e.\n", v->x, v->y, expected.x, expected.y, x, y, viewport_offsets[i]); todo_wine ok(compare_float(v->z, expected.z, 2) && compare_float(v->w, expected.w, 2), "Got texcoord {%.8e, %.8e}, expected {%.8e, %.8e} at (%u, %u), offset %.8e.\n", v->z, v->w, expected.z, expected.w, x, y, viewport_offsets[i]); } } release_resource_readback(&rb); } ID3D11InputLayout_Release(input_layout); ID3D11Buffer_Release(vb); ID3D11VertexShader_Release(vs); ID3D11PixelShader_Release(ps); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(rt); release_test_context(&test_context); } static void test_negative_viewports(const D3D_FEATURE_LEVEL feature_level) { struct d3d11_test_context test_context; ID3D11DeviceContext *context; BOOL quirk; RECT rect; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const struct vec4 green = {0.0f, 1.0f, 0.0f, 1.0f}; if (!init_test_context(&test_context, &feature_level)) return; context = test_context.immediate_context; set_viewport(context, 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1.0f); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); set_viewport(context, -0.0f, -0.0f, 640.0f, 480.0f, 0.0f, 1.0f); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); /* For feature levels greater than or equal to 11_0, a negative top left * corner shifts the bottom right corner by a whole integer. It seems that * floor() is used to round viewport corners to integers. */ quirk = feature_level >= D3D_FEATURE_LEVEL_11_0; set_viewport(context, -0.4f, -0.4f, 640.0f, 480.0f, 0.0f, 1.0f); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad(&test_context, &green); SetRect(&rect, 0, 0, 639, 479); check_texture_sub_resource_color(test_context.backbuffer, 0, &rect, 0xff00ff00, 1); SetRect(&rect, 639, 479, 640, 480); todo_wine_if(quirk) check_texture_sub_resource_color(test_context.backbuffer, 0, &rect, quirk ? 0xffffffff : 0xff00ff00, 1); set_viewport(context, -1.0f / 128.0f, -1.0 / 128.0f, 640.0f, 480.0f, 0.0f, 1.0f); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad(&test_context, &green); SetRect(&rect, 0, 0, 639, 479); check_texture_sub_resource_color(test_context.backbuffer, 0, &rect, 0xff00ff00, 1); SetRect(&rect, 639, 479, 640, 480); todo_wine_if(quirk) check_texture_sub_resource_color(test_context.backbuffer, 0, &rect, quirk ? 0xffffffff : 0xff00ff00, 1); release_test_context(&test_context); } static void test_early_depth_stencil(void) { ID3D11DepthStencilState *depth_stencil_state; D3D11_DEPTH_STENCIL_DESC depth_stencil_desc; ID3D11Texture2D *texture, *depth_texture; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11UnorderedAccessView *uav; ID3D11DeviceContext *context; ID3D11DepthStencilView *dsv; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; static const DWORD ps_code[] = { #if 0 RWTexture2D u; [earlydepthstencil] float4 main() : SV_Target { InterlockedAdd(u[uint2(0, 0)], 1); return float4(1.0f, 1.0f, 1.0f, 1.0f); } #endif 0x43425844, 0xda4325ad, 0xc01d3815, 0xfd610cc9, 0x8ed1e351, 0x00000001, 0x000000ec, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000074, 0x00000050, 0x0000001d, 0x0100286a, 0x0400189c, 0x0011e000, 0x00000001, 0x00003333, 0x03000065, 0x001020f2, 0x00000000, 0x0a0000ad, 0x0011e000, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004001, 0x00000001, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x0100003e, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const UINT values[4] = {0}; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; depth_stencil_desc.DepthEnable = TRUE; depth_stencil_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; depth_stencil_desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; depth_stencil_desc.StencilEnable = FALSE; hr = ID3D11Device_CreateDepthStencilState(device, &depth_stencil_desc, &depth_stencil_state); ok(SUCCEEDED(hr), "Failed to create depth stencil state, hr %#x.\n", hr); texture_desc.Width = 1; texture_desc.Height = 1; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32_SINT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)texture, NULL, &uav); ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_D32_FLOAT; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &depth_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)depth_texture, NULL, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); set_viewport(context, 0.0f, 0.0f, 1.0f, 100.0f, 0.5f, 0.5f); ID3D11DeviceContext_OMSetDepthStencilState(context, depth_stencil_state, 0); ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, 1, &test_context.backbuffer_rtv, dsv, 1, 1, &uav, NULL); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, values); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.6f, 0); draw_quad(&test_context); check_texture_color(texture, 100, 1); draw_quad(&test_context); check_texture_color(texture, 200, 1); check_texture_float(depth_texture, 0.6f, 1); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.3f, 0); draw_quad(&test_context); draw_quad(&test_context); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.55f, 0); draw_quad(&test_context); check_texture_color(texture, 300, 1); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.5f, 0); draw_quad(&test_context); check_texture_color(texture, 400, 1); check_texture_float(depth_texture, 0.5f, 1); ID3D11Texture2D_Release(depth_texture); ID3D11DepthStencilView_Release(dsv); ID3D11DepthStencilState_Release(depth_stencil_state); ID3D11PixelShader_Release(ps); ID3D11Texture2D_Release(texture); ID3D11UnorderedAccessView_Release(uav); release_test_context(&test_context); } static void test_conservative_depth_output(void) { struct shader { const DWORD *code; size_t size; }; ID3D11DepthStencilState *depth_stencil_state; D3D11_DEPTH_STENCIL_DESC depth_stencil_desc; struct d3d11_test_context test_context; const struct shader *current_shader; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11DepthStencilView *dsv; ID3D11Texture2D *texture; ID3D11PixelShader *ps; DWORD expected_color; float expected_depth; ID3D11Device *device; struct vec4 ps_depth; ID3D11Buffer *cb; unsigned int i; HRESULT hr; static const DWORD ps_depth_le_code[] = { #if 0 float depth; float4 main(out float out_depth : SV_DepthLessEqual) : SV_Target0 { out_depth = depth; return float4(0.0f, 1.0f, 0.f, 1.0f); } #endif 0x43425844, 0x045c8d00, 0xc49e2ebe, 0x76f6022a, 0xf6996ecc, 0x00000001, 0x00000108, 0x00000003, 0x0000002c, 0x0000003c, 0x00000098, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000054, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000042, 0x00000000, 0x00000000, 0x00000003, 0xffffffff, 0x00000e01, 0x545f5653, 0x65677261, 0x56530074, 0x7065445f, 0x654c6874, 0x71457373, 0x006c6175, 0x58454853, 0x00000068, 0x00000050, 0x0000001a, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000065, 0x00027001, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x05000036, 0x00027001, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; static const struct shader ps_depth_le = {ps_depth_le_code, sizeof(ps_depth_le_code)}; static const DWORD ps_depth_ge_code[] = { #if 0 float depth; float4 main(out float out_depth : SV_DepthGreaterEqual) : SV_Target0 { out_depth = depth; return float4(0.0f, 1.0f, 0.f, 1.0f); } #endif 0x43425844, 0xd17af83e, 0xa32c01cc, 0x0d8e9665, 0xe6dc17c2, 0x00000001, 0x0000010c, 0x00000003, 0x0000002c, 0x0000003c, 0x0000009c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000058, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000042, 0x00000000, 0x00000000, 0x00000003, 0xffffffff, 0x00000e01, 0x545f5653, 0x65677261, 0x56530074, 0x7065445f, 0x72476874, 0x65746165, 0x75714572, 0xab006c61, 0x58454853, 0x00000068, 0x00000050, 0x0000001a, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000065, 0x00026001, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x05000036, 0x00026001, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; static const struct shader ps_depth_ge = {ps_depth_ge_code, sizeof(ps_depth_ge_code)}; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const struct { const struct shader *ps; float vs_depth; float ps_depth; BOOL passes_depth_test; } tests[] = { {&ps_depth_le, 0.7f, 0.7f, TRUE}, {&ps_depth_le, 0.7f, 0.4f, FALSE}, {&ps_depth_le, 0.4f, 0.4f, FALSE}, /* {&ps_depth_le, 0.4f, 0.6f, FALSE}, undefined result */ {&ps_depth_ge, 0.7f, 0.7f, TRUE}, /* {&ps_depth_ge, 0.7f, 0.4f, TRUE}, undefined result */ {&ps_depth_ge, 0.4f, 0.4f, FALSE}, {&ps_depth_ge, 0.4f, 0.6f, TRUE}, }; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(ps_depth), NULL); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_D32_FLOAT; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, NULL, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); depth_stencil_desc.DepthEnable = TRUE; depth_stencil_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depth_stencil_desc.DepthFunc = D3D11_COMPARISON_GREATER_EQUAL; depth_stencil_desc.StencilEnable = FALSE; hr = ID3D11Device_CreateDepthStencilState(device, &depth_stencil_desc, &depth_stencil_state); ok(SUCCEEDED(hr), "Failed to create depth stencil state, hr %#x.\n", hr); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, dsv); ID3D11DeviceContext_OMSetDepthStencilState(context, depth_stencil_state, 0); ps = NULL; current_shader = NULL; for (i = 0; i < ARRAY_SIZE(tests); ++i) { if (current_shader != tests[i].ps) { if (ps) ID3D11PixelShader_Release(ps); current_shader = tests[i].ps; hr = ID3D11Device_CreatePixelShader(device, current_shader->code, current_shader->size, NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); } ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 0.5f, 0); ps_depth.x = tests[i].ps_depth; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_depth, 0, 0); draw_quad_z(&test_context, tests[i].vs_depth); expected_color = tests[i].passes_depth_test ? 0xff00ff00 : 0xffffffff; expected_depth = tests[i].passes_depth_test ? max(tests[i].vs_depth, tests[i].ps_depth) : 0.5f; check_texture_color(test_context.backbuffer, expected_color, 0); check_texture_float(texture, expected_depth, 1); } ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps); ID3D11DepthStencilView_Release(dsv); ID3D11DepthStencilState_Release(depth_stencil_state); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_format_compatibility(void) { ID3D11Texture2D *dst_texture, *src_texture; D3D11_SUBRESOURCE_DATA resource_data; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; struct resource_readback rb; DWORD colour, expected; ID3D11Device *device; unsigned int i, j; ULONG refcount; HRESULT hr; static const struct { DXGI_FORMAT src_format; DXGI_FORMAT dst_format; size_t texel_size; BOOL success; } test_data[] = { {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, 4, TRUE}, {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 4, TRUE}, {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UINT, 4, TRUE}, {DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_SNORM, 4, TRUE}, {DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SINT, 4, TRUE}, {DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_TYPELESS, 4, TRUE}, {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, 4, FALSE}, {DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R16G16_UINT, 4, FALSE}, {DXGI_FORMAT_R16G16_TYPELESS, DXGI_FORMAT_R16G16_FLOAT, 4, TRUE}, {DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_UNORM, 4, TRUE}, {DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_UINT, 4, TRUE}, {DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_SNORM, 4, TRUE}, {DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16_SINT, 4, TRUE}, {DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_TYPELESS, 4, TRUE}, {DXGI_FORMAT_R16G16_TYPELESS, DXGI_FORMAT_R32_TYPELESS, 4, FALSE}, {DXGI_FORMAT_R32G32_TYPELESS, DXGI_FORMAT_R32G32_FLOAT, 8, TRUE}, {DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_UINT, 8, TRUE}, {DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_SINT, 8, TRUE}, {DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_TYPELESS, 8, TRUE}, }; static const DWORD initial_data[16] = {0}; static const DWORD bitmap_data[] = { 0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00, 0xffff0000, 0xffff00ff, 0xff000000, 0xff7f7f7f, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, }; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } ID3D11Device_GetImmediateContext(device, &context); texture_desc.Height = 4; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; for (i = 0; i < ARRAY_SIZE(test_data); ++i) { unsigned int x, y, texel_dwords; D3D11_BOX box; texture_desc.Width = sizeof(bitmap_data) / (texture_desc.Height * test_data[i].texel_size); texture_desc.Format = test_data[i].src_format; texture_desc.Usage = D3D11_USAGE_IMMUTABLE; resource_data.pSysMem = bitmap_data; resource_data.SysMemPitch = texture_desc.Width * test_data[i].texel_size; resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &src_texture); ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr); texture_desc.Format = test_data[i].dst_format; texture_desc.Usage = D3D11_USAGE_DEFAULT; resource_data.pSysMem = initial_data; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &dst_texture); ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr); set_box(&box, 0, 0, 0, texture_desc.Width - 1, texture_desc.Height - 1, 1); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)dst_texture, 0, 1, 1, 0, (ID3D11Resource *)src_texture, 0, &box); texel_dwords = test_data[i].texel_size / sizeof(DWORD); get_texture_readback(dst_texture, 0, &rb); for (j = 0; j < ARRAY_SIZE(bitmap_data); ++j) { x = j % 4; y = j / 4; colour = get_readback_color(&rb, x, y, 0); expected = test_data[i].success && x >= texel_dwords && y ? bitmap_data[j - (4 + texel_dwords)] : initial_data[j]; ok(colour == expected, "Test %u: Got unexpected colour 0x%08x at (%u, %u), expected 0x%08x.\n", i, colour, x, y, expected); } release_resource_readback(&rb); ID3D11DeviceContext_CopyResource(context, (ID3D11Resource *)dst_texture, (ID3D11Resource *)src_texture); get_texture_readback(dst_texture, 0, &rb); for (j = 0; j < ARRAY_SIZE(bitmap_data); ++j) { x = j % 4; y = j / 4; colour = get_readback_color(&rb, x, y, 0); expected = test_data[i].success ? bitmap_data[j] : initial_data[j]; ok(colour == expected, "Test %u: Got unexpected colour 0x%08x at (%u, %u), expected 0x%08x.\n", i, colour, x, y, expected); } release_resource_readback(&rb); ID3D11Texture2D_Release(dst_texture); ID3D11Texture2D_Release(src_texture); } ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void check_clip_distance(struct d3d11_test_context *test_context, ID3D11Buffer *vb) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; struct vertex { float clip_distance0; float clip_distance1; }; ID3D11DeviceContext *context = test_context->immediate_context; struct resource_readback rb; struct vertex vertices[4]; unsigned int i; RECT rect; for (i = 0; i < ARRAY_SIZE(vertices); ++i) vertices[i].clip_distance0 = 1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context->backbuffer_rtv, white); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(test_context->backbuffer, 0xff00ff00, 1); for (i = 0; i < ARRAY_SIZE(vertices); ++i) vertices[i].clip_distance0 = 0.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context->backbuffer_rtv, white); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(test_context->backbuffer, 0xff00ff00, 1); for (i = 0; i < ARRAY_SIZE(vertices); ++i) vertices[i].clip_distance0 = -1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context->backbuffer_rtv, white); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(test_context->backbuffer, 0xffffffff, 1); for (i = 0; i < ARRAY_SIZE(vertices); ++i) vertices[i].clip_distance0 = i < 2 ? 1.0f : -1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context->backbuffer_rtv, white); ID3D11DeviceContext_Draw(context, 4, 0); get_texture_readback(test_context->backbuffer, 0, &rb); SetRect(&rect, 0, 0, 320, 480); check_readback_data_color(&rb, &rect, 0xff00ff00, 1); SetRect(&rect, 320, 0, 320, 480); check_readback_data_color(&rb, &rect, 0xffffffff, 1); release_resource_readback(&rb); for (i = 0; i < ARRAY_SIZE(vertices); ++i) vertices[i].clip_distance0 = i % 2 ? 1.0f : -1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context->backbuffer_rtv, white); ID3D11DeviceContext_Draw(context, 4, 0); get_texture_readback(test_context->backbuffer, 0, &rb); SetRect(&rect, 0, 0, 640, 240); check_readback_data_color(&rb, &rect, 0xff00ff00, 1); SetRect(&rect, 0, 240, 640, 240); check_readback_data_color(&rb, &rect, 0xffffffff, 1); release_resource_readback(&rb); } static void test_clip_distance(void) { struct d3d11_test_context test_context; ID3D11Buffer *vs_cb, *tess_cb, *gs_cb; D3D_FEATURE_LEVEL feature_level; ID3D11DomainShader *ds = NULL; ID3D11DeviceContext *context; struct resource_readback rb; unsigned int offset, stride; ID3D11HullShader *hs = NULL; ID3D11GeometryShader *gs; ID3D11Device *device; ID3D11Buffer *vb; unsigned int i; HRESULT hr; RECT rect; static const DWORD vs_code[] = { #if 0 bool use_constant; float clip_distance; struct input { float4 position : POSITION; float distance0 : CLIP_DISTANCE0; float distance1 : CLIP_DISTANCE1; }; struct vertex { float4 position : SV_POSITION; float user_clip : CLIP_DISTANCE; float clip : SV_ClipDistance; }; void main(input vin, out vertex vertex) { vertex.position = vin.position; vertex.user_clip = vin.distance0; vertex.clip = vin.distance0; if (use_constant) vertex.clip = clip_distance; } #endif 0x43425844, 0x09dfef58, 0x88570f2e, 0x1ebcf953, 0x9f97e22a, 0x00000001, 0x000001dc, 0x00000003, 0x0000002c, 0x0000009c, 0x00000120, 0x4e475349, 0x00000068, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000059, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000101, 0x00000059, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000001, 0x49534f50, 0x4e4f4954, 0x494c4300, 0x49445f50, 0x4e415453, 0xab004543, 0x4e47534f, 0x0000007c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000e01, 0x0000006a, 0x00000000, 0x00000002, 0x00000003, 0x00000002, 0x00000e01, 0x505f5653, 0x5449534f, 0x004e4f49, 0x50494c43, 0x5349445f, 0x434e4154, 0x56530045, 0x696c435f, 0x73694470, 0x636e6174, 0xabab0065, 0x52444853, 0x000000b4, 0x00010040, 0x0000002d, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x00101012, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000001, 0x04000067, 0x00102012, 0x00000002, 0x00000002, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x00102012, 0x00000001, 0x0010100a, 0x00000001, 0x0b000037, 0x00102012, 0x00000002, 0x0020800a, 0x00000000, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0010100a, 0x00000001, 0x0100003e, }; static const DWORD vs_multiple_code[] = { #if 0 bool use_constant; float clip_distance0; float clip_distance1; struct input { float4 position : POSITION; float distance0 : CLIP_DISTANCE0; float distance1 : CLIP_DISTANCE1; }; struct vertex { float4 position : SV_POSITION; float user_clip : CLIP_DISTANCE; float2 clip : SV_ClipDistance; }; void main(input vin, out vertex vertex) { vertex.position = vin.position; vertex.user_clip = vin.distance0; vertex.clip.x = vin.distance0; if (use_constant) vertex.clip.x = clip_distance0; vertex.clip.y = vin.distance1; if (use_constant) vertex.clip.y = clip_distance1; } #endif 0x43425844, 0xef5cc236, 0xe2fbfa69, 0x560b6591, 0x23037999, 0x00000001, 0x00000214, 0x00000003, 0x0000002c, 0x0000009c, 0x00000120, 0x4e475349, 0x00000068, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000059, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000101, 0x00000059, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000101, 0x49534f50, 0x4e4f4954, 0x494c4300, 0x49445f50, 0x4e415453, 0xab004543, 0x4e47534f, 0x0000007c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000e01, 0x0000006a, 0x00000000, 0x00000002, 0x00000003, 0x00000002, 0x00000c03, 0x505f5653, 0x5449534f, 0x004e4f49, 0x50494c43, 0x5349445f, 0x434e4154, 0x56530045, 0x696c435f, 0x73694470, 0x636e6174, 0xabab0065, 0x52444853, 0x000000ec, 0x00010040, 0x0000003b, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x00101012, 0x00000001, 0x0300005f, 0x00101012, 0x00000002, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000001, 0x04000067, 0x00102032, 0x00000002, 0x00000002, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x00102012, 0x00000001, 0x0010100a, 0x00000001, 0x0b000037, 0x00102012, 0x00000002, 0x0020800a, 0x00000000, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0010100a, 0x00000001, 0x0b000037, 0x00102022, 0x00000002, 0x0020800a, 0x00000000, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0010100a, 0x00000002, 0x0100003e, }; #if 0 bool use_constant; float clip_distance0; float clip_distance1; float tessellation_factor; struct vertex { float4 position : SV_POSITION; float user_clip : CLIP_DISTANCE; float clip : SV_ClipDistance; }; struct patch_constant_data { float edges[4] : SV_TessFactor; float inside[2] : SV_InsideTessFactor; }; patch_constant_data patch_constant() { patch_constant_data output; output.edges[0] = tessellation_factor; output.edges[1] = tessellation_factor; output.edges[2] = tessellation_factor; output.edges[3] = tessellation_factor; output.inside[0] = tessellation_factor; output.inside[1] = tessellation_factor; return output; } [domain("quad")] [outputcontrolpoints(4)] [outputtopology("triangle_cw")] [partitioning("pow2")] [patchconstantfunc("patch_constant")] vertex hs_main(InputPatch input, uint i : SV_OutputControlPointID) { vertex o; o.position = input[i].position; o.user_clip = input[i].user_clip; o.clip = input[i].user_clip; return o; } float4 interpolate_vec(float4 a, float4 b, float4 c, float4 d, float2 tess_coord) { float4 e = lerp(a, b, tess_coord.x); float4 f = lerp(c, d, tess_coord.x); return lerp(e, f, tess_coord.y); } float interpolate(float a, float b, float c, float d, float2 tess_coord) { float e = lerp(a, b, tess_coord.x); float f = lerp(c, d, tess_coord.x); return lerp(e, f, tess_coord.y); } [domain("quad")] vertex ds_main(patch_constant_data input, float2 tess_coord : SV_DomainLocation, const OutputPatch patch) { vertex output; output.position = interpolate_vec(patch[0].position, patch[1].position, patch[2].position, patch[3].position, tess_coord); output.user_clip = interpolate(patch[0].user_clip, patch[1].user_clip, patch[2].user_clip, patch[3].user_clip, tess_coord); output.clip = interpolate(patch[0].clip, patch[1].clip, patch[2].clip, patch[3].clip, tess_coord); if (use_constant) output.clip = clip_distance0; return output; } #endif static const DWORD hs_code[] = { 0x43425844, 0x5a6d7564, 0x5f30a6c9, 0x2cf3b848, 0x5b4c6dca, 0x00000001, 0x00000414, 0x00000004, 0x00000030, 0x000000b4, 0x00000138, 0x000001fc, 0x4e475349, 0x0000007c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000101, 0x0000006a, 0x00000000, 0x00000002, 0x00000003, 0x00000002, 0x00000001, 0x505f5653, 0x5449534f, 0x004e4f49, 0x50494c43, 0x5349445f, 0x434e4154, 0x56530045, 0x696c435f, 0x73694470, 0x636e6174, 0xabab0065, 0x4e47534f, 0x0000007c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000e01, 0x0000006a, 0x00000000, 0x00000002, 0x00000003, 0x00000002, 0x00000e01, 0x505f5653, 0x5449534f, 0x004e4f49, 0x50494c43, 0x5349445f, 0x434e4154, 0x56530045, 0x696c435f, 0x73694470, 0x636e6174, 0xabab0065, 0x47534350, 0x000000bc, 0x00000006, 0x00000008, 0x00000098, 0x00000000, 0x0000000b, 0x00000003, 0x00000000, 0x00000e01, 0x00000098, 0x00000001, 0x0000000b, 0x00000003, 0x00000001, 0x00000e01, 0x00000098, 0x00000002, 0x0000000b, 0x00000003, 0x00000002, 0x00000e01, 0x00000098, 0x00000003, 0x0000000b, 0x00000003, 0x00000003, 0x00000e01, 0x000000a6, 0x00000000, 0x0000000c, 0x00000003, 0x00000004, 0x00000e01, 0x000000a6, 0x00000001, 0x0000000c, 0x00000003, 0x00000005, 0x00000e01, 0x545f5653, 0x46737365, 0x6f746361, 0x56530072, 0x736e495f, 0x54656469, 0x46737365, 0x6f746361, 0xabab0072, 0x58454853, 0x00000210, 0x00030050, 0x00000084, 0x01000071, 0x01002093, 0x01002094, 0x01001895, 0x01001096, 0x01001897, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x01000072, 0x0200005f, 0x00016000, 0x0400005f, 0x002010f2, 0x00000004, 0x00000000, 0x0400005f, 0x00201012, 0x00000004, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x00102012, 0x00000001, 0x03000065, 0x00102012, 0x00000002, 0x02000068, 0x00000001, 0x04000036, 0x00100012, 0x00000000, 0x00016001, 0x07000036, 0x001020f2, 0x00000000, 0x00a01e46, 0x0010000a, 0x00000000, 0x00000000, 0x07000036, 0x00102012, 0x00000001, 0x00a0100a, 0x0010000a, 0x00000000, 0x00000001, 0x07000036, 0x00102012, 0x00000002, 0x00a0100a, 0x0010000a, 0x00000000, 0x00000001, 0x0100003e, 0x01000073, 0x02000099, 0x00000004, 0x0200005f, 0x00017000, 0x04000067, 0x00102012, 0x00000000, 0x0000000b, 0x04000067, 0x00102012, 0x00000001, 0x0000000c, 0x04000067, 0x00102012, 0x00000002, 0x0000000d, 0x04000067, 0x00102012, 0x00000003, 0x0000000e, 0x02000068, 0x00000001, 0x0400005b, 0x00102012, 0x00000000, 0x00000004, 0x04000036, 0x00100012, 0x00000000, 0x0001700a, 0x07000036, 0x00902012, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000000, 0x0100003e, 0x01000073, 0x02000099, 0x00000002, 0x0200005f, 0x00017000, 0x04000067, 0x00102012, 0x00000004, 0x0000000f, 0x04000067, 0x00102012, 0x00000005, 0x00000010, 0x02000068, 0x00000001, 0x0400005b, 0x00102012, 0x00000004, 0x00000002, 0x04000036, 0x00100012, 0x00000000, 0x0001700a, 0x08000036, 0x00d02012, 0x00000004, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000000, 0x0100003e, }; static const DWORD ds_code[] = { 0x43425844, 0xc54dc020, 0x063a9622, 0x6f649eb9, 0xceb1dd36, 0x00000001, 0x0000054c, 0x00000004, 0x00000030, 0x000000b4, 0x00000178, 0x000001fc, 0x4e475349, 0x0000007c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000101, 0x0000006a, 0x00000000, 0x00000002, 0x00000003, 0x00000002, 0x00000101, 0x505f5653, 0x5449534f, 0x004e4f49, 0x50494c43, 0x5349445f, 0x434e4154, 0x56530045, 0x696c435f, 0x73694470, 0x636e6174, 0xabab0065, 0x47534350, 0x000000bc, 0x00000006, 0x00000008, 0x00000098, 0x00000000, 0x0000000b, 0x00000003, 0x00000000, 0x00000001, 0x00000098, 0x00000001, 0x0000000b, 0x00000003, 0x00000001, 0x00000001, 0x00000098, 0x00000002, 0x0000000b, 0x00000003, 0x00000002, 0x00000001, 0x00000098, 0x00000003, 0x0000000b, 0x00000003, 0x00000003, 0x00000001, 0x000000a6, 0x00000000, 0x0000000c, 0x00000003, 0x00000004, 0x00000001, 0x000000a6, 0x00000001, 0x0000000c, 0x00000003, 0x00000005, 0x00000001, 0x545f5653, 0x46737365, 0x6f746361, 0x56530072, 0x736e495f, 0x54656469, 0x46737365, 0x6f746361, 0xabab0072, 0x4e47534f, 0x0000007c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000e01, 0x0000006a, 0x00000000, 0x00000002, 0x00000003, 0x00000002, 0x00000e01, 0x505f5653, 0x5449534f, 0x004e4f49, 0x50494c43, 0x5349445f, 0x434e4154, 0x56530045, 0x696c435f, 0x73694470, 0x636e6174, 0xabab0065, 0x58454853, 0x00000348, 0x00040050, 0x000000d2, 0x01002093, 0x01001895, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0200005f, 0x0001c032, 0x0400005f, 0x002190f2, 0x00000004, 0x00000000, 0x0400005f, 0x00219012, 0x00000004, 0x00000001, 0x0400005f, 0x00219012, 0x00000004, 0x00000002, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000001, 0x04000067, 0x00102012, 0x00000002, 0x00000002, 0x02000068, 0x00000002, 0x0a000000, 0x001000f2, 0x00000000, 0x80219e46, 0x00000041, 0x00000002, 0x00000000, 0x00219e46, 0x00000003, 0x00000000, 0x09000032, 0x001000f2, 0x00000000, 0x0001c006, 0x00100e46, 0x00000000, 0x00219e46, 0x00000002, 0x00000000, 0x0a000000, 0x001000f2, 0x00000001, 0x80219e46, 0x00000041, 0x00000000, 0x00000000, 0x00219e46, 0x00000001, 0x00000000, 0x09000032, 0x001000f2, 0x00000001, 0x0001c006, 0x00100e46, 0x00000001, 0x00219e46, 0x00000000, 0x00000000, 0x08000000, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x80100e46, 0x00000041, 0x00000001, 0x08000032, 0x001020f2, 0x00000000, 0x0001c556, 0x00100e46, 0x00000000, 0x00100e46, 0x00000001, 0x0a000000, 0x00100012, 0x00000000, 0x8021900a, 0x00000041, 0x00000002, 0x00000001, 0x0021900a, 0x00000003, 0x00000001, 0x09000032, 0x00100012, 0x00000000, 0x0001c00a, 0x0010000a, 0x00000000, 0x0021900a, 0x00000002, 0x00000001, 0x0a000000, 0x00100022, 0x00000000, 0x8021900a, 0x00000041, 0x00000000, 0x00000001, 0x0021900a, 0x00000001, 0x00000001, 0x09000032, 0x00100022, 0x00000000, 0x0001c00a, 0x0010001a, 0x00000000, 0x0021900a, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x08000032, 0x00102012, 0x00000001, 0x0001c01a, 0x0010000a, 0x00000000, 0x0010001a, 0x00000000, 0x0a000000, 0x00100012, 0x00000000, 0x8021900a, 0x00000041, 0x00000002, 0x00000002, 0x0021900a, 0x00000003, 0x00000002, 0x09000032, 0x00100012, 0x00000000, 0x0001c00a, 0x0010000a, 0x00000000, 0x0021900a, 0x00000002, 0x00000002, 0x0a000000, 0x00100022, 0x00000000, 0x8021900a, 0x00000041, 0x00000000, 0x00000002, 0x0021900a, 0x00000001, 0x00000002, 0x09000032, 0x00100022, 0x00000000, 0x0001c00a, 0x0010001a, 0x00000000, 0x0021900a, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x08000032, 0x00100012, 0x00000000, 0x0001c01a, 0x0010000a, 0x00000000, 0x0010001a, 0x00000000, 0x0b000037, 0x00102012, 0x00000002, 0x0020800a, 0x00000000, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0010000a, 0x00000000, 0x0100003e, }; static const DWORD gs_code[] = { #if 0 bool use_constant; float clip_distance; struct vertex { float4 position : SV_POSITION; float user_clip : CLIP_DISTANCE; float clip : SV_ClipDistance; }; [maxvertexcount(3)] void main(triangle vertex input[3], inout TriangleStream output) { vertex o; o = input[0]; o.clip = input[0].user_clip; if (use_constant) o.clip = clip_distance; output.Append(o); o = input[1]; o.clip = input[1].user_clip; if (use_constant) o.clip = clip_distance; output.Append(o); o = input[2]; o.clip = input[2].user_clip; if (use_constant) o.clip = clip_distance; output.Append(o); } #endif 0x43425844, 0x9b0823e9, 0xab3ed100, 0xba0ff618, 0x1bbd1cb8, 0x00000001, 0x00000338, 0x00000003, 0x0000002c, 0x000000b0, 0x00000134, 0x4e475349, 0x0000007c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000101, 0x0000006a, 0x00000000, 0x00000002, 0x00000003, 0x00000002, 0x00000001, 0x505f5653, 0x5449534f, 0x004e4f49, 0x50494c43, 0x5349445f, 0x434e4154, 0x56530045, 0x696c435f, 0x73694470, 0x636e6174, 0xabab0065, 0x4e47534f, 0x0000007c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000e01, 0x0000006a, 0x00000000, 0x00000002, 0x00000003, 0x00000002, 0x00000e01, 0x505f5653, 0x5449534f, 0x004e4f49, 0x50494c43, 0x5349445f, 0x434e4154, 0x56530045, 0x696c435f, 0x73694470, 0x636e6174, 0xabab0065, 0x52444853, 0x000001fc, 0x00020040, 0x0000007f, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x05000061, 0x002010f2, 0x00000003, 0x00000000, 0x00000001, 0x0400005f, 0x00201012, 0x00000003, 0x00000001, 0x0400005f, 0x00201012, 0x00000003, 0x00000002, 0x02000068, 0x00000001, 0x0100185d, 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000001, 0x04000067, 0x00102012, 0x00000002, 0x00000002, 0x0200005e, 0x00000003, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000000, 0x00000000, 0x06000036, 0x00102012, 0x00000001, 0x0020100a, 0x00000000, 0x00000001, 0x0c000037, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0020100a, 0x00000000, 0x00000001, 0x05000036, 0x00102012, 0x00000002, 0x0010000a, 0x00000000, 0x01000013, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000001, 0x00000000, 0x06000036, 0x00102012, 0x00000001, 0x0020100a, 0x00000001, 0x00000001, 0x0c000037, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0020100a, 0x00000001, 0x00000001, 0x05000036, 0x00102012, 0x00000002, 0x0010000a, 0x00000000, 0x01000013, 0x06000036, 0x001020f2, 0x00000000, 0x00201e46, 0x00000002, 0x00000000, 0x06000036, 0x00102012, 0x00000001, 0x0020100a, 0x00000002, 0x00000001, 0x0c000037, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0020100a, 0x00000002, 0x00000001, 0x05000036, 0x00102012, 0x00000002, 0x0010000a, 0x00000000, 0x01000013, 0x0100003e, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"CLIP_DISTANCE", 0, DXGI_FORMAT_R32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"CLIP_DISTANCE", 1, DXGI_FORMAT_R32_FLOAT, 1, 4, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; struct { float clip_distance0; float clip_distance1; } vertices[] = { {1.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 1.0f}, }; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const struct vec4 green = {0.0f, 1.0f, 0.0f, 1.0f}; struct { BOOL use_constant; float clip_distance0; float clip_distance1; float tessellation_factor; } cb_data; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; feature_level = ID3D11Device_GetFeatureLevel(device); hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &test_context.input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(vertices), vertices); stride = sizeof(*vertices); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 1, 1, &vb, &stride, &offset); memset(&cb_data, 0, sizeof(cb_data)); cb_data.tessellation_factor = 1.0f; vs_cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(cb_data), &cb_data); ID3D11DeviceContext_VSSetConstantBuffers(context, 0, 1, &vs_cb); tess_cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(cb_data), &cb_data); ID3D11DeviceContext_HSSetConstantBuffers(context, 0, 1, &tess_cb); ID3D11DeviceContext_DSSetConstantBuffers(context, 0, 1, &tess_cb); gs_cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(cb_data), &cb_data); ID3D11DeviceContext_GSSetConstantBuffers(context, 0, 1, &gs_cb); /* vertex shader */ ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad_vs(&test_context, &green, vs_code, sizeof(vs_code)); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); check_clip_distance(&test_context, vb); cb_data.use_constant = TRUE; cb_data.clip_distance0 = -1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vs_cb, 0, NULL, &cb_data, 0, 0); /* tessellation shaders */ if (feature_level >= D3D_FEATURE_LEVEL_11_0) { ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST); hr = ID3D11Device_CreateHullShader(device, hs_code, sizeof(hs_code), NULL, &hs); ok(SUCCEEDED(hr), "Failed to create hull shader, hr %#x.\n", hr); ID3D11DeviceContext_HSSetShader(context, hs, NULL, 0); hr = ID3D11Device_CreateDomainShader(device, ds_code, sizeof(ds_code), NULL, &ds); ok(SUCCEEDED(hr), "Failed to create domain shader, hr %#x.\n", hr); ID3D11DeviceContext_DSSetShader(context, ds, NULL, 0); check_clip_distance(&test_context, vb); cb_data.use_constant = FALSE; cb_data.tessellation_factor = 2.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)tess_cb, 0, NULL, &cb_data, 0, 0); for (i = 0; i < ARRAY_SIZE(vertices); ++i) vertices[i].clip_distance0 = 1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); cb_data.use_constant = TRUE; cb_data.clip_distance0 = -1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)tess_cb, 0, NULL, &cb_data, 0, 0); } else { skip("Tessellation shaders are not supported.\n"); } /* geometry shader */ hr = ID3D11Device_CreateGeometryShader(device, gs_code, sizeof(gs_code), NULL, &gs); ok(SUCCEEDED(hr), "Failed to create geometry shader, hr %#x.\n", hr); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); check_clip_distance(&test_context, vb); cb_data.use_constant = TRUE; cb_data.clip_distance0 = 1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)gs_cb, 0, NULL, &cb_data, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ID3D11DeviceContext_Draw(context, 4, 0); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); /* multiple clip distances */ ID3D11DeviceContext_HSSetShader(context, NULL, NULL, 0); ID3D11DeviceContext_DSSetShader(context, NULL, NULL, 0); ID3D11DeviceContext_GSSetShader(context, NULL, NULL, 0); cb_data.use_constant = FALSE; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vs_cb, 0, NULL, &cb_data, 0, 0); for (i = 0; i < ARRAY_SIZE(vertices); ++i) vertices[i].clip_distance0 = 1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad_vs(&test_context, &green, vs_multiple_code, sizeof(vs_multiple_code)); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); for (i = 0; i < ARRAY_SIZE(vertices); ++i) { vertices[i].clip_distance0 = i < 2 ? 1.0f : -1.0f; vertices[i].clip_distance1 = i % 2 ? 1.0f : -1.0f; } ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad_vs(&test_context, &green, vs_multiple_code, sizeof(vs_multiple_code)); get_texture_readback(test_context.backbuffer, 0, &rb); SetRect(&rect, 0, 0, 320, 240); check_readback_data_color(&rb, &rect, 0xff00ff00, 1); SetRect(&rect, 0, 240, 320, 480); check_readback_data_color(&rb, &rect, 0xffffffff, 1); SetRect(&rect, 320, 0, 640, 480); check_readback_data_color(&rb, &rect, 0xffffffff, 1); release_resource_readback(&rb); cb_data.use_constant = TRUE; cb_data.clip_distance0 = 0.0f; cb_data.clip_distance1 = 0.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vs_cb, 0, NULL, &cb_data, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad_vs(&test_context, &green, vs_multiple_code, sizeof(vs_multiple_code)); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); if (hs) ID3D11HullShader_Release(hs); if (ds) ID3D11DomainShader_Release(ds); ID3D11GeometryShader_Release(gs); ID3D11Buffer_Release(vb); ID3D11Buffer_Release(vs_cb); ID3D11Buffer_Release(tess_cb); ID3D11Buffer_Release(gs_cb); release_test_context(&test_context); } static void test_combined_clip_and_cull_distances(void) { struct d3d11_test_context test_context; ID3D11DeviceContext *context; struct resource_readback rb; unsigned int offset, stride; ID3D11Device *device; unsigned int i, j, k; ID3D11Buffer *vb; HRESULT hr; static const DWORD vs_code[] = { #if 0 struct input { float4 position : POSITION; float clip0 : CLIP_DISTANCE0; float clip1 : CLIP_DISTANCE1; float clip2 : CLIP_DISTANCE2; float clip3 : CLIP_DISTANCE3; float cull0 : CULL_DISTANCE0; float cull1 : CULL_DISTANCE1; float cull2 : CULL_DISTANCE2; float cull3 : CULL_DISTANCE3; }; struct vertex { float4 position : SV_Position; float3 clip0 : SV_ClipDistance1; float3 cull0 : SV_CullDistance1; float clip1 : SV_ClipDistance2; float cull1 : SV_CullDistance2; }; void main(input vin, out vertex vertex) { vertex.position = vin.position; vertex.clip0 = float3(vin.clip0, vin.clip1, vin.clip2); vertex.cull0 = float3(vin.cull0, vin.cull1, vin.cull2); vertex.clip1 = vin.clip3; vertex.cull1 = vin.cull3; } #endif 0x43425844, 0xa24fb3ea, 0x92e2c2b0, 0xb599b1b9, 0xd671f830, 0x00000001, 0x00000374, 0x00000003, 0x0000002c, 0x0000013c, 0x000001f0, 0x4e475349, 0x00000108, 0x00000009, 0x00000008, 0x000000e0, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x000000e9, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000101, 0x000000e9, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000101, 0x000000e9, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000101, 0x000000e9, 0x00000003, 0x00000000, 0x00000003, 0x00000004, 0x00000101, 0x000000f7, 0x00000000, 0x00000000, 0x00000003, 0x00000005, 0x00000101, 0x000000f7, 0x00000001, 0x00000000, 0x00000003, 0x00000006, 0x00000101, 0x000000f7, 0x00000002, 0x00000000, 0x00000003, 0x00000007, 0x00000101, 0x000000f7, 0x00000003, 0x00000000, 0x00000003, 0x00000008, 0x00000101, 0x49534f50, 0x4e4f4954, 0x494c4300, 0x49445f50, 0x4e415453, 0x43004543, 0x5f4c4c55, 0x54534944, 0x45434e41, 0xababab00, 0x4e47534f, 0x000000ac, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000008c, 0x00000000, 0x00000002, 0x00000003, 0x00000001, 0x00000807, 0x0000008c, 0x00000001, 0x00000002, 0x00000003, 0x00000001, 0x00000708, 0x0000009c, 0x00000000, 0x00000003, 0x00000003, 0x00000002, 0x00000807, 0x0000009c, 0x00000001, 0x00000003, 0x00000003, 0x00000002, 0x00000708, 0x505f5653, 0x7469736f, 0x006e6f69, 0x435f5653, 0x4470696c, 0x61747369, 0x0065636e, 0x435f5653, 0x446c6c75, 0x61747369, 0x0065636e, 0x52444853, 0x0000017c, 0x00010040, 0x0000005f, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x00101012, 0x00000001, 0x0300005f, 0x00101012, 0x00000002, 0x0300005f, 0x00101012, 0x00000003, 0x0300005f, 0x00101012, 0x00000004, 0x0300005f, 0x00101012, 0x00000005, 0x0300005f, 0x00101012, 0x00000006, 0x0300005f, 0x00101012, 0x00000007, 0x0300005f, 0x00101012, 0x00000008, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x04000067, 0x00102072, 0x00000001, 0x00000002, 0x04000067, 0x00102082, 0x00000001, 0x00000002, 0x04000067, 0x00102072, 0x00000002, 0x00000003, 0x04000067, 0x00102082, 0x00000002, 0x00000003, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x00102012, 0x00000001, 0x0010100a, 0x00000001, 0x05000036, 0x00102022, 0x00000001, 0x0010100a, 0x00000002, 0x05000036, 0x00102042, 0x00000001, 0x0010100a, 0x00000003, 0x05000036, 0x00102082, 0x00000001, 0x0010100a, 0x00000004, 0x05000036, 0x00102012, 0x00000002, 0x0010100a, 0x00000005, 0x05000036, 0x00102022, 0x00000002, 0x0010100a, 0x00000006, 0x05000036, 0x00102042, 0x00000002, 0x0010100a, 0x00000007, 0x05000036, 0x00102082, 0x00000002, 0x0010100a, 0x00000008, 0x0100003e, }; static const D3D11_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"CLIP_DISTANCE", 0, DXGI_FORMAT_R32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"CLIP_DISTANCE", 1, DXGI_FORMAT_R32_FLOAT, 1, 4, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"CLIP_DISTANCE", 2, DXGI_FORMAT_R32_FLOAT, 1, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"CLIP_DISTANCE", 3, DXGI_FORMAT_R32_FLOAT, 1, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"CULL_DISTANCE", 0, DXGI_FORMAT_R32_FLOAT, 1, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"CULL_DISTANCE", 1, DXGI_FORMAT_R32_FLOAT, 1, 20, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"CULL_DISTANCE", 2, DXGI_FORMAT_R32_FLOAT, 1, 24, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"CULL_DISTANCE", 3, DXGI_FORMAT_R32_FLOAT, 1, 28, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; struct { float clip_distance[4]; float cull_distance[4]; } vertices[4] = { {{1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, {{1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, {{1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, {{1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, }; static const struct test { float vertices[4]; BOOL triangle_visible[2]; } cull_distance_tests[] = { {{-1.0f, 1.0f, 1.0f, 1.0f}, {TRUE, TRUE}}, {{ 1.0f, -1.0f, 1.0f, 1.0f}, {TRUE, TRUE}}, {{ 1.0f, 1.0f, 1.0f, -1.0f}, {TRUE, TRUE}}, {{-1.0f, -1.0f, 1.0f, 1.0f}, {TRUE, TRUE}}, {{-1.0f, 1.0f, -1.0f, 1.0f}, {TRUE, TRUE}}, {{-1.0f, 1.0f, 1.0f, -1.0f}, {TRUE, TRUE}}, {{ 1.0f, -1.0f, -1.0f, 1.0f}, {TRUE, TRUE}}, {{ 1.0f, -1.0f, 1.0f, -1.0f}, {TRUE, TRUE}}, {{ 1.0f, 1.0f, -1.0f, -1.0f}, {TRUE, TRUE}}, {{-1.0f, -1.0f, -1.0f, 1.0f}, {FALSE, TRUE}}, {{-1.0f, -1.0f, 1.0f, -1.0f}, {TRUE, TRUE}}, {{-1.0f, -1.0f, 1.0f, -1.0f}, {TRUE, TRUE}}, {{-1.0f, 1.0f, -1.0f, -1.0f}, {TRUE, TRUE}}, {{ 1.0f, -1.0f, -1.0f, -1.0f}, {TRUE, FALSE}}, {{-1.0f, -1.0f, -1.0f, -1.0f}, {FALSE, FALSE}}, }; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const struct vec4 green = {0.0f, 1.0f, 0.0f, 1.0f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreateInputLayout(device, layout_desc, ARRAY_SIZE(layout_desc), vs_code, sizeof(vs_code), &test_context.input_layout); ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(vertices), vertices); stride = sizeof(*vertices); offset = 0; ID3D11DeviceContext_IASetVertexBuffers(context, 1, 1, &vb, &stride, &offset); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad(&test_context, &green); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); for (i = 0; i < ARRAY_SIZE(vertices->cull_distance); ++i) { for (j = 0; j < ARRAY_SIZE(cull_distance_tests); ++j) { const struct test *test = &cull_distance_tests[j]; unsigned int expected_color[ARRAY_SIZE(test->triangle_visible)]; unsigned int color; for (k = 0; k < ARRAY_SIZE(vertices); ++k) vertices[k].cull_distance[i] = test->vertices[k]; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad_vs(&test_context, &green, vs_code, sizeof(vs_code)); for (k = 0; k < ARRAY_SIZE(expected_color); ++k) expected_color[k] = test->triangle_visible[k] ? 0xff00ff00 : 0xffffffff; if (expected_color[0] == expected_color[1]) { check_texture_color(test_context.backbuffer, *expected_color, 1); } else { get_texture_readback(test_context.backbuffer, 0, &rb); color = get_readback_color(&rb, 160, 240, 0); ok(color == expected_color[0], "Got unexpected color 0x%08x.\n", color); color = get_readback_color(&rb, 480, 240, 0); ok(color == expected_color[1], "Got unexpected color 0x%08x.\n", color); release_resource_readback(&rb); } } for (j = 0; j < ARRAY_SIZE(vertices); ++j) vertices[j].cull_distance[i] = 1.0f; } for (i = 0; i < ARRAY_SIZE(vertices->clip_distance); ++i) { for (j = 0; j < ARRAY_SIZE(vertices); ++j) vertices[j].clip_distance[i] = -1.0f; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad_vs(&test_context, &green, vs_code, sizeof(vs_code)); check_texture_color(test_context.backbuffer, 0xffffffff, 1); for (j = 0; j < ARRAY_SIZE(vertices); ++j) vertices[j].clip_distance[i] = 1.0f; } memset(vertices, 0, sizeof(vertices)); ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)vb, 0, NULL, vertices, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_color_quad_vs(&test_context, &green, vs_code, sizeof(vs_code)); check_texture_color(test_context.backbuffer, 0xff00ff00, 1); ID3D11Buffer_Release(vb); release_test_context(&test_context); } static void test_generate_mips(void) { static const DWORD ps_code[] = { #if 0 Texture2D t; SamplerState s; float4 main(float4 position : SV_POSITION) : SV_Target { float2 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; return t.Sample(s, p); } #endif 0x43425844, 0x1ce9b612, 0xc8176faa, 0xd37844af, 0xdb515605, 0x00000001, 0x00000134, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040, 0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, }; static const DWORD ps_code_3d[] = { #if 0 Texture3D t; SamplerState s; float4 main(float4 position : SV_POSITION) : SV_Target { float3 p; p.x = position.x / 640.0f; p.y = position.y / 480.0f; p.z = 0.5f; return t.Sample(s, p); } #endif 0x43425844, 0xa1e26083, 0xeb45763e, 0x1e5a5089, 0xdfbbe0df, 0x00000001, 0x00000148, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000ac, 0x00000040, 0x0000002b, 0x0300005a, 0x00106000, 0x00000000, 0x04002858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100246, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, }; static const struct { D3D11_RESOURCE_DIMENSION dim; D3D11_SRV_DIMENSION srv_dim; unsigned int array_size; } resource_types[] = { {D3D11_RESOURCE_DIMENSION_BUFFER, D3D11_SRV_DIMENSION_BUFFER, 1}, {D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3D11_SRV_DIMENSION_TEXTURE2D, 1}, {D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3D11_SRV_DIMENSION_TEXTURE2DARRAY, 4}, {D3D11_RESOURCE_DIMENSION_TEXTURE3D, D3D11_SRV_DIMENSION_TEXTURE3D, 1}, }; static const struct { DXGI_FORMAT texture_format; UINT bind_flags; UINT misc_flags; BOOL null_srv; UINT base_level; BOOL expected_creation; BOOL expected_mips; } tests[] = { {DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_SHADER_RESOURCE, 0, TRUE, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0, TRUE, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_SHADER_RESOURCE, 0, FALSE, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0, FALSE, 0, TRUE, FALSE}, {DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_GENERATE_MIPS, FALSE, 0, FALSE, FALSE}, {DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_RENDER_TARGET, D3D11_RESOURCE_MISC_GENERATE_MIPS, FALSE, 0, FALSE, FALSE}, {DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_GENERATE_MIPS, FALSE, 0, TRUE, TRUE}, {DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_GENERATE_MIPS, FALSE, 1, TRUE, TRUE}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_GENERATE_MIPS, FALSE, 1, TRUE, TRUE}, {DXGI_FORMAT_R8G8B8A8_UINT, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_GENERATE_MIPS, TRUE, 1, TRUE, FALSE}, }; static const struct { POINT pos; DWORD color; } expected[] = { {{200, 200}, 0xffff0000}, {{280, 200}, 0xffff0000}, {{360, 200}, 0xff00ff00}, {{440, 200}, 0xff00ff00}, {{200, 270}, 0xff0000ff}, {{280, 270}, 0xff0000ff}, {{360, 270}, 0xff000000}, {{440, 270}, 0xff000000}, }; static const struct vec4 white = {1.0f, 1.0f, 1.0f, 1.0f}; static const RECT r1 = {8, 8, 16, 16}; static const RECT r2 = {16, 8, 24, 16}; static const RECT r3 = {8, 16, 16, 24}; static const RECT r4 = {16, 16, 24, 24}; DWORD *data, *zero_data, color, expected_color; ID3D11ShaderResourceView *srv, *srv_sampling; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture2d_desc; D3D11_TEXTURE3D_DESC texture3d_desc; ID3D11SamplerState *sampler_state; D3D11_SAMPLER_DESC sampler_desc; D3D11_BUFFER_DESC buffer_desc; unsigned int i, j, k, x, y, z; ID3D11PixelShader *ps, *ps_3d; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Resource *resource; ID3D11Device *device; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_code_3d, sizeof(ps_code_3d), NULL, &ps_3d); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = D3D11_FLOAT32_MAX; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler_state); ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler_state); data = heap_alloc(sizeof(*data) * 32 * 32 * 32); for (z = 0; z < 32; ++z) { for (y = 0; y < 32; ++y) { for (x = 0; x < 32; ++x) { DWORD *dst = &data[z * 32 * 32 + y * 32 + x]; POINT pt; pt.x = x; pt.y = y; if (PtInRect(&r1, pt)) *dst = 0xffff0000; else if (PtInRect(&r2, pt)) *dst = 0xff00ff00; else if (PtInRect(&r3, pt)) *dst = 0xff0000ff; else if (PtInRect(&r4, pt)) *dst = 0xff000000; else *dst = 0xffffffff; } } } zero_data = heap_alloc_zero(sizeof(*zero_data) * 16 * 16 * 16); for (i = 0; i < ARRAY_SIZE(resource_types); ++i) { for (j = 0; j < ARRAY_SIZE(tests); ++j) { unsigned int base_multiplier = 1u << tests[j].base_level; if (is_warp_device(device) && tests[j].texture_format == DXGI_FORMAT_R8G8B8A8_UINT) { /* Testing this format seems to break the WARP device. */ skip("Skipping test with DXGI_FORMAT_R8G8B8A8_UINT on WARP.\n"); continue; } switch (resource_types[i].dim) { case D3D11_RESOURCE_DIMENSION_BUFFER: buffer_desc.ByteWidth = 32 * base_multiplier; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = tests[j].bind_flags; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = tests[j].misc_flags; buffer_desc.StructureByteStride = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, (ID3D11Buffer **)&resource); break; case D3D11_RESOURCE_DIMENSION_TEXTURE2D: texture2d_desc.Width = 32 * base_multiplier; texture2d_desc.Height = 32 * base_multiplier; texture2d_desc.MipLevels = 0; texture2d_desc.ArraySize = resource_types[i].array_size; texture2d_desc.Format = tests[j].texture_format; texture2d_desc.SampleDesc.Count = 1; texture2d_desc.SampleDesc.Quality = 0; texture2d_desc.Usage = D3D11_USAGE_DEFAULT; texture2d_desc.BindFlags = tests[j].bind_flags; texture2d_desc.CPUAccessFlags = 0; texture2d_desc.MiscFlags = tests[j].misc_flags; hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, NULL, (ID3D11Texture2D **)&resource); break; case D3D11_RESOURCE_DIMENSION_TEXTURE3D: texture3d_desc.Width = 32 * base_multiplier; texture3d_desc.Height = 32 * base_multiplier; texture3d_desc.Depth = 32 * base_multiplier; texture3d_desc.MipLevels = 0; texture3d_desc.Format = tests[j].texture_format; texture3d_desc.Usage = D3D11_USAGE_DEFAULT; texture3d_desc.BindFlags = tests[j].bind_flags; texture3d_desc.CPUAccessFlags = 0; texture3d_desc.MiscFlags = tests[j].misc_flags; hr = ID3D11Device_CreateTexture3D(device, &texture3d_desc, NULL, (ID3D11Texture3D **)&resource); break; default: break; } if (tests[j].expected_creation && (resource_types[i].dim != D3D11_RESOURCE_DIMENSION_BUFFER || !(tests[j].misc_flags & D3D11_RESOURCE_MISC_GENERATE_MIPS))) { ok(SUCCEEDED(hr), "Resource type %u, test %u: failed to create resource, hr %#x.\n", i, j, hr); } else { ok(hr == E_INVALIDARG, "Resource type %u, test %u: unexpectedly succeeded " "to create resource, hr %#x.\n", i, j, hr); continue; } if (tests[j].null_srv) { hr = ID3D11Device_CreateShaderResourceView(device, resource, NULL, &srv); } else { srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srv_desc.ViewDimension = resource_types[i].srv_dim; switch (resource_types[i].srv_dim) { case D3D11_SRV_DIMENSION_BUFFER: srv_desc.Buffer.ElementOffset = 0; srv_desc.Buffer.ElementWidth = 0; break; case D3D11_SRV_DIMENSION_TEXTURE2D: srv_desc.Texture2D.MostDetailedMip = tests[j].base_level; srv_desc.Texture2D.MipLevels = ~0u; break; case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: srv_desc.Texture2DArray.MostDetailedMip = tests[j].base_level; srv_desc.Texture2DArray.MipLevels = ~0u; srv_desc.Texture2DArray.FirstArraySlice = 0; srv_desc.Texture2DArray.ArraySize = resource_types[i].array_size; break; case D3D11_SRV_DIMENSION_TEXTURE3D: srv_desc.Texture3D.MostDetailedMip = tests[j].base_level; srv_desc.Texture3D.MipLevels = ~0u; break; default: break; } hr = ID3D11Device_CreateShaderResourceView(device, resource, &srv_desc, &srv); } if (resource_types[i].dim == D3D11_RESOURCE_DIMENSION_BUFFER) { ok(FAILED(hr), "Test %u: unexpectedly succeeded to create shader resource view, " "hr %#x.\n", j, hr); ID3D11Resource_Release(resource); continue; } else { ok(SUCCEEDED(hr), "Resource type %u, test %u: failed to create " "shader resource view, hr %#x.\n", i, j, hr); } ID3D11DeviceContext_UpdateSubresource(context, resource, tests[j].base_level, NULL, data, sizeof(*data) * 32, sizeof(*data) * 32 * 32); ID3D11DeviceContext_UpdateSubresource(context, resource, tests[j].base_level + 1, NULL, zero_data, sizeof(*zero_data) * 16, sizeof(*zero_data) * 16 * 16); ID3D11DeviceContext_GenerateMips(context, srv); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &white.x); srv_desc.Format = tests[j].texture_format == DXGI_FORMAT_R8G8B8A8_UINT ? DXGI_FORMAT_R8G8B8A8_UINT : DXGI_FORMAT_R8G8B8A8_UNORM; srv_desc.ViewDimension = resource_types[i].dim == D3D11_RESOURCE_DIMENSION_TEXTURE3D ? D3D11_SRV_DIMENSION_TEXTURE3D : D3D11_SRV_DIMENSION_TEXTURE2D; srv_desc.Texture2D.MostDetailedMip = tests[j].base_level + 1; srv_desc.Texture2D.MipLevels = ~0u; hr = ID3D11Device_CreateShaderResourceView(device, resource, &srv_desc, &srv_sampling); ok(SUCCEEDED(hr), "Resource type %u, test %u: failed to create shader resource view, " "hr %#x.\n", i, j, hr); ID3D11DeviceContext_PSSetShader(context, resource_types[i].dim == D3D11_RESOURCE_DIMENSION_TEXTURE3D ? ps_3d : ps, NULL, 0); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv_sampling); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (k = 0; k < ARRAY_SIZE(expected); ++k) { color = get_readback_color(&rb, expected[k].pos.x, expected[k].pos.y, 0); expected_color = tests[j].expected_mips ? expected[k].color : 0; ok(color == expected_color, "Resource type %u, test %u: pixel (%u, %u) " "has color %08x, expected %08x.\n", i, j, expected[k].pos.x, expected[k].pos.y, color, expected_color); } release_resource_readback(&rb); ID3D11ShaderResourceView_Release(srv_sampling); ID3D11ShaderResourceView_Release(srv); ID3D11Resource_Release(resource); } } /* Test the effect of sRGB views. */ for (y = 0; y < 32; ++y) { for (x = 0; x < 32; ++x) { DWORD *dst = &data[y * 32 + x]; *dst = (x + y) % 2 * 0xffffffff; } } texture2d_desc.Width = 32; texture2d_desc.Height = 32; texture2d_desc.MipLevels = 0; texture2d_desc.ArraySize = 1; texture2d_desc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS; texture2d_desc.SampleDesc.Count = 1; texture2d_desc.SampleDesc.Quality = 0; texture2d_desc.Usage = D3D11_USAGE_DEFAULT; texture2d_desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; texture2d_desc.CPUAccessFlags = 0; texture2d_desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; hr = ID3D11Device_CreateTexture2D(device, &texture2d_desc, NULL, (ID3D11Texture2D **)&resource); ok(SUCCEEDED(hr), "Failed to create resource, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, resource, NULL, &srv); ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srv_desc.Texture2D.MostDetailedMip = 0; srv_desc.Texture2D.MipLevels = ~0u; hr = ID3D11Device_CreateShaderResourceView(device, resource, &srv_desc, &srv); ID3D11DeviceContext_UpdateSubresource(context, resource, 0, NULL, data, sizeof(*data) * 32, sizeof(*data) * 32 * 32); ID3D11DeviceContext_GenerateMips(context, srv); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &white.w); srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srv_desc.Texture2D.MostDetailedMip = 1; srv_desc.Texture2D.MipLevels = ~0u; hr = ID3D11Device_CreateShaderResourceView(device, resource, &srv_desc, &srv_sampling); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv_sampling); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); color = get_readback_color(&rb, 320, 240, 0); ok(compare_color(color, 0x7fbcbcbc, 1) || broken(compare_color(color, 0x7f7f7f7f, 1)), /* AMD */ "Unexpected color %08x.\n", color); release_resource_readback(&rb); ID3D11ShaderResourceView_Release(srv_sampling); ID3D11ShaderResourceView_Release(srv); srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srv_desc.Texture2D.MostDetailedMip = 0; srv_desc.Texture2D.MipLevels = ~0u; hr = ID3D11Device_CreateShaderResourceView(device, resource, &srv_desc, &srv); ID3D11DeviceContext_UpdateSubresource(context, resource, 0, NULL, data, sizeof(*data) * 32, sizeof(*data) * 32 * 32); ID3D11DeviceContext_GenerateMips(context, srv); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, &white.w); srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srv_desc.Texture2D.MostDetailedMip = 1; srv_desc.Texture2D.MipLevels = ~0u; hr = ID3D11Device_CreateShaderResourceView(device, resource, &srv_desc, &srv_sampling); ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv_sampling); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); check_readback_data_color(&rb, NULL, 0x7f7f7f7f, 1); release_resource_readback(&rb); ID3D11ShaderResourceView_Release(srv_sampling); ID3D11ShaderResourceView_Release(srv); ID3D11Resource_Release(resource); heap_free(zero_data); heap_free(data); ID3D11SamplerState_Release(sampler_state); ID3D11PixelShader_Release(ps_3d); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_alpha_to_coverage(void) { struct ps_cb { struct vec2 top; struct vec2 bottom; float alpha[2]; float padding[2]; }; struct d3d11_test_context test_context; ID3D11Texture2D *render_targets[3]; D3D11_TEXTURE2D_DESC texture_desc; ID3D11Texture2D *readback_texture; ID3D11RenderTargetView *rtvs[3]; ID3D11BlendState *blend_state; ID3D11DeviceContext *context; D3D11_BLEND_DESC blend_desc; struct resource_readback rb; UINT quality_level_count; ID3D11PixelShader *ps; struct ps_cb cb_data; ID3D11Device *device; ID3D11Buffer *cb; unsigned int i; HRESULT hr; RECT rect; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const DWORD ps_code[] = { #if 0 float2 top; float2 bottom; float alpha1; float alpha2; void main(float4 position : SV_Position, out float4 target0 : SV_Target0, out float4 target1 : SV_Target1, out float4 target2 : SV_Target2) { float alpha = all(top <= position.xy) && all(position.xy <= bottom) ? 1.0f : 0.0f; target0 = float4(0.0f, 1.0f, 0.0f, alpha); target1 = float4(0.0f, 0.0f, 1.0f, alpha1); target2 = float4(0.0f, 1.0f, 0.0f, alpha2); } #endif 0x43425844, 0x771ff802, 0xca927279, 0x5bdd75ae, 0xf53cb31b, 0x00000001, 0x00000264, 0x00000003, 0x0000002c, 0x00000060, 0x000000c4, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000005c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000050, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000050, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000198, 0x00000040, 0x00000066, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x02000068, 0x00000001, 0x0800001d, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0800001d, 0x00100062, 0x00000000, 0x00208ba6, 0x00000000, 0x00000000, 0x00101106, 0x00000000, 0x07000001, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x07000001, 0x00102082, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x08000036, 0x00102072, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x00102072, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x06000036, 0x00102082, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x08000036, 0x00102072, 0x00000002, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x06000036, 0x00102082, 0x00000002, 0x0020801a, 0x00000000, 0x00000001, 0x0100003e, }; static const DWORD colors[] = {0xff00ff00, 0xbfff0000, 0x8000ff00}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); memset(&blend_desc, 0, sizeof(blend_desc)); blend_desc.AlphaToCoverageEnable = TRUE; blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &blend_state); ok(SUCCEEDED(hr), "Failed to create blend state, hr %#x.\n", hr); ID3D11DeviceContext_OMSetBlendState(context, blend_state, NULL, D3D11_DEFAULT_SAMPLE_MASK); render_targets[0] = test_context.backbuffer; rtvs[0] = test_context.backbuffer_rtv; for (i = 1; i < ARRAY_SIZE(render_targets); ++i) { ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &render_targets[i]); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)render_targets[i], NULL, &rtvs[i]); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); } ID3D11DeviceContext_OMSetRenderTargets(context, ARRAY_SIZE(rtvs), rtvs, NULL); cb_data.top.x = cb_data.top.y = 0.0f; cb_data.bottom.x = cb_data.bottom.y = 200.0f; cb_data.alpha[0] = 0.75; cb_data.alpha[1] = 0.5f; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(cb_data), &cb_data); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); for (i = 0; i < ARRAY_SIZE(rtvs); ++i) ID3D11DeviceContext_ClearRenderTargetView(context, rtvs[i], white); draw_quad(&test_context); for (i = 0; i < ARRAY_SIZE(render_targets); ++i) { DWORD expected_color; assert(i < ARRAY_SIZE(colors)); expected_color = colors[i]; get_texture_readback(render_targets[i], 0, &rb); SetRect(&rect, 0, 0, 200, 200); check_readback_data_color(&rb, &rect, expected_color, 1); SetRect(&rect, 200, 0, 640, 200); todo_wine check_readback_data_color(&rb, &rect, 0xffffffff, 1); SetRect(&rect, 0, 200, 640, 480); todo_wine check_readback_data_color(&rb, &rect, 0xffffffff, 1); release_resource_readback(&rb); if (i > 0) ID3D11Texture2D_Release(render_targets[i]); render_targets[i] = NULL; } ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_R16G16_UNORM; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &render_targets[0]); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)render_targets[0], NULL, &rtvs[0]); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, ARRAY_SIZE(rtvs), rtvs, NULL); ID3D11DeviceContext_ClearRenderTargetView(context, rtvs[0], white); draw_quad(&test_context); get_texture_readback(render_targets[0], 0, &rb); SetRect(&rect, 0, 0, 200, 200); check_readback_data_color(&rb, &rect, 0xffff0000, 1); SetRect(&rect, 200, 0, 640, 200); todo_wine check_readback_data_color(&rb, &rect, 0xffffffff, 1); SetRect(&rect, 0, 200, 640, 480); todo_wine check_readback_data_color(&rb, &rect, 0xffffffff, 1); release_resource_readback(&rb); ID3D11Texture2D_Release(render_targets[0]); for (i = 0; i < ARRAY_SIZE(rtvs); ++i) ID3D11RenderTargetView_Release(rtvs[i]); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); hr = ID3D11Device_CheckMultisampleQualityLevels(device, texture_desc.Format, 4, &quality_level_count); ok(hr == S_OK, "Failed to check multisample quality levels, hr %#x.\n", hr); if (!quality_level_count) { skip("4xMSAA not supported.\n"); goto done; } texture_desc.SampleDesc.Count = 4; texture_desc.SampleDesc.Quality = 0; for (i = 0; i < ARRAY_SIZE(render_targets); ++i) { hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &render_targets[i]); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)render_targets[i], NULL, &rtvs[i]); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); } ID3D11DeviceContext_OMSetRenderTargets(context, ARRAY_SIZE(rtvs), rtvs, NULL); for (i = 0; i < ARRAY_SIZE(rtvs); ++i) ID3D11DeviceContext_ClearRenderTargetView(context, rtvs[i], white); draw_quad(&test_context); texture_desc.SampleDesc.Count = 1; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &readback_texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(render_targets); ++i) { DWORD expected_color; assert(i < ARRAY_SIZE(colors)); expected_color = colors[i]; ID3D11DeviceContext_ResolveSubresource(context, (ID3D11Resource *)readback_texture, 0, (ID3D11Resource *)render_targets[i], 0, texture_desc.Format); get_texture_readback(readback_texture, 0, &rb); SetRect(&rect, 0, 0, 200, 200); check_readback_data_color(&rb, &rect, expected_color, 1); SetRect(&rect, 200, 0, 640, 200); check_readback_data_color(&rb, &rect, 0xffffffff, 1); SetRect(&rect, 0, 200, 640, 480); check_readback_data_color(&rb, &rect, 0xffffffff, 1); release_resource_readback(&rb); } ID3D11Texture2D_Release(readback_texture); for (i = 0; i < ARRAY_SIZE(render_targets); ++i) { ID3D11Texture2D_Release(render_targets[i]); ID3D11RenderTargetView_Release(rtvs[i]); } done: ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps); ID3D11BlendState_Release(blend_state); release_test_context(&test_context); } static void test_unbound_multisample_texture(void) { struct d3d11_test_context test_context; ID3D11DeviceContext *context; ID3D11PixelShader *ps; struct uvec4 cb_data; ID3D11Device *device; ID3D11Buffer *cb; unsigned int i; HRESULT hr; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const DWORD ps_code[] = { #if 0 Texture2DMS t; uint sample_index; float4 main(float4 position : SV_Position) : SV_Target { float3 p; t.GetDimensions(p.x, p.y, p.z); p *= float3(position.x / 640.0f, position.y / 480.0f, 0.0f); /* sample index must be a literal */ switch (sample_index) { case 1: return t.Load(int2(p.xy), 1); case 2: return t.Load(int2(p.xy), 2); case 3: return t.Load(int2(p.xy), 3); default: return t.Load(int2(p.xy), 0); } } #endif 0x43425844, 0x03d62416, 0x1914ee8b, 0xccd08d68, 0x27f42136, 0x00000001, 0x000002f8, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000025c, 0x00000040, 0x00000097, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04042058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0700003d, 0x001000f2, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00101046, 0x00000000, 0x0a000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x0400004c, 0x0020800a, 0x00000000, 0x00000000, 0x03000006, 0x00004001, 0x00000001, 0x0500001b, 0x00100032, 0x00000001, 0x00100046, 0x00000000, 0x08000036, 0x001000c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0900002e, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00107e46, 0x00000000, 0x00004001, 0x00000001, 0x0100003e, 0x03000006, 0x00004001, 0x00000002, 0x0500001b, 0x00100032, 0x00000001, 0x00100046, 0x00000000, 0x08000036, 0x001000c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0900002e, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00107e46, 0x00000000, 0x00004001, 0x00000002, 0x0100003e, 0x03000006, 0x00004001, 0x00000003, 0x0500001b, 0x00100032, 0x00000001, 0x00100046, 0x00000000, 0x08000036, 0x001000c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0900002e, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00107e46, 0x00000000, 0x00004001, 0x00000003, 0x0100003e, 0x0100000a, 0x0500001b, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x08000036, 0x001000c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0900002e, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x00004001, 0x00000000, 0x0100003e, 0x01000017, 0x0100003e, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); memset(&cb_data, 0, sizeof(cb_data)); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(cb_data), &cb_data); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); for (i = 0; i < 4; ++i) { cb_data.x = i; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &cb_data, 0, 0); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0x00000000, 1); } ID3D11Buffer_Release(cb); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_multiple_viewports(void) { struct { unsigned int draw_id; unsigned int padding[3]; } constant; D3D11_VIEWPORT vp[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE + 1]; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Texture2D *texture; ID3D11GeometryShader *gs; ID3D11PixelShader *ps; ID3D11Device *device; ID3D11Buffer *cb; HRESULT hr; static const DWORD gs_code[] = { #if 0 struct gs_in { float4 pos : SV_Position; }; struct gs_out { float4 pos : SV_Position; uint viewport : SV_ViewportArrayIndex; }; [maxvertexcount(6)] void main(triangle gs_in vin[3], inout TriangleStream vout) { gs_out o; for (uint instance_id = 0; instance_id < 2; ++instance_id) { o.viewport = instance_id; for (uint i = 0; i < 3; ++i) { o.pos = vin[i].pos; vout.Append(o); } vout.RestartStrip(); } } #endif 0x43425844, 0xabbb660f, 0x0729bf23, 0x14a9a104, 0x1b454917, 0x00000001, 0x0000021c, 0x00000003, 0x0000002c, 0x00000060, 0x000000c4, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x00000f0f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000005c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000005, 0x00000001, 0x00000001, 0x00000e01, 0x505f5653, 0x7469736f, 0x006e6f69, 0x565f5653, 0x70776569, 0x4174726f, 0x79617272, 0x65646e49, 0xabab0078, 0x52444853, 0x00000150, 0x00020040, 0x00000054, 0x05000061, 0x002010f2, 0x00000003, 0x00000000, 0x00000001, 0x02000068, 0x00000001, 0x0100185d, 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x04000067, 0x00102012, 0x00000001, 0x00000005, 0x0200005e, 0x00000006, 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000002, 0x03040003, 0x0010001a, 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0x00000000, 0x01000030, 0x07000050, 0x00100042, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000003, 0x03040003, 0x0010002a, 0x00000000, 0x07000036, 0x001020f2, 0x00000000, 0x00a01e46, 0x0010001a, 0x00000000, 0x00000000, 0x05000036, 0x00102012, 0x00000001, 0x0010000a, 0x00000000, 0x01000013, 0x0700001e, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x01000009, 0x0700001e, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000001, 0x01000016, 0x0100003e, }; static const DWORD ps_code[] = { #if 0 uint draw_id; float4 main(in float4 pos : SV_Position, in uint viewport : SV_ViewportArrayIndex) : SV_Target { return float4(viewport, draw_id, 0, 0); } #endif 0x43425844, 0x77334c0f, 0x5df3ca7a, 0xc53c00db, 0x3e6e5750, 0x00000001, 0x00000150, 0x00000003, 0x0000002c, 0x00000090, 0x000000c4, 0x4e475349, 0x0000005c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000005, 0x00000001, 0x00000001, 0x00000101, 0x505f5653, 0x7469736f, 0x006e6f69, 0x565f5653, 0x70776569, 0x4174726f, 0x79617272, 0x65646e49, 0xabab0078, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000084, 0x00000040, 0x00000021, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04000864, 0x00101012, 0x00000001, 0x00000005, 0x03000065, 0x001020f2, 0x00000000, 0x05000056, 0x00102012, 0x00000000, 0x0010100a, 0x00000001, 0x06000056, 0x00102022, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0100003e, }; static const struct vec4 expected_values[] = { {0.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 2.0f}, {0.5f, 0.5f}, {0.5f, 0.5f}, {0.0f, 4.0f}, {0.5f, 0.5f}, {0.5f, 0.5f}, {0.0f, 5.0f}, {0.5f, 0.5f}, {1.0f, 5.0f}, {0.5f, 0.5f}, }; static const float clear_color[] = {0.5f, 0.5f, 0.0f, 0.0f}; ID3D11RasterizerState *rasterizer_state; D3D11_RASTERIZER_DESC rasterizer_desc; unsigned int count, i; D3D11_RECT rects[2]; RECT rect; int width; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; memset(&constant, 0, sizeof(constant)); cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constant), &constant); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); hr = ID3D11Device_CreateGeometryShader(device, gs_code, sizeof(gs_code), NULL, &gs); ok(SUCCEEDED(hr), "Failed to create geometry shader, hr %#x.\n", hr); ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0); hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); texture_desc.Width = 32; texture_desc.Height = 32; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); width = texture_desc.Width / 2; vp[0].TopLeftX = 0.0f; vp[0].TopLeftY = 0.0f; vp[0].Width = width; vp[0].Height = texture_desc.Height; vp[0].MinDepth = 0.0f; vp[0].MaxDepth = 1.0f; vp[1] = vp[0]; vp[1].TopLeftX = width; vp[1].Width = width; ID3D11DeviceContext_RSSetViewports(context, 2, vp); count = enable_debug_layer ? ARRAY_SIZE(vp) - 1 : ARRAY_SIZE(vp); ID3D11DeviceContext_RSGetViewports(context, &count, vp); ok(count == 2, "Unexpected viewport count %d.\n", count); constant.draw_id = 0; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); constant.draw_id = 1; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); SetRect(&rect, 0, 0, width - 1, texture_desc.Height - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[0], 1); SetRect(&rect, width, 0, 2 * width - 1, texture_desc.Height - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[1], 1); /* One viewport. */ ID3D11DeviceContext_ClearRenderTargetView(context, rtv, clear_color); ID3D11DeviceContext_RSSetViewports(context, 1, vp); constant.draw_id = 2; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); SetRect(&rect, 0, 0, width - 1, texture_desc.Height - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[2], 1); SetRect(&rect, width, 0, 2 * width - 1, texture_desc.Height - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[3], 1); /* Reset viewports. */ ID3D11DeviceContext_ClearRenderTargetView(context, rtv, clear_color); ID3D11DeviceContext_RSSetViewports(context, 0, NULL); constant.draw_id = 3; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); check_texture_sub_resource_vec4(texture, 0, NULL, &expected_values[4], 1); /* Two viewports, only first scissor rectangle set. */ memset(&rasterizer_desc, 0, sizeof(rasterizer_desc)); rasterizer_desc.FillMode = D3D11_FILL_SOLID; rasterizer_desc.CullMode = D3D11_CULL_BACK; rasterizer_desc.DepthClipEnable = TRUE; rasterizer_desc.ScissorEnable = TRUE; hr = ID3D11Device_CreateRasterizerState(device, &rasterizer_desc, &rasterizer_state); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ID3D11DeviceContext_RSSetState(context, rasterizer_state); ID3D11RasterizerState_Release(rasterizer_state); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, clear_color); ID3D11DeviceContext_RSSetViewports(context, 2, vp); SetRect(&rects[0], 0, 0, width, texture_desc.Height / 2); memset(&rects[1], 0, sizeof(*rects)); ID3D11DeviceContext_RSSetScissorRects(context, 1, rects); constant.draw_id = 4; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); SetRect(&rect, 0, 0, width - 1, texture_desc.Height / 2 - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[5], 1); SetRect(&rect, 0, texture_desc.Height / 2, width - 1, texture_desc.Height - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[6], 1); SetRect(&rect, width, 0, 2 * width - 1, texture_desc.Height - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[7], 1); /* Set both rectangles. */ SetRect(&rects[0], 0, 0, width, texture_desc.Height / 2); SetRect(&rects[1], width, 0, 2 * width, texture_desc.Height / 2); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, clear_color); ID3D11DeviceContext_RSSetScissorRects(context, 2, rects); constant.draw_id = 5; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); SetRect(&rect, 0, 0, width - 1, texture_desc.Height / 2 - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[8], 1); SetRect(&rect, 0, texture_desc.Height / 2, width - 1, texture_desc.Height - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[9], 1); SetRect(&rect, width, 0, 2 * width - 1, texture_desc.Height / 2 - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[10], 1); SetRect(&rect, width, texture_desc.Height / 2, 2 * width - 1, texture_desc.Height - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[11], 1); if (enable_debug_layer) goto done; /* Viewport count exceeding maximum value. */ ID3D11DeviceContext_RSSetViewports(context, 1, vp); vp[0].TopLeftX = 1.0f; vp[0].TopLeftY = 0.0f; vp[0].Width = width; vp[0].Height = texture_desc.Height; vp[0].MinDepth = 0.0f; vp[0].MaxDepth = 1.0f; for (i = 1; i < ARRAY_SIZE(vp); ++i) { vp[i] = vp[0]; } ID3D11DeviceContext_RSSetViewports(context, ARRAY_SIZE(vp), vp); count = ARRAY_SIZE(vp); memset(vp, 0, sizeof(vp)); ID3D11DeviceContext_RSGetViewports(context, &count, vp); ok(count == 1, "Unexpected viewport count %d.\n", count); ok(vp[0].TopLeftX == 0.0f && vp[0].Width == width, "Unexpected viewport.\n"); done: ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(texture); ID3D11Buffer_Release(cb); ID3D11GeometryShader_Release(gs); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_multisample_resolve(void) { struct d3d11_test_context test_context; D3D11_RENDER_TARGET_VIEW_DESC rtv_desc; ID3D11Texture2D *texture, *ms_texture; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Device *device; unsigned int i; HRESULT hr; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const struct vec4 green = {0.0f, 1.0f, 0.0f, 1.0f}; static const struct vec4 color = {0.25f, 0.5f, 0.75f, 1.0f}; static const struct { DXGI_FORMAT src_format; DXGI_FORMAT dst_format; DXGI_FORMAT format; DXGI_FORMAT rtv_format; const struct vec4 *color; DWORD expected_color; BOOL todo; } tests[] = { {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, &green, 0xff00ff00}, {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &green, 0xff00ff00}, {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, &color, 0xffbf7f40}, {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &color, 0xffe1bc89}, {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &green, 0xff00ff00}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &green, 0xff00ff00}, {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &color, 0xffe1bc89, TRUE}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &color, 0xffe1bc89}, {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, &green, 0xff00ff00}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, &green, 0xff00ff00}, {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, &color, 0xffbf7f40}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, &color, 0xffbf7f40}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, &green, 0xff00ff00}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, &color, 0xffbf7f40}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &green, 0xff00ff00}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &color, 0xffe1bc89}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &green, 0xff00ff00}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &color, 0xffe1bc89}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM, &green, 0xff00ff00}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM, &color, 0xffbf7f40}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_TYPELESS, 4, &i); ok(hr == S_OK, "Failed to check multisample quality levels, hr %#x.\n", hr); if (!i) { skip("4xMSAA not supported.\n"); release_test_context(&test_context); return; } for (i = 0; i < ARRAY_SIZE(tests); ++i) { ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = tests[i].dst_format; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); texture_desc.Format = tests[i].src_format; texture_desc.SampleDesc.Count = 4; texture_desc.SampleDesc.Quality = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &ms_texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); rtv_desc.Format = tests[i].rtv_format; rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)ms_texture, &rtv_desc, &rtv); ok(hr == S_OK, "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, white); draw_color_quad(&test_context, tests[i].color); ID3D11DeviceContext_ResolveSubresource(context, (ID3D11Resource *)texture, 0, (ID3D11Resource *)ms_texture, 0, tests[i].format); todo_wine_if(tests[i].todo) check_texture_color(texture, tests[i].expected_color, 2); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(ms_texture); ID3D11Texture2D_Release(texture); } release_test_context(&test_context); } static void test_sample_shading(void) { struct shader { const DWORD *code; size_t size; }; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; struct d3d11_test_context test_context; struct swapchain_desc swapchain_desc; D3D11_TEXTURE2D_DESC texture_desc; ID3D11UnorderedAccessView *uav; D3D11_BUFFER_DESC buffer_desc; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; struct resource_readback rb; ID3D11Buffer *buffer, *cb; ID3D11Texture2D *texture; struct uvec4 ps_constant; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int data; unsigned int i; HRESULT hr; static const DWORD ps_unused_sample_index_code[] = { #if 0 RWByteAddressBuffer u; float4 main(uint id : SV_SampleIndex) : SV_Target { u.InterlockedAdd(0, 1); return float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x41e4574b, 0x1e6441d6, 0x5e756375, 0xacd5dc27, 0x00000001, 0x00000104, 0x00000003, 0x0000002c, 0x00000064, 0x00000098, 0x4e475349, 0x00000030, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x0000000a, 0x00000001, 0x00000000, 0x00000001, 0x535f5653, 0x6c706d61, 0x646e4965, 0xab007865, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000064, 0x00000050, 0x00000019, 0x0100086a, 0x0300009d, 0x0011e000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000000, 0x00004001, 0x00000001, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const struct shader ps_unused_sample_index = {ps_unused_sample_index_code, sizeof(ps_unused_sample_index_code)}; static const DWORD ps_sample_index_code[] = { #if 0 RWByteAddressBuffer u; float4 main(uint id : SV_SampleIndex) : SV_Target { u.InterlockedAdd(0, 1); u.InterlockedAdd(4, id); return float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x943ab9ed, 0x91520b4a, 0xb75df9d0, 0x692cd3e6, 0x00000001, 0x00000130, 0x00000003, 0x0000002c, 0x00000064, 0x00000098, 0x4e475349, 0x00000030, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x0000000a, 0x00000001, 0x00000000, 0x00000101, 0x535f5653, 0x6c706d61, 0x646e4965, 0xab007865, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000090, 0x00000050, 0x00000024, 0x0100086a, 0x0300009d, 0x0011e000, 0x00000001, 0x04000863, 0x00101012, 0x00000000, 0x0000000a, 0x03000065, 0x001020f2, 0x00000000, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000000, 0x00004001, 0x00000001, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000004, 0x0010100a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const struct shader ps_sample_index = {ps_sample_index_code, sizeof(ps_sample_index_code)}; static const DWORD ps_samplepos_code[] = { #if 0 Texture2DMS t; RWByteAddressBuffer u; float4 main() : SV_Target { float2 sample_position = t.GetSamplePosition(0); u.InterlockedAdd(0, 1); u.InterlockedAdd(4, sample_position.x + sample_position.y); return float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x9ec7f344, 0x588f5863, 0x436c0531, 0x69dc54bb, 0x00000001, 0x00000160, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000e8, 0x00000050, 0x0000003a, 0x0100086a, 0x04002058, 0x00107000, 0x00000000, 0x00005555, 0x0300009d, 0x0011e000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000000, 0x00004001, 0x00000001, 0x0800006e, 0x00100032, 0x00000000, 0x00107046, 0x00000000, 0x00004001, 0x00000000, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0500001c, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000004, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const struct shader ps_samplepos = {ps_samplepos_code, sizeof(ps_samplepos_code)}; static const DWORD ps_samplepos_rasterizer_code[] = { #if 0 RWByteAddressBuffer u; float4 main() : SV_Target { float2 sample_position = GetRenderTargetSamplePosition(0); u.InterlockedAdd(0, 1); u.InterlockedAdd(4, sample_position.x + sample_position.y); return float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0xe31795d9, 0x4e9951da, 0xc1713913, 0xfb12da31, 0x00000001, 0x00000148, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000d0, 0x00000050, 0x00000034, 0x0100086a, 0x0300009d, 0x0011e000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000000, 0x00004001, 0x00000001, 0x0600006e, 0x00100032, 0x00000000, 0x0000e046, 0x00004001, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0500001c, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000004, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const struct shader ps_samplepos_rasterizer = {ps_samplepos_rasterizer_code, sizeof(ps_samplepos_rasterizer_code)}; static const DWORD ps_samplepos_indexed_code[] = { #if 0 RWByteAddressBuffer u; float4 main(uint id : SV_SampleIndex) : SV_Target { float2 sample_position = GetRenderTargetSamplePosition(id); u.InterlockedAdd(0, 1); u.InterlockedAdd(4, sample_position.x + sample_position.y); return float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x4b501464, 0x0cd4f636, 0x36428677, 0x6db6b4fb, 0x00000001, 0x00000180, 0x00000003, 0x0000002c, 0x00000064, 0x00000098, 0x4e475349, 0x00000030, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x0000000a, 0x00000001, 0x00000000, 0x00000101, 0x535f5653, 0x6c706d61, 0x646e4965, 0xab007865, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000e0, 0x00000050, 0x00000038, 0x0100086a, 0x0300009d, 0x0011e000, 0x00000001, 0x04000863, 0x00101012, 0x00000000, 0x0000000a, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000000, 0x00004001, 0x00000001, 0x0600006e, 0x00100032, 0x00000000, 0x0000e046, 0x0010100a, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0500001c, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000004, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const struct shader ps_samplepos_indexed = {ps_samplepos_indexed_code, sizeof(ps_samplepos_indexed_code)}; static const DWORD ps_sampleinfo_code[] = { #if 0 Texture2DMS t; RWByteAddressBuffer u; float4 main() : SV_Target { uint width, height, sample_count; t.GetDimensions(width, height, sample_count); u.InterlockedAdd(0, 1); u.InterlockedAdd(4, sample_count); return float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x4e4f4065, 0x20d88902, 0xd4750e8c, 0x652b8c04, 0x00000001, 0x00000124, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000ac, 0x00000050, 0x0000002b, 0x0100086a, 0x04002058, 0x00107000, 0x00000000, 0x00005555, 0x0300009d, 0x0011e000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000000, 0x00004001, 0x00000001, 0x0500086f, 0x00100012, 0x00000000, 0x0010700a, 0x00000000, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000004, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const struct shader ps_sampleinfo = {ps_sampleinfo_code, sizeof(ps_sampleinfo_code)}; static const DWORD ps_sampleinfo_rasterizer_code[] = { #if 0 RWByteAddressBuffer u; float4 main() : SV_Target { uint sample_count = GetRenderTargetSampleCount(); u.InterlockedAdd(0, 1); u.InterlockedAdd(4, sample_count); return float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0xfbbd8619, 0x9c2654c8, 0xb385363a, 0x4aacd10f, 0x00000001, 0x00000110, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000098, 0x00000050, 0x00000026, 0x0100086a, 0x0300009d, 0x0011e000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000000, 0x00004001, 0x00000001, 0x0400086f, 0x00100012, 0x00000000, 0x0000e00a, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000004, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const struct shader ps_sampleinfo_rasterizer = {ps_sampleinfo_rasterizer_code, sizeof(ps_sampleinfo_rasterizer_code)}; static const DWORD ps_sample_code[] = { #if 0 RWByteAddressBuffer u; float4 main(sample float4 position : SV_Position) : SV_Target { u.InterlockedAdd(0, 1); u.InterlockedAdd(4, position.x); return float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0x46ecbadb, 0xedccbea6, 0x236d7923, 0x0c356c8c, 0x00000001, 0x00000148, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000010f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000ac, 0x00000050, 0x0000002b, 0x0100086a, 0x0300009d, 0x0011e000, 0x00000001, 0x04003864, 0x00101012, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000000, 0x00004001, 0x00000001, 0x0500001c, 0x00100012, 0x00000000, 0x0010100a, 0x00000000, 0x070000ad, 0x0011e000, 0x00000001, 0x00004001, 0x00000004, 0x0010000a, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const struct shader ps_sample = {ps_sample_code, sizeof(ps_sample_code)}; static const DWORD ps_color_code[] = { #if 0 float4 main(uint id : SV_SampleIndex) : SV_Target { switch (id) { case 0: return float4(1.0f, 0.0f, 0.0f, 1.0f); case 1: return float4(0.0f, 1.0f, 0.0f, 1.0f); case 2: return float4(0.0f, 0.0f, 1.0f, 1.0f); default: return float4(0.0f, 0.0f, 0.0f, 1.0f); } } #endif 0x43425844, 0x94c35f48, 0x04c6b0f7, 0x407d8214, 0xc24f01e5, 0x00000001, 0x00000194, 0x00000003, 0x0000002c, 0x00000064, 0x00000098, 0x4e475349, 0x00000030, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x0000000a, 0x00000001, 0x00000000, 0x00000101, 0x535f5653, 0x6c706d61, 0x646e4965, 0xab007865, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000f4, 0x00000050, 0x0000003d, 0x0100086a, 0x04000863, 0x00101012, 0x00000000, 0x0000000a, 0x03000065, 0x001020f2, 0x00000000, 0x0300004c, 0x0010100a, 0x00000000, 0x03000006, 0x00004001, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, 0x03000006, 0x00004001, 0x00000001, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, 0x03000006, 0x00004001, 0x00000002, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x0100003e, 0x0100000a, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, 0x01000017, 0x0100003e, }; static const DWORD ps_resolve_code[] = { #if 0 Texture2DMS t; uint sample; uint rt_size; float4 main(float4 position : SV_Position) : SV_Target { float3 p; t.GetDimensions(p.x, p.y, p.z); p *= float3(position.x / rt_size, position.y / rt_size, 0); return t.Load((int2)p.xy, sample); } #endif 0x43425844, 0x68a4590b, 0xc1ec3070, 0x1b957c43, 0x0c080741, 0x00000001, 0x000001c8, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x0000012c, 0x00000050, 0x0000004b, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04002058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x06000056, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0700000e, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00100006, 0x00000000, 0x8900003d, 0x80000102, 0x00155543, 0x001000c2, 0x00000000, 0x00004001, 0x00000000, 0x001074e6, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00100ae6, 0x00000000, 0x0500001b, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x08000036, 0x001000c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8c00002e, 0x80000102, 0x00155543, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; static const struct { const struct shader *ps; BOOL sample_shading; BOOL todo; BOOL broken; } tests[] = { {&ps_unused_sample_index, FALSE, FALSE, TRUE /* broken on Nvidia */}, {&ps_sample_index, TRUE}, {&ps_samplepos, FALSE}, {&ps_samplepos_rasterizer, FALSE}, {&ps_samplepos_indexed, TRUE, TRUE}, {&ps_sampleinfo, FALSE}, {&ps_sampleinfo_rasterizer, FALSE}, {&ps_sample, TRUE, TRUE, TRUE /* broken on Intel */}, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const unsigned int zero[4] = {0}; swapchain_desc.windowed = TRUE; swapchain_desc.buffer_count = 1; swapchain_desc.width = 32; swapchain_desc.height = 32; swapchain_desc.swap_effect = DXGI_SWAP_EFFECT_DISCARD; swapchain_desc.flags = 0; if (!init_test_context_ext(&test_context, &feature_level, &swapchain_desc)) return; device = test_context.device; context = test_context.immediate_context; ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.SampleDesc.Count = 4; texture_desc.SampleDesc.Quality = 0; texture_desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(hr == S_OK, "Failed to create render target view, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(hr == S_OK, "Failed to create shader resource view, hr %#x.\n", hr); buffer_desc.ByteWidth = 1024; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(hr == S_OK, "Failed to create buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 256; U(uav_desc).Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(tests); ++i) { hr = ID3D11Device_CreatePixelShader(device, tests[i].ps->code, tests[i].ps->size, NULL, &ps); ok(hr == S_OK, "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, zero); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, 1, &test_context.backbuffer_rtv, NULL, 1, 1, &uav, NULL); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); get_buffer_readback(buffer, &rb); data = get_readback_color(&rb, 0, 0, 0); ok(1024 <= data && data <= 1056, "Test %u: Got unexpected value %u.\n", i, data); release_resource_readback(&rb); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, zero); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, white); ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, 1, &rtv, NULL, 1, 1, &uav, NULL); draw_quad(&test_context); get_buffer_readback(buffer, &rb); data = get_readback_color(&rb, 0, 0, 0); todo_wine_if(tests[i].todo) { if (tests[i].sample_shading) { ok(4096 <= data || broken(tests[i].broken && data >= 1024), "Test %u: Got unexpected value %u.\n", i, data); } else { ok((1024 <= data && data <= 1056) || broken(tests[i].broken && data >= 4096), "Test %u: Got unexpected value %u.\n", i, data); } } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); } if (is_warp_device(device)) { skip("Sample shading tests fail on WARP.\n"); goto done; } hr = ID3D11Device_CreatePixelShader(device, ps_color_code, sizeof(ps_color_code), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11PixelShader_Release(ps); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, white); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); draw_quad(&test_context); ID3D11DeviceContext_ResolveSubresource(context, (ID3D11Resource *)test_context.backbuffer, 0, (ID3D11Resource *)texture, 0, texture_desc.Format); check_texture_color(test_context.backbuffer, 0xff404040, 2); hr = ID3D11Device_CreatePixelShader(device, ps_resolve_code, sizeof(ps_resolve_code), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11PixelShader_Release(ps); ps_constant.x = 0; ps_constant.y = texture_desc.Width; cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(ps_constant), &ps_constant); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, NULL); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff0000ff, 0); ps_constant.x = 1; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); ps_constant.x = 2; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xffff0000, 0); ps_constant.x = 3; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &ps_constant, 0, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff000000, 0); ID3D11Buffer_Release(cb); done: ID3D11Buffer_Release(buffer); ID3D11UnorderedAccessView_Release(uav); ID3D11RenderTargetView_Release(rtv); ID3D11ShaderResourceView_Release(srv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_sample_mask(void) { static const DWORD ps_code[] = { #if 0 float4 main(in float4 pos : SV_Position, out uint sample_mask : SV_Coverage) : SV_Target { sample_mask = 0x5; return float4(1.0, 1.0, 1.0, 1.0); } #endif 0x43425844, 0x196779a9, 0xda85988a, 0xb7f0a0b6, 0xb30dd6ba, 0x00000001, 0x00000114, 0x00000003, 0x0000002c, 0x00000060, 0x000000b8, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000042, 0x00000000, 0x00000000, 0x00000001, 0xffffffff, 0x00000e01, 0x545f5653, 0x65677261, 0x56530074, 0x766f435f, 0x67617265, 0xabab0065, 0x58454853, 0x00000054, 0x00000050, 0x00000015, 0x0100086a, 0x03000065, 0x001020f2, 0x00000000, 0x02000065, 0x0000f000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x04000036, 0x0000f001, 0x00004001, 0x00000005, 0x0100003e, }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const float black[] = {0.0f, 0.0f, 0.0f, 0.0f}; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; UINT quality_levels; HRESULT hr; if (!init_test_context(&test_context, &feature_level)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CheckMultisampleQualityLevels(device, DXGI_FORMAT_R8G8B8A8_TYPELESS, 4, &quality_levels); ok(hr == S_OK, "Failed to check multisample quality levels, hr %#x.\n", hr); if (!quality_levels) { skip("4xMSAA not supported.\n"); release_test_context(&test_context); return; } hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.SampleDesc.Count = 4; texture_desc.SampleDesc.Quality = 0; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(hr == S_OK, "Failed to create render target view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); ID3D11DeviceContext_ResolveSubresource(context, (ID3D11Resource *)test_context.backbuffer, 0, (ID3D11Resource *)texture, 0, texture_desc.Format); check_texture_color(test_context.backbuffer, 0x7f7f7f7f, 1); ID3D11DeviceContext_OMSetBlendState(context, NULL, NULL, 0xb); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); draw_quad(&test_context); ID3D11DeviceContext_ResolveSubresource(context, (ID3D11Resource *)test_context.backbuffer, 0, (ID3D11Resource *)texture, 0, texture_desc.Format); check_texture_color(test_context.backbuffer, 0x3f3f3f3f, 1); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(texture); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_depth_clip(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; D3D11_RASTERIZER_DESC rs_desc; ID3D11DeviceContext *context; ID3D11DepthStencilView *dsv; ID3D11RasterizerState *rs; ID3D11Texture2D *texture; ID3D11Device *device; unsigned int count; D3D11_VIEWPORT vp; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_D32_FLOAT; texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)texture, NULL, &dsv); ok(SUCCEEDED(hr), "Failed to create depth stencil view, hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, dsv); count = 1; ID3D11DeviceContext_RSGetViewports(context, &count, &vp); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); set_viewport(context, vp.TopLeftX, vp.TopLeftY, vp.Width, vp.Height, 0.4f, 0.6f); draw_quad_z(&test_context, 2.0f); check_texture_float(texture, 1.0f, 1); draw_quad_z(&test_context, 0.5f); check_texture_float(texture, 0.5f, 1); draw_quad_z(&test_context, -1.0f); check_texture_float(texture, 0.5f, 1); rs_desc.FillMode = D3D11_FILL_SOLID; rs_desc.CullMode = D3D11_CULL_BACK; rs_desc.FrontCounterClockwise = FALSE; rs_desc.DepthBias = 0; rs_desc.DepthBiasClamp = 0.0f; rs_desc.SlopeScaledDepthBias = 0.0f; rs_desc.DepthClipEnable = FALSE; rs_desc.ScissorEnable = FALSE; rs_desc.MultisampleEnable = FALSE; rs_desc.AntialiasedLineEnable = FALSE; hr = ID3D11Device_CreateRasterizerState(device, &rs_desc, &rs); ok(SUCCEEDED(hr), "Failed to create rasterizer state, hr %#x.\n", hr); ID3D11DeviceContext_RSSetState(context, rs); ID3D11DeviceContext_ClearDepthStencilView(context, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0); set_viewport(context, vp.TopLeftX, vp.TopLeftY, vp.Width, vp.Height, 0.4f, 0.6f); draw_quad_z(&test_context, 2.0f); check_texture_float(texture, 0.6f, 1); draw_quad_z(&test_context, 0.5f); check_texture_float(texture, 0.5f, 1); draw_quad_z(&test_context, -1.0f); check_texture_float(texture, 0.4f, 1); ID3D11DepthStencilView_Release(dsv); ID3D11Texture2D_Release(texture); ID3D11RasterizerState_Release(rs); release_test_context(&test_context); } static void test_staging_buffers(void) { struct d3d11_test_context test_context; ID3D11Buffer *dst_buffer, *src_buffer; D3D11_SUBRESOURCE_DATA resource_data; D3D11_BUFFER_DESC buffer_desc; ID3D11DeviceContext *context; struct resource_readback rb; float data[16], value; ID3D11Device *device; unsigned int i; HRESULT hr; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; buffer_desc.ByteWidth = sizeof(data); buffer_desc.Usage = D3D11_USAGE_STAGING; buffer_desc.BindFlags = 0; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; buffer_desc.MiscFlags = 0; buffer_desc.StructureByteStride = 0; for (i = 0; i < ARRAY_SIZE(data); ++i) data[i] = i; resource_data.pSysMem = data; resource_data.SysMemPitch = 0; resource_data.SysMemSlicePitch = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, &resource_data, &src_buffer); ok(hr == S_OK, "Failed to create buffer, hr %#x.\n", hr); buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; buffer_desc.CPUAccessFlags = 0; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &dst_buffer); ok(hr == S_OK, "Failed to create buffer, hr %#x.\n", hr); ID3D11DeviceContext_CopyResource(context, (ID3D11Resource *)dst_buffer, (ID3D11Resource *)src_buffer); get_buffer_readback(dst_buffer, &rb); for (i = 0; i < ARRAY_SIZE(data); ++i) { value = get_readback_float(&rb, i, 0); ok(value == data[i], "Got unexpected value %.8e at %u.\n", value, i); } release_resource_readback(&rb); for (i = 0; i < ARRAY_SIZE(data); ++i) data[i] = 2 * i; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)src_buffer, 0, NULL, data, 0, 0); ID3D11DeviceContext_CopyResource(context, (ID3D11Resource *)dst_buffer, (ID3D11Resource *)src_buffer); get_buffer_readback(dst_buffer, &rb); for (i = 0; i < ARRAY_SIZE(data); ++i) { value = get_readback_float(&rb, i, 0); ok(value == i, "Got unexpected value %.8e at %u.\n", value, i); } release_resource_readback(&rb); ID3D11Buffer_Release(dst_buffer); ID3D11Buffer_Release(src_buffer); release_test_context(&test_context); } static void test_render_a8(void) { static const float black[] = {0.0f, 0.0f, 0.0f, 0.0f}; struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11DeviceContext *context; ID3D11RenderTargetView *rtv; struct resource_readback rb; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i; HRESULT hr; static const DWORD ps_code[] = { #if 0 void main(out float4 target : SV_Target) { target = float4(0.0f, 0.25f, 0.5f, 1.0f); } #endif 0x43425844, 0x8a06129f, 0x3041bde2, 0x09389749, 0xb339ba8b, 0x00000001, 0x000000b0, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03000065, 0x001020f2, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3e800000, 0x3f000000, 0x3f800000, 0x0100003e, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.Format = DXGI_FORMAT_A8_UNORM; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, NULL, &rtv); ok(hr == S_OK, "Failed to create render target view, hr %#x.\n", hr); for (i = 0; i < 2; ++i) { ID3D11DeviceContext_ClearRenderTargetView(context, rtv, black); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); draw_quad(&test_context); get_texture_readback(texture, 0, &rb); check_readback_data_u8(&rb, NULL, 0xff, 0); release_resource_readback(&rb); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, black); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, NULL); draw_quad(&test_context); check_texture_sub_resource_color(test_context.backbuffer, 0, NULL, 0xff7f4000, 1); } ID3D11PixelShader_Release(ps); ID3D11Texture2D_Release(texture); ID3D11RenderTargetView_Release(rtv); release_test_context(&test_context); } static void test_standard_pattern(void) { D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; struct d3d11_test_context test_context; struct swapchain_desc swapchain_desc; D3D11_TEXTURE2D_DESC texture_desc; ID3D11UnorderedAccessView *uav; D3D11_BUFFER_DESC buffer_desc; ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Buffer *buffer; ID3D11Device *device; unsigned int i; HRESULT hr; static const DWORD ps_samplepos[] = { #if 0 Texture2DMS t; RWByteAddressBuffer u; float4 main() : SV_Target { u.Store2(0, asuint(t.GetSamplePosition(0))); u.Store2(8, asuint(t.GetSamplePosition(1))); u.Store2(16, asuint(t.GetSamplePosition(2))); u.Store2(24, asuint(t.GetSamplePosition(3))); return float4(0.0f, 1.0f, 0.0f, 1.0f); } #endif 0x43425844, 0xa1db77e8, 0x804d8862, 0x0e3c213d, 0x2703dec6, 0x00000001, 0x00000190, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000118, 0x00000050, 0x00000046, 0x0100086a, 0x04002058, 0x00107000, 0x00000000, 0x00005555, 0x0300009d, 0x0011e000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800006e, 0x00100032, 0x00000000, 0x00107046, 0x00000000, 0x00004001, 0x00000000, 0x00000000, 0x0800006e, 0x001000c2, 0x00000000, 0x00107406, 0x00000000, 0x00004001, 0x00000001, 0x00000000, 0x070000a6, 0x0011e0f2, 0x00000001, 0x00004001, 0x00000000, 0x00100e46, 0x00000000, 0x0800006e, 0x00100032, 0x00000000, 0x00107046, 0x00000000, 0x00004001, 0x00000002, 0x00000000, 0x0800006e, 0x001000c2, 0x00000000, 0x00107406, 0x00000000, 0x00004001, 0x00000003, 0x00000000, 0x070000a6, 0x0011e0f2, 0x00000001, 0x00004001, 0x00000010, 0x00100e46, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e }; static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const unsigned int zero[4] = {0}; static const float standard_pos4[] = { -2 / 16.0f, -6 / 16.0f, 6 / 16.0f, -2 / 16.0f, -6 / 16.0f, 2 / 16.0f, 2 / 16.0f, 6 / 16.0f, }; swapchain_desc.windowed = TRUE; swapchain_desc.buffer_count = 1; swapchain_desc.width = 32; swapchain_desc.height = 32; swapchain_desc.swap_effect = DXGI_SWAP_EFFECT_DISCARD; swapchain_desc.flags = 0; if (!init_test_context_ext(&test_context, &feature_level, &swapchain_desc)) return; device = test_context.device; context = test_context.immediate_context; ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); texture_desc.SampleDesc.Count = 4; texture_desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN; texture_desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); ok(hr == S_OK, "Failed to create shader resource view, hr %#x.\n", hr); buffer_desc.ByteWidth = 1024; buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; buffer_desc.CPUAccessFlags = 0; buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); ok(hr == S_OK, "Failed to create buffer, hr %#x.\n", hr); uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; U(uav_desc).Buffer.FirstElement = 0; U(uav_desc).Buffer.NumElements = 256; U(uav_desc).Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); ok(hr == S_OK, "Failed to create unordered access view, hr %#x.\n", hr); hr = ID3D11Device_CreatePixelShader(device, ps_samplepos, sizeof(ps_samplepos), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); ID3D11DeviceContext_ClearUnorderedAccessViewUint(context, uav, zero); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, 1, &test_context.backbuffer_rtv, NULL, 1, 1, &uav, NULL); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0xff00ff00, 0); get_buffer_readback(buffer, &rb); for (i = 0; i < ARRAY_SIZE(standard_pos4); ++i) { float data = get_readback_float(&rb, i, 0); /* Wine does not support GetSamplePosition. */ todo_wine ok(data == standard_pos4[i], "Got sample position %.8e, expected %.8e.\n", data, standard_pos4[i]); } release_resource_readback(&rb); ID3D11PixelShader_Release(ps); ID3D11Buffer_Release(buffer); ID3D11UnorderedAccessView_Release(uav); ID3D11ShaderResourceView_Release(srv); ID3D11Texture2D_Release(texture); release_test_context(&test_context); } static void test_desktop_window(void) { ID3D11RenderTargetView *backbuffer_rtv; DXGI_SWAP_CHAIN_DESC swapchain_desc; ID3D11DeviceContext *context; ID3D11Texture2D *backbuffer; IDXGISwapChain *swapchain; IDXGIDevice *dxgi_device; IDXGIAdapter *adapter; IDXGIFactory *factory; ID3D11Device *device; ULONG refcount; HRESULT hr; static const float red[] = {1.0f, 0.0f, 0.0f, 1.0f}; if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); return; } hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); ok(SUCCEEDED(hr), "Failed to get DXGI device, hr %#x.\n", hr); hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter); ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr); IDXGIDevice_Release(dxgi_device); hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory); ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr); IDXGIAdapter_Release(adapter); swapchain_desc.BufferDesc.Width = 640; swapchain_desc.BufferDesc.Height = 480; swapchain_desc.BufferDesc.RefreshRate.Numerator = 60; swapchain_desc.BufferDesc.RefreshRate.Denominator = 1; swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; swapchain_desc.SampleDesc.Count = 1; swapchain_desc.SampleDesc.Quality = 0; swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapchain_desc.BufferCount = 1; swapchain_desc.OutputWindow = GetDesktopWindow(); swapchain_desc.Windowed = TRUE; swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swapchain_desc.Flags = 0; hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain); ok(hr == S_OK || broken(hr == DXGI_ERROR_INVALID_CALL) /* Not available on all Windows versions. */, "Failed to create swapchain, hr %#x.\n", hr); IDXGIFactory_Release(factory); if (FAILED(hr)) { ID3D11Device_Release(device); return; } hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D11Texture2D, (void **)&backbuffer); ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)backbuffer, NULL, &backbuffer_rtv); ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); ID3D11Device_GetImmediateContext(device, &context); ID3D11DeviceContext_ClearRenderTargetView(context, backbuffer_rtv, red); check_texture_color(backbuffer, 0xff0000ff, 1); hr = IDXGISwapChain_Present(swapchain, 0, 0); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11RenderTargetView_Release(backbuffer_rtv); ID3D11Texture2D_Release(backbuffer); IDXGISwapChain_Release(swapchain); ID3D11DeviceContext_Release(context); refcount = ID3D11Device_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); } static void test_sample_attached_rtv(void) { ID3D11ShaderResourceView *srv, *srv2, *srv_test, *srv_ds; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc, srvds_desc; ID3D11Texture2D *texture, *texture2, *dstexture; ID3D11RenderTargetView *rtv, *rtv2, *rtvs[2]; D3D11_DEPTH_STENCIL_VIEW_DESC dsview_desc; struct d3d11_test_context test_context; D3D11_RENDER_TARGET_VIEW_DESC rtv_desc; D3D11_TEXTURE2D_DESC texture_desc; D3D_FEATURE_LEVEL feature_level; D3D11_SAMPLER_DESC sampler_desc; ID3D11DepthStencilView *dsview; ID3D11BlendState *blend_state; ID3D11DeviceContext *context; D3D11_BLEND_DESC blend_desc; ID3D11SamplerState *sampler; struct resource_readback rb; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int x, y; unsigned int i; D3D11_BOX box; DWORD color; HRESULT hr; static const DWORD ps_ld_code[] = { #if 0 Texture2D t; struct PS_OUTPUT { float4 color0: SV_Target0; float4 color1: SV_Target1; }; PS_OUTPUT main(float4 position : SV_POSITION) { PS_OUTPUT output; float3 p; t.GetDimensions(0, p.x, p.y, p.z); p.z = 0; p *= float3(position.x / 640.0f, position.y / 480.0f, 1.0f); output.color0 = output.color1 = t.Load(int3(p)) + float4(0.25, 0.25, 0.25, 0.25); return output; } #endif 0x43425844, 0x08dd0517, 0x07d7e538, 0x4cad261f, 0xa2ae5942, 0x00000001, 0x00000200, 0x00000003, 0x0000002c, 0x00000060, 0x000000ac, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x00000044, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000038, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000014c, 0x00000040, 0x00000053, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x02000068, 0x00000001, 0x0700003d, 0x001000f2, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00101046, 0x00000000, 0x0a000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x08000036, 0x001000c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0500001b, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x0700002d, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x0a000000, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3e800000, 0x3e800000, 0x3e800000, 0x3e800000, 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00100e46, 0x00000000, 0x0100003e, }; static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f}; static const struct { DXGI_FORMAT texture_format, dsv_format, srv_format; UINT dsv_flags; BOOL srv_bind_allowed; } ds_tests[] = { {DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 0, FALSE}, {DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, D3D11_DSV_READ_ONLY_DEPTH, TRUE}, {DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_X24_TYPELESS_G8_UINT, D3D11_DSV_READ_ONLY_DEPTH, FALSE}, {DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_X24_TYPELESS_G8_UINT, D3D11_DSV_READ_ONLY_STENCIL, TRUE}, {DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_FLOAT, 0, FALSE}, {DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_FLOAT, D3D11_DSV_READ_ONLY_DEPTH, TRUE}, }; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; feature_level = ID3D11Device_GetFeatureLevel(device); texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; texture_desc.CPUAccessFlags = 0; texture_desc.MiscFlags = 0; sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampler_desc.BorderColor[0] = 0.0f; sampler_desc.BorderColor[1] = 0.0f; sampler_desc.BorderColor[2] = 0.0f; sampler_desc.BorderColor[3] = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = D3D11_FLOAT32_MAX; hr = ID3D11Device_CreatePixelShader(device, ps_ld_code, sizeof(ps_ld_code), NULL, &ps); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); texture_desc.Width = 64; texture_desc.Height = 64; texture_desc.MipLevels = 2; texture_desc.ArraySize = 1; texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); texture_desc.Width = 640; texture_desc.Height = 480; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &texture2); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.MipLODBias = 0.0f; sampler_desc.MinLOD = 0.0f; sampler_desc.MaxLOD = 0.0f; hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); memset(&rtv_desc, 0, sizeof(rtv_desc)); rtv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; U(rtv_desc).Texture2D.MipSlice = 0; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture2, &rtv_desc, &rtv); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); U(rtv_desc).Texture2D.MipSlice = 1; hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture2, &rtv_desc, &rtv2); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); rtvs[0] = test_context.backbuffer_rtv; rtvs[1] = rtv; ID3D11DeviceContext_OMSetRenderTargets(context, 2, rtvs, NULL); memset(&srv_desc, 0, sizeof(srv_desc)); srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; U(srv_desc).Texture2D.MipLevels = 1; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, &srv_desc, &srv); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); draw_quad(&test_context); set_box(&box, 0, 0, 0, 320, 240, 1); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)texture2, 1, 0, 0, 0, (ID3D11Resource *)texture2, 0, &box); get_texture_readback(texture2, 0, &rb); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 80 + x * 160, 60 + y * 120, 0); ok(compare_color(color, 0x40404040, 2), "Got unexpected color 0x%08x at (%u, %u).\n", color, x, y); } } release_resource_readback(&rb); get_texture_readback(texture2, 1, &rb); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 40 + x * 80, 30 + y * 60, 0); ok(compare_color(color, 0x40404040, 2), "Got unexpected color 0x%08x at (%u, %u).\n", color, x, y); } } release_resource_readback(&rb); ID3D11ShaderResourceView_Release(srv); ID3D11DeviceContext_OMSetRenderTargets(context, 2, rtvs, NULL); ID3D11DeviceContext_ClearRenderTargetView(context, rtv, red); hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture2, &srv_desc, &srv); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); U(srv_desc).Texture2D.MostDetailedMip = 1; U(srv_desc).Texture2D.MipLevels = 1; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture2, &srv_desc, &srv2); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); memset(&blend_desc, 0, sizeof(blend_desc)); blend_desc.IndependentBlendEnable = TRUE; blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; blend_desc.RenderTarget[1].RenderTargetWriteMask = 0; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &blend_state); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_OMSetBlendState(context, blend_state, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11BlendState_Release(blend_state); /* SRV does not get bound if resource is attached as render target, even if write mask is 0. */ ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); ID3D11DeviceContext_PSGetShaderResources(context, 0, 1, &srv_test); ok(!srv_test, "Unexpected SRV %p.\n", srv_test); blend_desc.RenderTarget[1].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &blend_state); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_OMSetBlendState(context, blend_state, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11BlendState_Release(blend_state); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, red); draw_quad(&test_context); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 80 + x * 160, 60 + y * 120, 0); ok(compare_color(color, 0x40404040, 2), "Got unexpected color 0x%08x at (%u, %u).\n", color, x, y); } } release_resource_readback(&rb); get_texture_readback(texture2, 0, &rb); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 80 + x * 160, 60 + y * 120, 0); ok(compare_color(color, 0x40404040, 2), "Got unexpected color 0x%08x at (%u, %u).\n", color, x, y); } } release_resource_readback(&rb); ID3D11DeviceContext_OMSetRenderTargets(context, 1, &test_context.backbuffer_rtv, NULL); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); ID3D11DeviceContext_PSGetShaderResources(context, 0, 1, &srv_test); ok(!!srv_test, "Unexpected SRV %p.\n", srv_test); ID3D11ShaderResourceView_Release(srv_test); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 80 + x * 160, 60 + y * 120, 0); ok(compare_color(color, 0x80808080, 2), "Got unexpected color 0x%08x at (%u, %u).\n", color, x, y); } } release_resource_readback(&rb); ID3D11DeviceContext_OMSetRenderTargets(context, 2, rtvs, NULL); /* SRV is reset when the same resource is set as render target. */ ID3D11DeviceContext_PSGetShaderResources(context, 0, 1, &srv_test); ok(!srv_test, "Unexpected SRV %p.\n", srv_test); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv2); ID3D11DeviceContext_OMSetRenderTargets(context, 2, rtvs, NULL); ID3D11DeviceContext_PSGetShaderResources(context, 0, 1, &srv_test); ok(!!srv_test, "Unexpected SRV %p.\n", srv_test); ID3D11ShaderResourceView_Release(srv_test); draw_quad(&test_context); get_texture_readback(test_context.backbuffer, 0, &rb); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { color = get_readback_color(&rb, 80 + x * 160, 60 + y * 120, 0); ok(compare_color(color, 0x80808080, 2), "Got unexpected color 0x%08x at (%u, %u).\n", color, x, y); } } release_resource_readback(&rb); texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; memset(&dsview_desc, 0, sizeof(dsview_desc)); dsview_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; memset(&srvds_desc, 0, sizeof(srvds_desc)); srvds_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; U(srvds_desc).Texture2D.MipLevels = 1; for (i = 0; i < ARRAY_SIZE(ds_tests); ++i) { if (ds_tests[i].dsv_flags && feature_level < D3D_FEATURE_LEVEL_11_0) { static unsigned int skip_once; if (!skip_once++) skip("Read only depths or stencils are not supported.\n"); continue; } texture_desc.Format = ds_tests[i].texture_format; hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &dstexture); ok(hr == S_OK, "Test %u, got unexpected hr %#x.\n", i, hr); dsview_desc.Format = ds_tests[i].dsv_format; dsview_desc.Flags = ds_tests[i].dsv_flags; hr = ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource *)dstexture, &dsview_desc, &dsview); ok(hr == S_OK, "Test %u, got unexpected hr %#x.\n", i, hr); srvds_desc.Format = ds_tests[i].srv_format; hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)dstexture, &srvds_desc, &srv_ds); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ID3D11DeviceContext_OMSetRenderTargets(context, 1, rtvs, NULL); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv_ds); ID3D11DeviceContext_PSGetShaderResources(context, 0, 1, &srv_test); ok(!!srv_test, "Test %u, unexpected SRV %p.\n", i, srv_test); ID3D11ShaderResourceView_Release(srv_test); ID3D11DeviceContext_OMSetRenderTargets(context, 1, rtvs, dsview); ID3D11DeviceContext_PSGetShaderResources(context, 0, 1, &srv_test); ok(!!srv_test == ds_tests[i].srv_bind_allowed, "Test %u, unexpected SRV %p.\n", i, srv_test); if (srv_test) ID3D11ShaderResourceView_Release(srv_test); ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv_ds); ID3D11DeviceContext_PSGetShaderResources(context, 0, 1, &srv_test); ok(!!srv_test == ds_tests[i].srv_bind_allowed, "Test %u, unexpected SRV %p.\n", i, srv_test); if (srv_test) ID3D11ShaderResourceView_Release(srv_test); ID3D11Texture2D_Release(dstexture); ID3D11DepthStencilView_Release(dsview); ID3D11ShaderResourceView_Release(srv_ds); } ID3D11DeviceContext_OMSetRenderTargets(context, 2, rtvs, NULL); ID3D11RenderTargetView_Release(rtv2); ID3D11RenderTargetView_Release(rtv); ID3D11ShaderResourceView_Release(srv2); ID3D11ShaderResourceView_Release(srv); ID3D11SamplerState_Release(sampler); ID3D11PixelShader_Release(ps); ID3D11Texture2D_Release(texture2); ID3D11Texture2D_Release(texture); ID3D11SamplerState_Release(sampler); release_test_context(&test_context); } static void test_color_mask(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11RenderTargetView *rtvs[8]; ID3D11BlendState *blend_state; ID3D11DeviceContext *context; struct resource_readback rb; D3D11_BLEND_DESC blend_desc; ID3D11Texture2D *rts[8]; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i; DWORD color; HRESULT hr; static const DWORD expected_colors[] = {0xff000080, 0xff0080ff, 0xff8000ff, 0x80808080, 0x800000ff, 0xff008080, 0x800080ff, 0xff0000ff}; static const DWORD ps_code[] = { #if 0 void main(float4 position : SV_Position, out float4 t0 : SV_Target0, out float4 t1 : SV_Target1, out float4 t2 : SV_Target2, out float4 t3 : SV_Target3, out float4 t4 : SV_Target4, out float4 t5 : SV_Target5, out float4 t6 : SV_Target6, out float4 t7 : SV_Target7) { t0 = t1 = t2 = t3 = t4 = t5 = t6 = t7 = float4(0.5f, 0.5f, 0.5f, 0.5f); } #endif 0x43425844, 0x7b1ab233, 0xdbe32d3b, 0x77084cc5, 0xe874d2b5, 0x00000001, 0x000002b0, 0x00000003, 0x0000002c, 0x00000060, 0x0000013c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x000000d4, 0x00000008, 0x00000008, 0x000000c8, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x000000c8, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x000000c8, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x0000000f, 0x000000c8, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x0000000f, 0x000000c8, 0x00000004, 0x00000000, 0x00000003, 0x00000004, 0x0000000f, 0x000000c8, 0x00000005, 0x00000000, 0x00000003, 0x00000005, 0x0000000f, 0x000000c8, 0x00000006, 0x00000000, 0x00000003, 0x00000006, 0x0000000f, 0x000000c8, 0x00000007, 0x00000000, 0x00000003, 0x00000007, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040, 0x0000005b, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000003, 0x03000065, 0x001020f2, 0x00000004, 0x03000065, 0x001020f2, 0x00000005, 0x03000065, 0x001020f2, 0x00000006, 0x03000065, 0x001020f2, 0x00000007, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x08000036, 0x001020f2, 0x00000002, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x08000036, 0x001020f2, 0x00000003, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x08000036, 0x001020f2, 0x00000004, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x08000036, 0x001020f2, 0x00000005, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x08000036, 0x001020f2, 0x00000006, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x08000036, 0x001020f2, 0x00000007, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x0100003e, }; static const float red[] = {1.0f, 0.0f, 0.0f, 1.0f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); memset(&blend_desc, 0, sizeof(blend_desc)); blend_desc.IndependentBlendEnable = TRUE; blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED; blend_desc.RenderTarget[1].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_GREEN; blend_desc.RenderTarget[2].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_BLUE; blend_desc.RenderTarget[3].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; blend_desc.RenderTarget[4].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA; blend_desc.RenderTarget[5].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN; blend_desc.RenderTarget[6].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_ALPHA; blend_desc.RenderTarget[7].RenderTargetWriteMask = 0; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &blend_state); ok(hr == S_OK, "Failed to create blend state, hr %#x.\n", hr); ID3D11DeviceContext_OMSetBlendState(context, blend_state, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11BlendState_Release(blend_state); for (i = 0; i < 8; ++i) { ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rts[i]); ok(hr == S_OK, "Failed to create texture %u, hr %#x.\n", i, hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rts[i], NULL, &rtvs[i]); ok(hr == S_OK, "Failed to create rendertarget view %u, hr %#x.\n", i, hr); } ID3D11DeviceContext_OMSetRenderTargets(context, 8, rtvs, NULL); for (i = 0; i < 8; ++i) ID3D11DeviceContext_ClearRenderTargetView(context, rtvs[i], red); draw_quad(&test_context); for (i = 0; i < 8; ++i) { get_texture_readback(rts[i], 0, &rb); color = get_readback_color(&rb, 320, 240, 0); ok(compare_color(color, expected_colors[i], 1), "%u: Got unexpected color 0x%08x.\n", i, color); release_resource_readback(&rb); } blend_desc.IndependentBlendEnable = FALSE; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &blend_state); ok(hr == S_OK, "Failed to create blend state, hr %#x.\n", hr); ID3D11DeviceContext_OMSetBlendState(context, blend_state, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11BlendState_Release(blend_state); for (i = 0; i < 8; ++i) ID3D11DeviceContext_ClearRenderTargetView(context, rtvs[i], red); draw_quad(&test_context); for (i = 0; i < 8; ++i) { get_texture_readback(rts[i], 0, &rb); color = get_readback_color(&rb, 320, 240, 0); ok(compare_color(color, expected_colors[0], 1), "%u: Got unexpected color 0x%08x.\n", i, color); release_resource_readback(&rb); ID3D11Texture2D_Release(rts[i]); ID3D11RenderTargetView_Release(rtvs[i]); } ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_independent_blend(void) { struct d3d11_test_context test_context; D3D11_TEXTURE2D_DESC texture_desc; ID3D11RenderTargetView *rtvs[8]; ID3D11BlendState *blend_state; ID3D11DeviceContext *context; struct resource_readback rb; ID3D11Texture2D *rts[8]; ID3D11PixelShader *ps; ID3D11Device *device; unsigned int i; DWORD color; HRESULT hr; static const DWORD ps_code[] = { #if 0 void main(float4 position : SV_Position, out float4 t0 : SV_Target0, out float4 t1 : SV_Target1, out float4 t2 : SV_Target2, out float4 t3 : SV_Target3, out float4 t4 : SV_Target4, out float4 t5 : SV_Target5, out float4 t6 : SV_Target6, out float4 t7 : SV_Target7) { t0 = t1 = t2 = t3 = t4 = t5 = t6 = t7 = float4(0.1f, 0.2f, 0.3f, 0.4f); } #endif 0x43425844, 0xb3dca7dc, 0x4a31f0f1, 0x747569cb, 0xae7af5ce, 0x00000001, 0x000002b0, 0x00000003, 0x0000002c, 0x00000060, 0x0000013c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x000000d4, 0x00000008, 0x00000008, 0x000000c8, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x000000c8, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x000000c8, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x0000000f, 0x000000c8, 0x00000003, 0x00000000, 0x00000003, 0x00000003, 0x0000000f, 0x000000c8, 0x00000004, 0x00000000, 0x00000003, 0x00000004, 0x0000000f, 0x000000c8, 0x00000005, 0x00000000, 0x00000003, 0x00000005, 0x0000000f, 0x000000c8, 0x00000006, 0x00000000, 0x00000003, 0x00000006, 0x0000000f, 0x000000c8, 0x00000007, 0x00000000, 0x00000003, 0x00000007, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040, 0x0000005b, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000003, 0x03000065, 0x001020f2, 0x00000004, 0x03000065, 0x001020f2, 0x00000005, 0x03000065, 0x001020f2, 0x00000006, 0x03000065, 0x001020f2, 0x00000007, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3dcccccd, 0x3e4ccccd, 0x3e99999a, 0x3ecccccd, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3dcccccd, 0x3e4ccccd, 0x3e99999a, 0x3ecccccd, 0x08000036, 0x001020f2, 0x00000002, 0x00004002, 0x3dcccccd, 0x3e4ccccd, 0x3e99999a, 0x3ecccccd, 0x08000036, 0x001020f2, 0x00000003, 0x00004002, 0x3dcccccd, 0x3e4ccccd, 0x3e99999a, 0x3ecccccd, 0x08000036, 0x001020f2, 0x00000004, 0x00004002, 0x3dcccccd, 0x3e4ccccd, 0x3e99999a, 0x3ecccccd, 0x08000036, 0x001020f2, 0x00000005, 0x00004002, 0x3dcccccd, 0x3e4ccccd, 0x3e99999a, 0x3ecccccd, 0x08000036, 0x001020f2, 0x00000006, 0x00004002, 0x3dcccccd, 0x3e4ccccd, 0x3e99999a, 0x3ecccccd, 0x08000036, 0x001020f2, 0x00000007, 0x00004002, 0x3dcccccd, 0x3e4ccccd, 0x3e99999a, 0x3ecccccd, 0x0100003e, }; D3D11_BLEND_DESC blend_desc = { .IndependentBlendEnable = TRUE, .RenderTarget = { {TRUE, D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL}, {TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ZERO, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL}, {TRUE, D3D11_BLEND_SRC_COLOR, D3D11_BLEND_DEST_COLOR, D3D11_BLEND_OP_ADD, D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL}, {TRUE, D3D11_BLEND_ONE, D3D11_BLEND_ONE, D3D11_BLEND_OP_MIN, D3D11_BLEND_ONE, D3D11_BLEND_ONE, D3D11_BLEND_OP_MIN, D3D11_COLOR_WRITE_ENABLE_ALL}, {TRUE, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL}, {TRUE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_ONE, D3D11_BLEND_ONE, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_COLOR_WRITE_ENABLE_ALL}, {FALSE, 0, 0, 0, 0, 0, 0, D3D11_COLOR_WRITE_ENABLE_ALL}, {TRUE, D3D11_BLEND_DEST_COLOR, D3D11_BLEND_SRC_COLOR, D3D11_BLEND_OP_ADD, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_INV_DEST_ALPHA, D3D11_BLEND_OP_SUBTRACT, D3D11_COLOR_WRITE_ENABLE_ALL}, }, }; static const DWORD expected_colors[] = {0x66426e1c, 0xb34c3319, 0xa6214a05, 0x66333319, 0xb34c4829, 0x4d19000a, 0x664c3319, 0x081f3305}; static const float clear_color[] = {0.1f, 0.5f, 0.2f, 0.7f}; static const float blend_factor[] = {0.8f, 0.4f, 0.6f, 0.2f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); hr = ID3D11Device_CreateBlendState(device, &blend_desc, &blend_state); ok(hr == S_OK, "Failed to create blend state, hr %#x.\n", hr); ID3D11DeviceContext_OMSetBlendState(context, blend_state, blend_factor, D3D11_DEFAULT_SAMPLE_MASK); ID3D11BlendState_Release(blend_state); for (i = 0; i < 8; ++i) { ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rts[i]); ok(hr == S_OK, "Failed to create texture %u, hr %#x.\n", i, hr); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rts[i], NULL, &rtvs[i]); ok(hr == S_OK, "Failed to create rendertarget view %u, hr %#x.\n", i, hr); } ID3D11DeviceContext_OMSetRenderTargets(context, 8, rtvs, NULL); for (i = 0; i < 8; ++i) ID3D11DeviceContext_ClearRenderTargetView(context, rtvs[i], clear_color); draw_quad(&test_context); for (i = 0; i < 8; ++i) { get_texture_readback(rts[i], 0, &rb); color = get_readback_color(&rb, 320, 240, 0); ok(compare_color(color, expected_colors[i], 1), "%u: Got unexpected color 0x%08x.\n", i, color); release_resource_readback(&rb); } blend_desc.IndependentBlendEnable = FALSE; hr = ID3D11Device_CreateBlendState(device, &blend_desc, &blend_state); ok(hr == S_OK, "Failed to create blend state, hr %#x.\n", hr); ID3D11DeviceContext_OMSetBlendState(context, blend_state, blend_factor, D3D11_DEFAULT_SAMPLE_MASK); ID3D11BlendState_Release(blend_state); for (i = 0; i < 8; ++i) ID3D11DeviceContext_ClearRenderTargetView(context, rtvs[i], clear_color); draw_quad(&test_context); for (i = 0; i < 8; ++i) { get_texture_readback(rts[i], 0, &rb); color = get_readback_color(&rb, 320, 240, 0); ok(compare_color(color, expected_colors[0], 1), "%u: Got unexpected color 0x%08x.\n", i, color); release_resource_readback(&rb); ID3D11Texture2D_Release(rts[i]); ID3D11RenderTargetView_Release(rtvs[i]); } ID3D11PixelShader_Release(ps); release_test_context(&test_context); } static void test_dual_source_blend(void) { struct d3d11_test_context test_context; ID3D11BlendState *blend_state; ID3D11DeviceContext *context; ID3D11PixelShader *ps; ID3D11Device *device; DWORD color; HRESULT hr; static const DWORD ps_code[] = { #if 0 void main(float4 position : SV_Position, out float4 t0 : SV_Target0, out float4 t1 : SV_Target1) { t0 = float4(0.5, 0.5, 0.0, 1.0); t1 = float4(0.0, 0.5, 0.5, 0.0); } #endif 0x43425844, 0x87120d01, 0xa0014738, 0x3a32d86c, 0x9d757441, 0x00000001, 0x00000118, 0x00000003, 0x0000002c, 0x00000060, 0x000000ac, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x4e47534f, 0x00000044, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000038, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000064, 0x00000040, 0x00000019, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x3f000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x3f000000, 0x3f000000, 0x00000000, 0x0100003e }; static const D3D11_BLEND_DESC blend_desc = { .RenderTarget[0].BlendEnable = TRUE, .RenderTarget[0].SrcBlend = D3D11_BLEND_SRC1_COLOR, .RenderTarget[0].DestBlend = D3D11_BLEND_SRC1_COLOR, .RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD, .RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE, .RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO, .RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD, .RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL, }; static const float clear_color[] = {0.7f, 0.0f, 1.0f, 1.0f}; if (!init_test_context(&test_context, NULL)) return; device = test_context.device; context = test_context.immediate_context; hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); hr = ID3D11Device_CreateBlendState(device, &blend_desc, &blend_state); ok(hr == S_OK, "Failed to create blend state, hr %#x.\n", hr); ID3D11DeviceContext_OMSetBlendState(context, blend_state, NULL, D3D11_DEFAULT_SAMPLE_MASK); ID3D11BlendState_Release(blend_state); ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, clear_color); draw_quad(&test_context); color = get_texture_color(test_context.backbuffer, 320, 240); ok(compare_color(color, 0x80804000, 1), "Got unexpected color 0x%08x.\n", color); ID3D11PixelShader_Release(ps); release_test_context(&test_context); } START_TEST(d3d11) { unsigned int argc, i; char **argv; use_mt = !getenv("WINETEST_NO_MT_D3D"); argc = winetest_get_mainargs(&argv); for (i = 2; i < argc; ++i) { if (!strcmp(argv[i], "--validate")) enable_debug_layer = TRUE; else if (!strcmp(argv[i], "--warp")) use_warp_adapter = TRUE; else if (!strcmp(argv[i], "--adapter") && i + 1 < argc) use_adapter_idx = atoi(argv[++i]); else if (!strcmp(argv[i], "--single")) use_mt = FALSE; } print_adapter_info(); queue_test(test_create_device); queue_for_each_feature_level(test_device_interfaces); queue_test(test_immediate_context); queue_test(test_create_deferred_context); queue_test(test_create_texture1d); queue_test(test_texture1d_interfaces); queue_test(test_create_texture2d); queue_test(test_texture2d_interfaces); queue_test(test_create_texture3d); queue_test(test_texture3d_interfaces); queue_test(test_create_buffer); queue_test(test_create_depthstencil_view); queue_test(test_depthstencil_view_interfaces); queue_test(test_create_rendertarget_view); queue_test(test_create_shader_resource_view); queue_for_each_feature_level(test_create_shader); queue_test(test_create_sampler_state); queue_test(test_create_blend_state); queue_test(test_create_depthstencil_state); queue_test(test_create_rasterizer_state); queue_test(test_create_query); queue_test(test_occlusion_query); queue_test(test_pipeline_statistics_query); queue_test(test_timestamp_query); queue_test(test_so_statistics_query); queue_test(test_device_removed_reason); queue_test(test_private_data); queue_for_each_feature_level(test_state_refcounting); queue_test(test_device_context_state); queue_test(test_blend); queue_test(test_texture1d); queue_test(test_texture); queue_test(test_cube_maps); queue_test(test_depth_stencil_sampling); queue_test(test_sample_c_lz); queue_test(test_multiple_render_targets); queue_test(test_render_target_views); queue_test(test_layered_rendering); queue_test(test_scissor); queue_test(test_clear_state); queue_test(test_il_append_aligned); queue_test(test_instance_id); queue_test(test_vertex_id); queue_test(test_fragment_coords); queue_test(test_initial_texture_data); queue_test(test_update_subresource); queue_test(test_copy_subresource_region); queue_test(test_copy_subresource_region_1d); queue_test(test_copy_subresource_region_3d); queue_test(test_resource_map); queue_for_each_feature_level(test_resource_access); queue_test(test_check_multisample_quality_levels); queue_for_each_feature_level(test_swapchain_formats); queue_test(test_swapchain_views); queue_test(test_swapchain_flip); queue_test(test_clear_render_target_view_1d); queue_test(test_clear_render_target_view_2d); queue_test(test_clear_render_target_view_3d); queue_test(test_clear_depth_stencil_view); queue_test(test_clear_buffer_unordered_access_view); queue_test(test_initial_depth_stencil_state); queue_test(test_draw_depth_only); queue_test(test_draw_uav_only); queue_test(test_cb_relative_addressing); queue_test(test_vs_input_relative_addressing); queue_test(test_getdc); queue_test(test_shader_stage_input_output_matching); queue_test(test_shader_interstage_interface); queue_test(test_sm4_if_instruction); queue_test(test_sm4_breakc_instruction); queue_test(test_sm4_continuec_instruction); queue_test(test_sm4_discard_instruction); queue_test(test_sm5_swapc_instruction); queue_test(test_create_input_layout); queue_test(test_input_assembler); queue_test(test_null_sampler); queue_test(test_check_feature_support); queue_test(test_create_unordered_access_view); queue_test(test_immediate_constant_buffer); queue_test(test_fp_specials); queue_test(test_uint_shader_instructions); queue_test(test_index_buffer_offset); queue_test(test_face_culling); queue_test(test_line_antialiasing_blending); queue_for_each_feature_level(test_format_support); queue_for_each_9_x_feature_level(test_fl9_draw); queue_test(test_ddy); queue_test(test_shader_input_registers_limits); queue_test(test_unbind_shader_resource_view); queue_test(test_stencil_separate); queue_test(test_uav_load); queue_test(test_cs_uav_store); queue_test(test_uav_store_immediate_constant); queue_test(test_ps_cs_uav_binding); queue_test(test_atomic_instructions); queue_test(test_sm4_ret_instruction); queue_test(test_primitive_restart); queue_test(test_resinfo_instruction); queue_test(test_sm5_bufinfo_instruction); queue_test(test_sampleinfo_instruction); queue_test(test_render_target_device_mismatch); queue_test(test_buffer_srv); queue_for_each_feature_level_in_range(D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_11_0, test_unaligned_raw_buffer_access); queue_test(test_uav_counters); queue_test(test_dispatch_indirect); queue_test(test_compute_shader_registers); queue_test(test_tgsm); queue_test(test_geometry_shader); queue_test(test_quad_tessellation); queue_test(test_stream_output); queue_test(test_fl10_stream_output_desc); queue_test(test_stream_output_resume); queue_test(test_stream_output_components); queue_test(test_stream_output_vs); queue_test(test_gather); queue_test(test_gather_c); queue_test(test_depth_bias); queue_test(test_fractional_viewports); queue_for_each_feature_level_in_range(D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_11_0, test_negative_viewports); queue_test(test_early_depth_stencil); queue_test(test_conservative_depth_output); queue_test(test_format_compatibility); queue_test(test_clip_distance); queue_test(test_combined_clip_and_cull_distances); queue_test(test_generate_mips); queue_test(test_alpha_to_coverage); queue_test(test_unbound_multisample_texture); queue_test(test_multiple_viewports); queue_test(test_multisample_resolve); queue_test(test_sample_shading); queue_test(test_sample_mask); queue_test(test_depth_clip); queue_test(test_staging_buffers); queue_test(test_render_a8); queue_test(test_standard_pattern); queue_test(test_desktop_window); queue_test(test_sample_attached_rtv); queue_test(test_color_mask); queue_test(test_independent_blend); queue_test(test_dual_source_blend); run_queued_tests(); }