vkd3d-shader/hlsl: Use a block in hlsl_normalize_binary_exprs().
[vkd3d.git] / tests / shader_runner_d3d11.c
blobe5d2431644e5a322458ca27d2c75709dbf7af35d
1 /*
2 * Copyright 2008 Henri Verbeet for CodeWeavers
3 * Copyright 2015 Józef Kucia for CodeWeavers
4 * Copyright 2021 Zebediah Figura for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #ifdef _WIN32
23 #define COBJMACROS
24 #define CONST_VTABLE
25 #define INITGUID
26 #define VKD3D_TEST_NO_DEFS
27 #include <d3d11_4.h>
28 #define __vkd3d_d3dcommon_h__
29 #define __vkd3d_dxgibase_h__
30 #define __vkd3d_dxgiformat_h__
31 #include "vkd3d_d3dcompiler.h"
32 #include "shader_runner.h"
33 #include "vkd3d_test.h"
35 static HRESULT (WINAPI *pCreateDXGIFactory1)(REFIID iid, void **factory);
37 static HRESULT (WINAPI *pD3D11CreateDevice)(IDXGIAdapter *adapter, D3D_DRIVER_TYPE driver_type,
38 HMODULE swrast, UINT flags, const D3D_FEATURE_LEVEL *feature_levels, UINT levels,
39 UINT sdk_version, ID3D11Device **device_out, D3D_FEATURE_LEVEL *obtained_feature_level,
40 ID3D11DeviceContext **immediate_context);
42 struct d3d11_resource
44 struct resource r;
46 ID3D11Resource *resource;
47 ID3D11Buffer *buffer;
48 ID3D11Texture2D *texture;
49 ID3D11RenderTargetView *rtv;
50 ID3D11DepthStencilView *dsv;
51 ID3D11ShaderResourceView *srv;
52 ID3D11UnorderedAccessView *uav;
53 bool is_uav_counter;
56 static struct d3d11_resource *d3d11_resource(struct resource *r)
58 return CONTAINING_RECORD(r, struct d3d11_resource, r);
61 struct d3d11_shader_runner
63 struct shader_runner r;
64 struct shader_runner_caps caps;
66 ID3D11Device *device;
67 HWND window;
68 IDXGISwapChain *swapchain;
69 ID3D11DeviceContext *immediate_context;
70 ID3D11RasterizerState *rasterizer_state;
73 static struct d3d11_shader_runner *d3d11_shader_runner(struct shader_runner *r)
75 return CONTAINING_RECORD(r, struct d3d11_shader_runner, r);
78 static void set_viewport(ID3D11DeviceContext *context, float x, float y,
79 float width, float height, float min_depth, float max_depth)
81 D3D11_VIEWPORT vp =
83 .TopLeftX = x,
84 .TopLeftY = y,
85 .Width = width,
86 .Height = height,
87 .MinDepth = min_depth,
88 .MaxDepth = max_depth,
91 ID3D11DeviceContext_RSSetViewports(context, 1, &vp);
94 static IDXGIAdapter *create_adapter(void)
96 IDXGIFactory4 *factory4;
97 IDXGIFactory *factory;
98 IDXGIAdapter *adapter;
99 HRESULT hr;
101 if (!pCreateDXGIFactory1)
103 trace("CreateDXGIFactory1() is not available.\n");
104 return NULL;
107 if (FAILED(hr = pCreateDXGIFactory1(&IID_IDXGIFactory, (void **)&factory)))
109 trace("Failed to create IDXGIFactory, hr %#lx.\n", hr);
110 return NULL;
113 adapter = NULL;
114 if (test_options.use_warp_device)
116 if (SUCCEEDED(hr = IDXGIFactory_QueryInterface(factory, &IID_IDXGIFactory4, (void **)&factory4)))
118 hr = IDXGIFactory4_EnumWarpAdapter(factory4, &IID_IDXGIAdapter, (void **)&adapter);
119 IDXGIFactory4_Release(factory4);
121 else
123 trace("Failed to get IDXGIFactory4, hr %#lx.\n", hr);
126 else
128 hr = IDXGIFactory_EnumAdapters(factory, test_options.adapter_idx, &adapter);
130 IDXGIFactory_Release(factory);
131 if (FAILED(hr))
132 trace("Failed to get adapter, hr %#lx.\n", hr);
133 return adapter;
136 static void init_adapter_info(void)
138 char name[MEMBER_SIZE(DXGI_ADAPTER_DESC, Description)];
139 IDXGIAdapter *adapter;
140 DXGI_ADAPTER_DESC desc;
141 unsigned int i;
142 HRESULT hr;
144 if (!(adapter = create_adapter()))
145 return;
147 hr = IDXGIAdapter_GetDesc(adapter, &desc);
148 ok(hr == S_OK, "Failed to get adapter desc, hr %#lx.\n", hr);
150 /* FIXME: Use debugstr_w(). */
151 for (i = 0; i < ARRAY_SIZE(desc.Description) && isprint(desc.Description[i]); ++i)
152 name[i] = desc.Description[i];
153 name[min(i, ARRAY_SIZE(name) - 1)] = '\0';
155 trace("Adapter: %s, %04x:%04x.\n", name, desc.VendorId, desc.DeviceId);
157 if (desc.VendorId == 0x1414 && desc.DeviceId == 0x008c)
159 trace("Using WARP device.\n");
160 test_options.use_warp_device = true;
163 IDXGIAdapter_Release(adapter);
166 static ID3D11Device *create_device(void)
168 static const D3D_FEATURE_LEVEL feature_level[] =
170 D3D_FEATURE_LEVEL_11_0,
171 D3D_FEATURE_LEVEL_10_1,
172 D3D_FEATURE_LEVEL_10_0,
174 IDXGIAdapter *adapter;
175 ID3D11Device *device;
176 UINT flags = 0;
177 HRESULT hr;
179 if (test_options.enable_debug_layer)
180 flags |= D3D11_CREATE_DEVICE_DEBUG;
182 if ((adapter = create_adapter()))
184 hr = pD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags,
185 feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL);
186 IDXGIAdapter_Release(adapter);
187 return SUCCEEDED(hr) ? device : NULL;
190 if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags,
191 feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL)))
192 return device;
193 if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL, flags,
194 feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL)))
195 return device;
196 if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, flags,
197 feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL)))
198 return device;
200 return NULL;
203 static IDXGISwapChain *create_swapchain(ID3D11Device *device, HWND window)
205 DXGI_SWAP_CHAIN_DESC dxgi_desc;
206 IDXGISwapChain *swapchain;
207 IDXGIDevice *dxgi_device;
208 IDXGIAdapter *adapter;
209 IDXGIFactory *factory;
210 HRESULT hr;
212 hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
213 ok(hr == S_OK, "Failed to get DXGI device, hr %#lx.\n", hr);
214 hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter);
215 ok(hr == S_OK, "Failed to get adapter, hr %#lx.\n", hr);
216 IDXGIDevice_Release(dxgi_device);
217 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
218 ok(hr == S_OK, "Failed to get factory, hr %#lx.\n", hr);
219 IDXGIAdapter_Release(adapter);
221 dxgi_desc.BufferDesc.Width = RENDER_TARGET_WIDTH;
222 dxgi_desc.BufferDesc.Height = RENDER_TARGET_HEIGHT;
223 dxgi_desc.BufferDesc.RefreshRate.Numerator = 60;
224 dxgi_desc.BufferDesc.RefreshRate.Denominator = 1;
225 dxgi_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
226 dxgi_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
227 dxgi_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
228 dxgi_desc.SampleDesc.Count = 1;
229 dxgi_desc.SampleDesc.Quality = 0;
230 dxgi_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
231 dxgi_desc.BufferCount = 1;
232 dxgi_desc.OutputWindow = window;
233 dxgi_desc.Windowed = TRUE;
234 dxgi_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
235 dxgi_desc.Flags = 0;
237 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &dxgi_desc, &swapchain);
238 ok(hr == S_OK, "Failed to create swapchain, hr %#lx.\n", hr);
239 IDXGIFactory_Release(factory);
241 return swapchain;
244 static bool get_format_support(ID3D11Device *device, enum DXGI_FORMAT format)
246 D3D11_FEATURE_DATA_FORMAT_SUPPORT2 format_support2 = {.InFormat = format};
247 uint32_t ret = 0;
248 HRESULT hr;
250 hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_FORMAT_SUPPORT2,
251 &format_support2, sizeof(format_support2));
252 ok(hr == S_OK, "Failed to query format support2, hr %#lx.\n", hr);
254 if (format_support2.OutFormatSupport2 & D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD)
255 ret |= FORMAT_CAP_UAV_LOAD;
257 return ret;
260 static BOOL init_test_context(struct d3d11_shader_runner *runner)
262 D3D11_FEATURE_DATA_D3D11_OPTIONS2 options2 = {0};
263 D3D11_FEATURE_DATA_D3D11_OPTIONS3 options3 = {0};
264 D3D11_FEATURE_DATA_DOUBLES doubles = {0};
265 unsigned int rt_width, rt_height;
266 D3D11_RASTERIZER_DESC rs_desc;
267 HRESULT hr;
268 RECT rect;
270 static const enum DXGI_FORMAT formats[] =
272 DXGI_FORMAT_R32_FLOAT,
273 DXGI_FORMAT_R32_UINT,
274 DXGI_FORMAT_R32_SINT,
275 DXGI_FORMAT_R32G32B32A32_FLOAT,
276 DXGI_FORMAT_R32G32B32A32_UINT,
277 DXGI_FORMAT_R32G32B32A32_SINT,
278 DXGI_FORMAT_R16G16B16A16_FLOAT,
279 DXGI_FORMAT_R16G16B16A16_UINT,
280 DXGI_FORMAT_R16G16B16A16_SINT,
281 DXGI_FORMAT_R8G8B8A8_UNORM,
282 DXGI_FORMAT_R8G8B8A8_UINT,
283 DXGI_FORMAT_R8G8B8A8_SINT,
284 DXGI_FORMAT_R16_FLOAT,
285 DXGI_FORMAT_R16_UINT,
286 DXGI_FORMAT_R16_SINT,
287 DXGI_FORMAT_R8_UNORM,
288 DXGI_FORMAT_R8_UINT,
289 DXGI_FORMAT_R8_SINT,
292 memset(runner, 0, sizeof(*runner));
294 if (!(runner->device = create_device()))
296 skip("Failed to create device.\n");
297 return FALSE;
300 runner->caps.runner = "d3d11.dll";
301 runner->caps.minimum_shader_model = SHADER_MODEL_4_0;
302 runner->caps.maximum_shader_model = SHADER_MODEL_5_0;
304 hr = ID3D11Device_CheckFeatureSupport(runner->device, D3D11_FEATURE_DOUBLES,
305 &doubles, sizeof(doubles));
306 ok(hr == S_OK, "Failed to check double precision feature support, hr %#lx.\n", hr);
307 runner->caps.shader_caps[SHADER_CAP_FLOAT64] = doubles.DoublePrecisionFloatShaderOps;
309 hr = ID3D11Device_CheckFeatureSupport(runner->device,
310 D3D11_FEATURE_D3D11_OPTIONS2, &options2, sizeof(options2));
311 ok(hr == S_OK, "Failed to check feature options2 support, hr %#lx.\n", hr);
313 hr = ID3D11Device_CheckFeatureSupport(runner->device,
314 D3D11_FEATURE_D3D11_OPTIONS3, &options3, sizeof(options3));
315 ok(hr == S_OK, "Failed to check feature options3 support, hr %#lx.\n", hr);
317 runner->caps.shader_caps[SHADER_CAP_ROV] = options2.ROVsSupported;
318 runner->caps.shader_caps[SHADER_CAP_RT_VP_ARRAY_INDEX] = options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer;
319 for (unsigned int i = 0; i < ARRAY_SIZE(formats); ++i)
321 runner->caps.format_caps[formats[i]] = get_format_support(runner->device, formats[i]);
324 rt_width = RENDER_TARGET_WIDTH;
325 rt_height = RENDER_TARGET_HEIGHT;
326 SetRect(&rect, 0, 0, rt_width, rt_height);
327 AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
328 runner->window = CreateWindowA("static", "d3dcompiler_test", WS_OVERLAPPEDWINDOW,
329 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL);
330 runner->swapchain = create_swapchain(runner->device, runner->window);
332 ID3D11Device_GetImmediateContext(runner->device, &runner->immediate_context);
334 set_viewport(runner->immediate_context, 0.0f, 0.0f, rt_width, rt_height, 0.0f, 1.0f);
336 rs_desc.FillMode = D3D11_FILL_SOLID;
337 rs_desc.CullMode = D3D11_CULL_NONE;
338 rs_desc.FrontCounterClockwise = FALSE;
339 rs_desc.DepthBias = 0;
340 rs_desc.DepthBiasClamp = 0.0f;
341 rs_desc.SlopeScaledDepthBias = 0.0f;
342 rs_desc.DepthClipEnable = TRUE;
343 rs_desc.ScissorEnable = FALSE;
344 rs_desc.MultisampleEnable = FALSE;
345 rs_desc.AntialiasedLineEnable = FALSE;
346 hr = ID3D11Device_CreateRasterizerState(runner->device, &rs_desc, &runner->rasterizer_state);
347 ok(hr == S_OK, "Failed to create rasterizer state.\n");
349 return TRUE;
352 static void destroy_test_context(struct d3d11_shader_runner *runner)
354 ULONG ref;
356 ID3D11RasterizerState_Release(runner->rasterizer_state);
357 ID3D11DeviceContext_Release(runner->immediate_context);
358 IDXGISwapChain_Release(runner->swapchain);
359 DestroyWindow(runner->window);
361 ref = ID3D11Device_Release(runner->device);
362 ok(!ref, "Device has %lu references left.\n", ref);
365 static ID3D11Buffer *create_buffer(ID3D11Device *device, unsigned int bind_flags, unsigned int size,
366 bool is_raw, unsigned int stride, const void *data)
368 D3D11_SUBRESOURCE_DATA resource_data;
369 D3D11_BUFFER_DESC buffer_desc;
370 ID3D11Buffer *buffer;
371 HRESULT hr;
373 buffer_desc.ByteWidth = size;
374 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
375 buffer_desc.BindFlags = bind_flags;
376 buffer_desc.CPUAccessFlags = 0;
377 if (is_raw)
378 buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
379 else if (stride)
380 buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
381 else
382 buffer_desc.MiscFlags = 0;
383 buffer_desc.StructureByteStride = stride;
385 resource_data.pSysMem = data;
386 resource_data.SysMemPitch = 0;
387 resource_data.SysMemSlicePitch = 0;
389 hr = ID3D11Device_CreateBuffer(device, &buffer_desc, data ? &resource_data : NULL, &buffer);
390 ok(hr == S_OK, "Failed to create buffer, hr %#lx.\n", hr);
391 return buffer;
394 static bool init_resource_2d(struct d3d11_shader_runner *runner, struct d3d11_resource *resource,
395 const struct resource_params *params)
397 D3D11_SUBRESOURCE_DATA resource_data[3];
398 ID3D11Device *device = runner->device;
399 D3D11_TEXTURE2D_DESC desc = {0};
400 UINT quality_levels;
401 HRESULT hr;
403 if (params->desc.level_count > ARRAY_SIZE(resource_data))
404 fatal_error("Level count %u is too high.\n", params->desc.level_count);
406 if (params->desc.sample_count > 1)
408 if (params->desc.level_count > 1)
409 fatal_error("Multisampled texture has multiple levels.\n");
411 if (FAILED(ID3D11Device_CheckMultisampleQualityLevels(device,
412 params->desc.format, params->desc.sample_count, &quality_levels)) || !quality_levels)
414 trace("Format #%x with sample count %u is not supported; skipping.\n",
415 params->desc.format, params->desc.sample_count);
416 return false;
420 desc.Width = params->desc.width;
421 desc.Height = params->desc.height;
422 desc.MipLevels = params->desc.level_count;
423 desc.ArraySize = params->desc.depth;
424 desc.Format = params->desc.format;
425 desc.SampleDesc.Count = max(params->desc.sample_count, 1);
426 desc.Usage = D3D11_USAGE_DEFAULT;
427 if (params->desc.type == RESOURCE_TYPE_UAV)
428 desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;
429 else if (params->desc.type == RESOURCE_TYPE_RENDER_TARGET)
430 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
431 else if (params->desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
432 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
433 else
434 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
436 if (params->data)
438 unsigned int buffer_offset = 0;
440 if (params->desc.sample_count > 1)
441 fatal_error("Cannot upload data to a multisampled texture.\n");
443 for (unsigned int level = 0; level < params->desc.level_count; ++level)
445 unsigned int level_width = get_level_dimension(params->desc.width, level);
446 unsigned int level_height = get_level_dimension(params->desc.height, level);
448 resource_data[level].pSysMem = &params->data[buffer_offset];
449 resource_data[level].SysMemPitch = level_width * params->desc.texel_size;
450 resource_data[level].SysMemSlicePitch = level_height * resource_data[level].SysMemPitch;
451 buffer_offset += resource_data[level].SysMemSlicePitch;
453 hr = ID3D11Device_CreateTexture2D(device, &desc, resource_data, &resource->texture);
455 else
457 hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &resource->texture);
459 ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr);
461 resource->resource = (ID3D11Resource *)resource->texture;
462 if (params->desc.type == RESOURCE_TYPE_UAV)
463 hr = ID3D11Device_CreateUnorderedAccessView(device, resource->resource, NULL, &resource->uav);
464 else if (params->desc.type == RESOURCE_TYPE_RENDER_TARGET)
465 hr = ID3D11Device_CreateRenderTargetView(device, resource->resource, NULL, &resource->rtv);
466 else if (params->desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
467 hr = ID3D11Device_CreateDepthStencilView(device, resource->resource, NULL, &resource->dsv);
468 else
469 hr = ID3D11Device_CreateShaderResourceView(device, resource->resource, NULL, &resource->srv);
470 ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr);
472 return true;
475 static void init_resource_srv_buffer(struct d3d11_shader_runner *runner, struct d3d11_resource *resource,
476 const struct resource_params *params)
478 D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc;
479 ID3D11Device *device = runner->device;
480 HRESULT hr;
482 resource->buffer = create_buffer(device, D3D11_BIND_SHADER_RESOURCE, params->data_size, params->is_raw,
483 params->stride, params->data);
484 resource->resource = (ID3D11Resource *)resource->buffer;
486 srv_desc.Format = params->desc.format;
487 if (params->is_raw)
489 srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
490 srv_desc.BufferEx.FirstElement = 0;
491 srv_desc.BufferEx.NumElements = params->data_size / params->desc.texel_size;
492 srv_desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
494 else
496 srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
497 srv_desc.Buffer.FirstElement = 0;
498 srv_desc.Buffer.NumElements = params->data_size / params->desc.texel_size;
500 hr = ID3D11Device_CreateShaderResourceView(device, resource->resource, &srv_desc, &resource->srv);
501 ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr);
504 static void init_resource_uav_buffer(struct d3d11_shader_runner *runner, struct d3d11_resource *resource,
505 const struct resource_params *params)
507 D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc;
508 ID3D11Device *device = runner->device;
509 HRESULT hr;
511 resource->buffer = create_buffer(device, D3D11_BIND_UNORDERED_ACCESS, params->data_size, params->is_raw,
512 params->stride, params->data);
513 resource->resource = (ID3D11Resource *)resource->buffer;
514 resource->is_uav_counter = params->is_uav_counter;
516 uav_desc.Format = params->desc.format;
517 uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
518 uav_desc.Buffer.FirstElement = 0;
519 uav_desc.Buffer.NumElements = params->data_size / params->desc.texel_size;
520 if (params->is_raw)
521 uav_desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
522 else if (params->is_uav_counter)
523 uav_desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER;
524 else
525 uav_desc.Buffer.Flags = 0;
526 hr = ID3D11Device_CreateUnorderedAccessView(device, resource->resource, &uav_desc, &resource->uav);
527 ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr);
530 static struct resource *d3d11_runner_create_resource(struct shader_runner *r, const struct resource_params *params)
532 struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
533 ID3D11Device *device = runner->device;
534 struct d3d11_resource *resource;
536 resource = calloc(1, sizeof(*resource));
537 init_resource(&resource->r, params);
539 switch (params->desc.type)
541 case RESOURCE_TYPE_RENDER_TARGET:
542 case RESOURCE_TYPE_DEPTH_STENCIL:
543 case RESOURCE_TYPE_TEXTURE:
544 if (params->desc.dimension == RESOURCE_DIMENSION_BUFFER)
545 init_resource_srv_buffer(runner, resource, params);
546 else if (!init_resource_2d(runner, resource, params))
547 return NULL;
548 break;
550 case RESOURCE_TYPE_UAV:
551 if (params->desc.dimension == RESOURCE_DIMENSION_BUFFER)
552 init_resource_uav_buffer(runner, resource, params);
553 else if (!init_resource_2d(runner, resource, params))
554 return NULL;
555 break;
557 case RESOURCE_TYPE_VERTEX_BUFFER:
558 resource->buffer = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, params->data_size, params->is_raw,
559 params->stride, params->data);
560 resource->resource = (ID3D11Resource *)resource->buffer;
561 break;
564 return &resource->r;
567 static void d3d11_runner_destroy_resource(struct shader_runner *r, struct resource *res)
569 struct d3d11_resource *resource = d3d11_resource(res);
571 ID3D11Resource_Release(resource->resource);
572 if (resource->rtv)
573 ID3D11RenderTargetView_Release(resource->rtv);
574 if (resource->dsv)
575 ID3D11DepthStencilView_Release(resource->dsv);
576 if (resource->srv)
577 ID3D11ShaderResourceView_Release(resource->srv);
578 if (resource->uav)
579 ID3D11UnorderedAccessView_Release(resource->uav);
580 free(resource);
583 static ID3D11SamplerState *create_sampler(ID3D11Device *device, const struct sampler *sampler)
585 ID3D11SamplerState *d3d11_sampler;
586 D3D11_SAMPLER_DESC desc = {0};
587 HRESULT hr;
589 /* Members of D3D11_FILTER are compatible with D3D12_FILTER. */
590 desc.Filter = (D3D11_FILTER)sampler->filter;
591 /* Members of D3D11_TEXTURE_ADDRESS_MODE are compatible with D3D12_TEXTURE_ADDRESS_MODE. */
592 desc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)sampler->u_address;
593 desc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)sampler->v_address;
594 desc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)sampler->w_address;
595 desc.ComparisonFunc = sampler->func;
596 desc.MaxLOD = D3D11_FLOAT32_MAX;
598 hr = ID3D11Device_CreateSamplerState(device, &desc, &d3d11_sampler);
599 ok(hr == S_OK, "Failed to create sampler state, hr %#lx.\n", hr);
600 return d3d11_sampler;
603 static bool d3d11_runner_dispatch(struct shader_runner *r, unsigned int x, unsigned int y, unsigned int z)
605 struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
606 ID3D11DeviceContext *context = runner->immediate_context;
607 ID3D11Device *device = runner->device;
608 ID3D11ComputeShader *cs;
609 ID3D10Blob *cs_code;
610 HRESULT hr;
611 size_t i;
613 if (!(cs_code = compile_hlsl(&runner->r, SHADER_TYPE_CS)))
614 return false;
616 hr = ID3D11Device_CreateComputeShader(device, ID3D10Blob_GetBufferPointer(cs_code),
617 ID3D10Blob_GetBufferSize(cs_code), NULL, &cs);
618 ok(hr == S_OK, "Failed to create compute shader, hr %#lx.\n", hr);
620 if (runner->r.uniform_count)
622 ID3D11Buffer *cb;
624 cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER,
625 runner->r.uniform_count * sizeof(*runner->r.uniforms), false, 0, runner->r.uniforms);
626 ID3D11DeviceContext_CSSetConstantBuffers(context, 0, 1, &cb);
627 ID3D11Buffer_Release(cb);
630 for (i = 0; i < runner->r.resource_count; ++i)
632 struct d3d11_resource *resource = d3d11_resource(runner->r.resources[i]);
634 switch (resource->r.desc.type)
636 case RESOURCE_TYPE_TEXTURE:
637 ID3D11DeviceContext_CSSetShaderResources(context, resource->r.desc.slot, 1, &resource->srv);
638 break;
640 case RESOURCE_TYPE_UAV:
641 ID3D11DeviceContext_CSSetUnorderedAccessViews(context, resource->r.desc.slot, 1, &resource->uav, NULL);
642 break;
644 case RESOURCE_TYPE_RENDER_TARGET:
645 case RESOURCE_TYPE_DEPTH_STENCIL:
646 case RESOURCE_TYPE_VERTEX_BUFFER:
647 break;
651 for (i = 0; i < runner->r.sampler_count; ++i)
653 struct sampler *sampler = &runner->r.samplers[i];
654 ID3D11SamplerState *d3d11_sampler;
656 d3d11_sampler = create_sampler(device, sampler);
657 ID3D11DeviceContext_CSSetSamplers(context, sampler->slot, 1, &d3d11_sampler);
658 ID3D11SamplerState_Release(d3d11_sampler);
661 ID3D11DeviceContext_CSSetShader(context, cs, NULL, 0);
662 ID3D11DeviceContext_Dispatch(context, x, y, z);
664 ID3D11ComputeShader_Release(cs);
666 return true;
669 static void d3d11_runner_clear(struct shader_runner *r, struct resource *res, const struct vec4 *clear_value)
671 struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
672 ID3D11DeviceContext *context = runner->immediate_context;
673 struct d3d11_resource *resource = d3d11_resource(res);
675 switch (resource->r.desc.type)
677 case RESOURCE_TYPE_RENDER_TARGET:
678 ID3D11DeviceContext_ClearRenderTargetView(context, resource->rtv, (const float *)clear_value);
679 break;
681 case RESOURCE_TYPE_DEPTH_STENCIL:
682 ID3D11DeviceContext_ClearDepthStencilView(context, resource->dsv, D3D11_CLEAR_DEPTH, clear_value->x, 0);
683 break;
685 default:
686 fatal_error("Clears are not implemented for resource type %u.\n", resource->r.desc.type);
690 static bool d3d11_runner_draw(struct shader_runner *r,
691 D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count, unsigned int instance_count)
693 ID3D10Blob *vs_code, *ps_code, *hs_code = NULL, *ds_code = NULL, *gs_code = NULL;
694 ID3D11UnorderedAccessView *uavs[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0};
695 ID3D11RenderTargetView *rtvs[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0};
696 struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
697 ID3D11DeviceContext *context = runner->immediate_context;
698 unsigned int fb_width, fb_height, rtv_count = 0;
699 unsigned int min_uav_slot = ARRAY_SIZE(uavs);
700 ID3D11DepthStencilState *ds_state = NULL;
701 D3D11_DEPTH_STENCIL_DESC ds_desc = {0};
702 ID3D11Device *device = runner->device;
703 ID3D11DepthStencilView *dsv = NULL;
704 ID3D11GeometryShader *gs;
705 ID3D11Buffer *cb = NULL;
706 ID3D11VertexShader *vs;
707 ID3D11DomainShader *ds;
708 ID3D11PixelShader *ps;
709 ID3D11HullShader *hs;
710 bool succeeded;
711 unsigned int i;
712 HRESULT hr;
714 vs_code = compile_hlsl(&runner->r, SHADER_TYPE_VS);
715 ps_code = compile_hlsl(&runner->r, SHADER_TYPE_PS);
716 succeeded = vs_code && ps_code;
718 if (runner->r.shader_source[SHADER_TYPE_HS])
720 hs_code = compile_hlsl(&runner->r, SHADER_TYPE_HS);
721 succeeded = succeeded && hs_code;
723 if (runner->r.shader_source[SHADER_TYPE_DS])
725 ds_code = compile_hlsl(&runner->r, SHADER_TYPE_DS);
726 succeeded = succeeded && ds_code;
728 if (runner->r.shader_source[SHADER_TYPE_GS])
730 gs_code = compile_hlsl(&runner->r, SHADER_TYPE_GS);
731 succeeded = succeeded && gs_code;
734 if (!succeeded)
736 if (ps_code)
737 ID3D10Blob_Release(ps_code);
738 if (vs_code)
739 ID3D10Blob_Release(vs_code);
740 if (hs_code)
741 ID3D10Blob_Release(hs_code);
742 if (ds_code)
743 ID3D10Blob_Release(ds_code);
744 if (gs_code)
745 ID3D10Blob_Release(gs_code);
746 return false;
749 hr = ID3D11Device_CreateVertexShader(device, ID3D10Blob_GetBufferPointer(vs_code),
750 ID3D10Blob_GetBufferSize(vs_code), NULL, &vs);
751 ok(hr == S_OK, "Failed to create vertex shader, hr %#lx.\n", hr);
753 hr = ID3D11Device_CreatePixelShader(device, ID3D10Blob_GetBufferPointer(ps_code),
754 ID3D10Blob_GetBufferSize(ps_code), NULL, &ps);
755 ok(hr == S_OK, "Failed to create pixel shader, hr %#lx.\n", hr);
757 if (hs_code)
759 hr = ID3D11Device_CreateHullShader(device, ID3D10Blob_GetBufferPointer(hs_code),
760 ID3D10Blob_GetBufferSize(hs_code), NULL, &hs);
761 ok(hr == S_OK, "Failed to create hull shader, hr %#lx.\n", hr);
763 if (ds_code)
765 hr = ID3D11Device_CreateDomainShader(device, ID3D10Blob_GetBufferPointer(ds_code),
766 ID3D10Blob_GetBufferSize(ds_code), NULL, &ds);
767 ok(hr == S_OK, "Failed to create domain shader, hr %#lx.\n", hr);
769 if (gs_code)
771 hr = ID3D11Device_CreateGeometryShader(device, ID3D10Blob_GetBufferPointer(gs_code),
772 ID3D10Blob_GetBufferSize(gs_code), NULL, &gs);
773 ok(hr == S_OK, "Failed to create geometry shader, hr %#lx.\n", hr);
776 ID3D10Blob_Release(ps_code);
777 if (hs_code)
778 ID3D10Blob_Release(hs_code);
779 if (ds_code)
780 ID3D10Blob_Release(ds_code);
781 if (gs_code)
782 ID3D10Blob_Release(gs_code);
784 if (runner->r.uniform_count)
786 cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER,
787 runner->r.uniform_count * sizeof(*runner->r.uniforms), false, 0, runner->r.uniforms);
788 ID3D11DeviceContext_VSSetConstantBuffers(context, 0, 1, &cb);
789 ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb);
790 if (hs_code)
791 ID3D11DeviceContext_HSSetConstantBuffers(context, 0, 1, &cb);
792 if (ds_code)
793 ID3D11DeviceContext_DSSetConstantBuffers(context, 0, 1, &cb);
794 if (gs_code)
795 ID3D11DeviceContext_GSSetConstantBuffers(context, 0, 1, &cb);
798 fb_width = ~0u;
799 fb_height = ~0u;
800 for (i = 0; i < runner->r.resource_count; ++i)
802 struct d3d11_resource *resource = d3d11_resource(runner->r.resources[i]);
803 unsigned int stride = get_vb_stride(&runner->r, resource->r.desc.slot);
804 unsigned int offset = 0;
806 switch (resource->r.desc.type)
808 case RESOURCE_TYPE_RENDER_TARGET:
809 rtvs[resource->r.desc.slot] = resource->rtv;
810 rtv_count = max(rtv_count, resource->r.desc.slot + 1);
811 if (resource->r.desc.width < fb_width)
812 fb_width = resource->r.desc.width;
813 if (resource->r.desc.height < fb_height)
814 fb_height = resource->r.desc.height;
815 break;
817 case RESOURCE_TYPE_DEPTH_STENCIL:
818 dsv = resource->dsv;
819 ds_desc.DepthEnable = TRUE;
820 ds_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
821 ds_desc.DepthFunc = runner->r.depth_func;
822 hr = ID3D11Device_CreateDepthStencilState(device, &ds_desc, &ds_state);
823 ok(hr == S_OK, "Failed to create depth/stencil state, hr %#lx.\n", hr);
824 ID3D11DeviceContext_OMSetDepthStencilState(context, ds_state, 0);
825 if (resource->r.desc.width < fb_width)
826 fb_width = resource->r.desc.width;
827 if (resource->r.desc.height < fb_height)
828 fb_height = resource->r.desc.height;
829 break;
831 case RESOURCE_TYPE_TEXTURE:
832 ID3D11DeviceContext_PSSetShaderResources(context, resource->r.desc.slot, 1, &resource->srv);
833 break;
835 case RESOURCE_TYPE_UAV:
836 uavs[resource->r.desc.slot] = resource->uav;
837 min_uav_slot = min(min_uav_slot, resource->r.desc.slot);
838 break;
840 case RESOURCE_TYPE_VERTEX_BUFFER:
841 ID3D11DeviceContext_IASetVertexBuffers(context, resource->r.desc.slot, 1,
842 (ID3D11Buffer **)&resource->resource, &stride, &offset);
843 break;
847 ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, rtv_count, rtvs, dsv,
848 min_uav_slot, ARRAY_SIZE(uavs) - min_uav_slot, &uavs[min_uav_slot], NULL);
850 for (i = 0; i < runner->r.sampler_count; ++i)
852 struct sampler *sampler = &runner->r.samplers[i];
853 ID3D11SamplerState *d3d11_sampler;
855 d3d11_sampler = create_sampler(device, sampler);
856 ID3D11DeviceContext_PSSetSamplers(context, sampler->slot, 1, &d3d11_sampler);
857 ID3D11SamplerState_Release(d3d11_sampler);
860 if (runner->r.input_element_count)
862 D3D11_INPUT_ELEMENT_DESC *descs;
863 ID3D11InputLayout *input_layout;
865 descs = calloc(runner->r.input_element_count, sizeof(*descs));
866 for (i = 0; i < runner->r.input_element_count; ++i)
868 const struct input_element *element = &runner->r.input_elements[i];
869 D3D11_INPUT_ELEMENT_DESC *desc = &descs[i];
871 desc->SemanticName = element->name;
872 desc->SemanticIndex = element->index;
873 desc->Format = element->format;
874 desc->InputSlot = element->slot;
875 desc->AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
876 desc->InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
879 hr = ID3D11Device_CreateInputLayout(device, descs, runner->r.input_element_count,
880 ID3D10Blob_GetBufferPointer(vs_code), ID3D10Blob_GetBufferSize(vs_code), &input_layout);
881 ok(hr == S_OK, "Failed to create input layout, hr %#lx.\n", hr);
882 ID3D11DeviceContext_IASetInputLayout(context, input_layout);
883 ID3D11InputLayout_Release(input_layout);
886 ID3D10Blob_Release(vs_code);
888 if (r->sample_mask)
889 ID3D11DeviceContext_OMSetBlendState(context, NULL, NULL, r->sample_mask);
890 ID3D11DeviceContext_IASetPrimitiveTopology(context, primitive_topology);
891 ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0);
892 ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0);
893 if (hs_code)
894 ID3D11DeviceContext_HSSetShader(context, hs, NULL, 0);
895 if (ds_code)
896 ID3D11DeviceContext_DSSetShader(context, ds, NULL, 0);
897 if (gs_code)
898 ID3D11DeviceContext_GSSetShader(context, gs, NULL, 0);
899 ID3D11DeviceContext_RSSetState(context, runner->rasterizer_state);
900 set_viewport(context, 0.0f, 0.0f, fb_width, fb_height, 0.0f, 1.0f);
902 ID3D11DeviceContext_DrawInstanced(context, vertex_count, instance_count, 0, 0);
904 ID3D11PixelShader_Release(ps);
905 ID3D11VertexShader_Release(vs);
906 if (hs_code)
907 ID3D11HullShader_Release(hs);
908 if (ds_code)
909 ID3D11DomainShader_Release(ds);
910 if (gs_code)
911 ID3D11GeometryShader_Release(gs);
912 if (cb)
913 ID3D11Buffer_Release(cb);
914 if (ds_state)
915 ID3D11DepthStencilState_Release(ds_state);
917 return true;
920 static bool d3d11_runner_copy(struct shader_runner *r, struct resource *src, struct resource *dst)
922 struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
923 struct d3d11_resource *s = d3d11_resource(src);
924 struct d3d11_resource *d = d3d11_resource(dst);
926 ID3D11DeviceContext_CopyResource(runner->immediate_context, d->resource, s->resource);
928 return true;
931 struct d3d11_resource_readback
933 struct resource_readback rb;
934 ID3D11Resource *resource;
935 unsigned int sub_resource_idx;
938 static struct resource_readback *d3d11_runner_get_resource_readback(struct shader_runner *r,
939 struct resource *res, unsigned int sub_resource_idx)
941 struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
942 struct d3d11_resource_readback *rb = malloc(sizeof(*rb));
943 ID3D11Resource *resolved_resource = NULL, *src_resource;
944 struct d3d11_resource *resource = d3d11_resource(res);
945 D3D11_TEXTURE2D_DESC texture_desc;
946 D3D11_MAPPED_SUBRESOURCE map_desc;
947 D3D11_BUFFER_DESC buffer_desc;
948 bool is_ms = false;
949 HRESULT hr;
951 src_resource = resource->resource;
952 switch (resource->r.desc.type)
954 case RESOURCE_TYPE_RENDER_TARGET:
955 case RESOURCE_TYPE_DEPTH_STENCIL:
956 case RESOURCE_TYPE_UAV:
957 if (resource->r.desc.dimension == RESOURCE_DIMENSION_BUFFER)
959 ID3D11Buffer_GetDesc(resource->buffer, &buffer_desc);
960 buffer_desc.Usage = D3D11_USAGE_STAGING;
961 buffer_desc.BindFlags = 0;
962 buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
963 buffer_desc.MiscFlags = 0;
964 hr = ID3D11Device_CreateBuffer(runner->device, &buffer_desc, NULL, (ID3D11Buffer **)&rb->resource);
965 ok(hr == S_OK, "Failed to create buffer, hr %#lx.\n", hr);
967 else
969 ID3D11Texture2D_GetDesc(resource->texture, &texture_desc);
970 is_ms = texture_desc.SampleDesc.Count > 1;
971 texture_desc.SampleDesc.Count = 1;
972 texture_desc.SampleDesc.Quality = 0;
973 texture_desc.Usage = D3D11_USAGE_STAGING;
974 texture_desc.BindFlags = 0;
975 texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
976 texture_desc.MiscFlags = 0;
977 hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, (ID3D11Texture2D **)&rb->resource);
978 ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr);
979 if (is_ms)
981 texture_desc.Usage = D3D11_USAGE_DEFAULT;
982 hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL,
983 (ID3D11Texture2D **)&resolved_resource);
984 ok(hr == S_OK, "Failed to create multisampled texture, hr %#lx.\n", hr);
985 ID3D11DeviceContext_ResolveSubresource(runner->immediate_context, resolved_resource, 0,
986 resource->resource, 0, texture_desc.Format);
987 src_resource = resolved_resource;
990 break;
992 case RESOURCE_TYPE_VERTEX_BUFFER:
993 case RESOURCE_TYPE_TEXTURE:
994 assert(0);
997 if (resource->is_uav_counter)
998 ID3D11DeviceContext_CopyStructureCount(runner->immediate_context, (ID3D11Buffer *)rb->resource, 0, resource->uav);
999 else
1000 ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, src_resource);
1001 hr = ID3D11DeviceContext_Map(runner->immediate_context, rb->resource,
1002 sub_resource_idx, D3D11_MAP_READ, 0, &map_desc);
1003 ok(hr == S_OK, "Failed to map texture, hr %#lx.\n", hr);
1005 if (resolved_resource)
1006 ID3D11Resource_Release(resolved_resource);
1008 rb->rb.data = map_desc.pData;
1009 rb->rb.row_pitch = map_desc.RowPitch;
1010 rb->rb.width = resource->r.desc.width;
1011 rb->rb.height = resource->r.desc.height;
1012 rb->rb.depth = 1;
1013 rb->sub_resource_idx = sub_resource_idx;
1015 return &rb->rb;
1018 static void d3d11_runner_release_readback(struct shader_runner *r, struct resource_readback *rb)
1020 struct d3d11_resource_readback *d3d11_rb = CONTAINING_RECORD(rb, struct d3d11_resource_readback, rb);
1021 struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
1023 ID3D11DeviceContext_Unmap(runner->immediate_context, d3d11_rb->resource, d3d11_rb->sub_resource_idx);
1024 ID3D11Resource_Release(d3d11_rb->resource);
1025 free(d3d11_rb);
1028 static const struct shader_runner_ops d3d11_runner_ops =
1030 .create_resource = d3d11_runner_create_resource,
1031 .destroy_resource = d3d11_runner_destroy_resource,
1032 .dispatch = d3d11_runner_dispatch,
1033 .clear = d3d11_runner_clear,
1034 .draw = d3d11_runner_draw,
1035 .copy = d3d11_runner_copy,
1036 .get_resource_readback = d3d11_runner_get_resource_readback,
1037 .release_readback = d3d11_runner_release_readback,
1040 void run_shader_tests_d3d11(void)
1042 struct d3d11_shader_runner runner;
1043 HMODULE dxgi_module, d3d11_module;
1045 d3d11_module = LoadLibraryA("d3d11.dll");
1046 dxgi_module = LoadLibraryA("dxgi.dll");
1047 if (d3d11_module && dxgi_module)
1049 pCreateDXGIFactory1 = (void *)GetProcAddress(dxgi_module, "CreateDXGIFactory1");
1050 pD3D11CreateDevice = (void *)GetProcAddress(d3d11_module, "D3D11CreateDevice");
1052 init_adapter_info();
1053 if (init_test_context(&runner))
1055 run_shader_tests(&runner.r, &runner.caps, &d3d11_runner_ops, NULL);
1056 destroy_test_context(&runner);
1059 FreeLibrary(d3d11_module);
1060 FreeLibrary(dxgi_module);
1063 #endif