VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/test/d3d11main.cpp

Last change on this file was 103983, checked in by vboxsync, 2 months ago

WDDM: D3D11 test

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.1 KB
Line 
1/* $Id: d3d11main.cpp 103983 2024-03-21 12:06:03Z vboxsync $ */
2/** @file
3 * D3D testcase. Win32 application to run D3D11 tests.
4 */
5
6/*
7 * Copyright (C) 2017-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include "d3d11render.h"
29
30#include <iprt/file.h>
31#include <iprt/formats/bmp.h>
32#include <iprt/string.h>
33
34/*
35 * Utilities.
36 */
37uint8_t *readBmpFile(char const *pszFilename, uint32_t cbPixel, uint32_t *pWidth, uint32_t *pHeight, uint32_t *pcbData)
38{
39 uint8_t *pu8Data = NULL;
40 uint32_t cbFileData = 0;
41
42 RTFILE f = NIL_RTFILE;
43 int rc = RTFileOpen(&f, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
44 if (RT_SUCCESS(rc))
45 {
46 BMPFILEHDR fileHdr;
47 rc = RTFileRead(f, &fileHdr, sizeof(fileHdr), NULL);
48 if (RT_SUCCESS(rc))
49 {
50 uint32_t const cbHdr = fileHdr.offBits - sizeof(fileHdr);
51 if (cbHdr == sizeof(BITMAPV4HEADER))
52 {
53 BITMAPV4HEADER hdrV4;
54 rc = RTFileRead(f, &hdrV4, sizeof(hdrV4), NULL);
55 if (RT_SUCCESS(rc))
56 {
57 *pWidth = hdrV4.bV4Width;
58 *pHeight = (uint32_t)-hdrV4.bV4Height;
59 }
60 }
61 else if (cbHdr == sizeof(BMPWIN3XINFOHDR))
62 {
63 BMPWIN3XINFOHDR coreHdr;
64 rc = RTFileRead(f, &coreHdr, sizeof(coreHdr), NULL);
65 if (RT_SUCCESS(rc))
66 {
67 *pWidth = coreHdr.uWidth;
68 *pHeight = (uint32_t)(-(int32_t)coreHdr.uHeight);
69 }
70 }
71 else
72 rc = VERR_NOT_SUPPORTED;
73
74 if (RT_SUCCESS(rc))
75 {
76 cbFileData = fileHdr.cbFileSize - fileHdr.offBits;
77 pu8Data = (uint8_t *)RTMemAlloc(cbFileData);
78 if (pu8Data)
79 rc = RTFileRead(f, pu8Data, cbFileData, NULL);
80 else
81 rc = VERR_NO_MEMORY;
82 }
83 }
84
85 RTFileClose(f);
86 }
87
88 if (RT_SUCCESS(rc))
89 {
90 /* If the actual data has less bits than 32, then convert the pixels. */
91 uint32_t const *s = (uint32_t *)pu8Data;
92 if (cbPixel == 2)
93 {
94 uint16_t *d = (uint16_t *)pu8Data;
95 for (unsigned i = 0 ; i < cbFileData / 4; ++i)
96 *d++ = (uint16_t)*s++;
97 }
98 else if (cbPixel == 1)
99 {
100 uint8_t *d = (uint8_t *)pu8Data;
101 for (unsigned i = 0 ; i < cbFileData / 4; ++i)
102 *d++ = (uint8_t)*s++;
103 }
104
105 *pcbData = (cbFileData / 4) * cbPixel;
106 }
107 else
108 {
109 RTMemFree(pu8Data);
110 pu8Data = NULL;
111 }
112
113 return pu8Data;
114}
115
116
117class D3D11Test : public D3D11DeviceProvider
118{
119public:
120 D3D11Test();
121 ~D3D11Test();
122
123 HRESULT Init(HINSTANCE hInstance, int argc, char **argv, int nCmdShow);
124 int Run();
125
126 virtual ID3D11Device *Device();
127 virtual ID3D11DeviceContext *ImmediateContext();
128 virtual ID3D11RenderTargetView *RenderTargetView();
129 virtual ID3D11DepthStencilView *DepthStencilView();
130
131private:
132 HRESULT initWindow(HINSTANCE hInstance, int nCmdShow);
133 HRESULT initDirect3D11();
134 void parseCmdLine(int argc, char **argv);
135 static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
136
137 int miRenderId;
138 enum
139 {
140 RenderModeStep = 0,
141 RenderModeContinuous = 1,
142 RenderModeFPS = 2
143 } miRenderMode;
144
145 HWND mHwnd;
146 UINT mRTWidth;
147 UINT mRTHeight;
148
149 struct
150 {
151 ID3D11Device *pDevice; /* Device for rendering. */
152 ID3D11DeviceContext *pImmediateContext; /* Associated context. */
153 IDXGIFactory *pDxgiFactory; /* DXGI Factory associated with the rendering device. */
154 ID3D11Texture2D *pRenderTarget; /* The render target. */
155 ID3D11RenderTargetView *pRenderTargetView; /* The render target view. */
156 IDXGIResource *pDxgiResource; /* Interface of the render target. */
157 IDXGIKeyedMutex *pDXGIKeyedMutex; /* Synchronization interface for the render device. */
158 ID3D11Texture2D *pDepthStencilBuffer;
159 ID3D11DepthStencilView *pDepthStencilView;
160 } mRender;
161
162 HANDLE mSharedHandle;
163
164 struct
165 {
166 ID3D11Device *pDevice; /* Device for the output drawing. */
167 ID3D11DeviceContext *pImmediateContext; /* Corresponding context. */
168 IDXGIFactory *pDxgiFactory; /* DXGI Factory associated with the output device. */
169 IDXGISwapChain *pSwapChain; /* Swap chain for displaying in the mHwnd window. */
170 ID3D11Texture2D *pSharedTexture; /* The texture to draw. Shared resource of mRender.pRenderTarget */
171 IDXGIKeyedMutex *pDXGIKeyedMutex; /* Synchronization interface for the render device. */
172 } mOutput;
173
174 D3D11Render *mpRender;
175};
176
177D3D11Test::D3D11Test()
178 :
179 miRenderId(1),
180 miRenderMode(RenderModeStep),
181 mHwnd(0),
182 mRTWidth(0),
183 mRTHeight(0),
184 mSharedHandle(0),
185 mpRender(0)
186{
187 RT_ZERO(mRender);
188 RT_ZERO(mOutput);
189}
190
191D3D11Test::~D3D11Test()
192{
193 if (mpRender)
194 {
195 delete mpRender;
196 mpRender = 0;
197 }
198
199 if (mOutput.pImmediateContext)
200 mOutput.pImmediateContext->ClearState();
201 if (mRender.pImmediateContext)
202 mRender.pImmediateContext->ClearState();
203
204 D3D_RELEASE(mOutput.pDevice);
205 D3D_RELEASE(mOutput.pImmediateContext);
206 D3D_RELEASE(mOutput.pDxgiFactory);
207 D3D_RELEASE(mOutput.pSwapChain);
208 D3D_RELEASE(mOutput.pSharedTexture);
209 D3D_RELEASE(mOutput.pDXGIKeyedMutex);
210
211 D3D_RELEASE(mRender.pDevice);
212 D3D_RELEASE(mRender.pImmediateContext);
213 D3D_RELEASE(mRender.pDxgiFactory);
214 D3D_RELEASE(mRender.pRenderTarget);
215 D3D_RELEASE(mRender.pRenderTargetView);
216 D3D_RELEASE(mRender.pDxgiResource);
217 D3D_RELEASE(mRender.pDXGIKeyedMutex);
218}
219
220LRESULT CALLBACK D3D11Test::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
221{
222 switch (msg)
223 {
224 case WM_CLOSE:
225 DestroyWindow(hwnd);
226 return 0;
227
228 case WM_DESTROY:
229 PostQuitMessage(0);
230 return 0;
231
232 default:
233 return DefWindowProcA(hwnd, msg, wParam, lParam);
234 }
235}
236
237HRESULT D3D11Test::initWindow(HINSTANCE hInstance,
238 int nCmdShow)
239{
240 HRESULT hr = S_OK;
241
242 WNDCLASSA wc;
243 RT_ZERO(wc);
244 wc.style = CS_HREDRAW | CS_VREDRAW;
245 wc.lpfnWndProc = wndProc;
246 wc.cbClsExtra = 0;
247 wc.cbWndExtra = 0;
248 wc.hInstance = hInstance;
249 wc.hIcon = LoadIcon(0, IDI_APPLICATION);
250 wc.hCursor = LoadCursor(0, IDC_ARROW);
251 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
252 wc.lpszMenuName = 0;
253 wc.lpszClassName = "D3D11TestWndClassName";
254
255 if (RegisterClassA(&wc))
256 {
257 RECT r = {0, 0, 800, 600};
258 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, false);
259
260 mHwnd = CreateWindowA("D3D11TestWndClassName",
261 "D3D11 Test",
262 WS_OVERLAPPEDWINDOW,
263 100, 100, r.right, r.bottom,
264 0, 0, hInstance, 0);
265 if (mHwnd)
266 {
267 ShowWindow(mHwnd, nCmdShow);
268 UpdateWindow(mHwnd);
269 }
270 else
271 {
272 D3DTestShowError(hr, "CreateWindow");
273 hr = E_FAIL;
274 }
275 }
276 else
277 {
278 D3DTestShowError(hr, "RegisterClass");
279 hr = E_FAIL;
280 }
281
282 return hr;
283}
284
285static HRESULT d3d11TestCreateDevice(ID3D11Device **ppDevice,
286 ID3D11DeviceContext **ppImmediateContext,
287 IDXGIFactory **ppDxgiFactory)
288{
289 HRESULT hr = S_OK;
290
291 IDXGIAdapter *pAdapter = NULL; /* Default adapter. */
292 static const D3D_FEATURE_LEVEL aFeatureLevels[] =
293 {
294 D3D_FEATURE_LEVEL_11_1,
295 D3D_FEATURE_LEVEL_11_0,
296 D3D_FEATURE_LEVEL_10_1,
297 D3D_FEATURE_LEVEL_10_0,
298 D3D_FEATURE_LEVEL_9_3,
299 D3D_FEATURE_LEVEL_9_2,
300 D3D_FEATURE_LEVEL_9_1
301 };
302 UINT Flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
303#ifdef DEBUG
304 Flags |= D3D11_CREATE_DEVICE_DEBUG;
305#endif
306 D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_9_1;
307
308 hr = D3D11CreateDevice(pAdapter,
309 D3D_DRIVER_TYPE_HARDWARE,
310 NULL,
311 Flags,
312 aFeatureLevels,
313 RT_ELEMENTS(aFeatureLevels),
314 D3D11_SDK_VERSION,
315 ppDevice,
316 &FeatureLevel,
317 ppImmediateContext);
318 if (FAILED(hr) && RT_BOOL(Flags & D3D11_CREATE_DEVICE_DEBUG))
319 {
320 /* Device creation may fail because _DEBUG flag requires "D3D11 SDK Layers for Windows 10" ("Graphics Tools"):
321 * Settings/System/Apps/Optional features/Add a feature/Graphics Tools
322 * Retry without the flag.
323 */
324 Flags &= ~D3D11_CREATE_DEVICE_DEBUG;
325 hr = D3D11CreateDevice(pAdapter,
326 D3D_DRIVER_TYPE_HARDWARE,
327 NULL,
328 Flags,
329 aFeatureLevels,
330 RT_ELEMENTS(aFeatureLevels),
331 D3D11_SDK_VERSION,
332 ppDevice,
333 &FeatureLevel,
334 ppImmediateContext);
335 }
336 D3DAssertHR(hr);
337
338 if (FeatureLevel != D3D_FEATURE_LEVEL_11_1)
339 {
340 char sz[128];
341 RTStrPrintf(sz, sizeof(sz), "Feature level %x", FeatureLevel);
342 D3DTestShowError(hr, sz);
343 }
344
345 IDXGIDevice *pDxgiDevice = 0;
346 hr = (*ppDevice)->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDxgiDevice);
347 if (SUCCEEDED(hr))
348 {
349 IDXGIAdapter *pDxgiAdapter = 0;
350 hr = pDxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&pDxgiAdapter);
351 if (SUCCEEDED(hr))
352 {
353 HTEST(pDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)ppDxgiFactory));
354 D3D_RELEASE(pDxgiAdapter);
355 }
356 else
357 D3DTestShowError(hr, "IDXGIAdapter");
358
359 D3D_RELEASE(pDxgiDevice);
360 }
361 else
362 D3DTestShowError(hr, "IDXGIDevice");
363
364 return hr;
365}
366
367HRESULT D3D11Test::initDirect3D11()
368{
369 HRESULT hr = S_OK;
370
371 RECT clientRect;
372 GetClientRect(mHwnd, &clientRect);
373 mRTWidth = clientRect.right;
374 mRTHeight = clientRect.bottom;
375
376 bool const fDirectOutput = mpRender->IsDirectOutputRequired(this);
377
378 /*
379 * Render.
380 */
381 d3d11TestCreateDevice(&mRender.pDevice,
382 &mRender.pImmediateContext,
383 &mRender.pDxgiFactory);
384 if (mRender.pDevice)
385 {
386 if (!fDirectOutput)
387 {
388 D3D11_TEXTURE2D_DESC texDesc;
389 RT_ZERO(texDesc);
390 texDesc.Width = mRTWidth;
391 texDesc.Height = mRTHeight;
392 texDesc.MipLevels = 1;
393 texDesc.ArraySize = 1;
394 texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
395 texDesc.SampleDesc.Count = 1;
396 texDesc.SampleDesc.Quality = 0;
397 texDesc.Usage = D3D11_USAGE_DEFAULT;
398 texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
399 texDesc.CPUAccessFlags = 0;
400 texDesc.MiscFlags = fDirectOutput ? 0 : D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
401
402 HTEST(mRender.pDevice->CreateTexture2D(&texDesc, 0, &mRender.pRenderTarget));
403 HTEST(mRender.pDevice->CreateRenderTargetView(mRender.pRenderTarget, 0, &mRender.pRenderTargetView));
404
405 /* Get the shared handle. */
406 HTEST(mRender.pRenderTarget->QueryInterface(__uuidof(IDXGIResource), (void**)&mRender.pDxgiResource));
407 HTEST(mRender.pDxgiResource->GetSharedHandle(&mSharedHandle));
408
409 HTEST(mRender.pRenderTarget->QueryInterface(__uuidof(IDXGIKeyedMutex), (LPVOID*)&mRender.pDXGIKeyedMutex));
410 }
411
412 if (mpRender->IsDepthStencilBufferRequired(this))
413 {
414 D3D11_TEXTURE2D_DESC depthStencilDesc;
415 depthStencilDesc.Width = mRTWidth;
416 depthStencilDesc.Height = mRTHeight;
417 depthStencilDesc.MipLevels = 1;
418 depthStencilDesc.ArraySize = 1;
419 depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
420 depthStencilDesc.SampleDesc.Count = 1;
421 depthStencilDesc.SampleDesc.Quality = 0;
422 depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
423 depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
424 depthStencilDesc.CPUAccessFlags = 0;
425 depthStencilDesc.MiscFlags = 0;
426
427 HTEST(mRender.pDevice->CreateTexture2D(&depthStencilDesc, 0, &mRender.pDepthStencilBuffer));
428 HTEST(mRender.pDevice->CreateDepthStencilView(mRender.pDepthStencilBuffer, 0, &mRender.pDepthStencilView));
429 }
430 }
431
432 if (mRender.pImmediateContext)
433 {
434 // Set the viewport transform.
435 D3D11_VIEWPORT mScreenViewport;
436 mScreenViewport.TopLeftX = 0;
437 mScreenViewport.TopLeftY = 0;
438 mScreenViewport.Width = static_cast<float>(mRTWidth);
439 mScreenViewport.Height = static_cast<float>(mRTHeight);
440 mScreenViewport.MinDepth = 0.0f;
441 mScreenViewport.MaxDepth = 1.0f;
442
443 mRender.pImmediateContext->RSSetViewports(1, &mScreenViewport);
444 }
445
446 /*
447 * Output.
448 */
449 if (fDirectOutput)
450 {
451 if (mRender.pDxgiFactory)
452 {
453 DXGI_SWAP_CHAIN_DESC sd;
454 RT_ZERO(sd);
455 sd.BufferDesc.Width = mRTWidth;
456 sd.BufferDesc.Height = mRTHeight;
457 sd.BufferDesc.RefreshRate.Numerator = 60;
458 sd.BufferDesc.RefreshRate.Denominator = 1;
459 sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
460 sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
461 sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
462 sd.SampleDesc.Count = 1;
463 sd.SampleDesc.Quality = 0;
464 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
465 sd.BufferCount = 1;
466 sd.OutputWindow = mHwnd;
467 sd.Windowed = true;
468 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
469 sd.Flags = 0;
470
471 HTEST(mRender.pDxgiFactory->CreateSwapChain(mRender.pDevice, &sd, &mOutput.pSwapChain));
472
473 HTEST(mOutput.pSwapChain->ResizeBuffers(1, mRTWidth, mRTHeight, DXGI_FORMAT_B8G8R8A8_UNORM, 0));
474 }
475 }
476 else
477 {
478 d3d11TestCreateDevice(&mOutput.pDevice,
479 &mOutput.pImmediateContext,
480 &mOutput.pDxgiFactory);
481 if (mOutput.pDxgiFactory)
482 {
483 DXGI_SWAP_CHAIN_DESC sd;
484 RT_ZERO(sd);
485 sd.BufferDesc.Width = mRTWidth;
486 sd.BufferDesc.Height = mRTHeight;
487 sd.BufferDesc.RefreshRate.Numerator = 60;
488 sd.BufferDesc.RefreshRate.Denominator = 1;
489 sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
490 sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
491 sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
492 sd.SampleDesc.Count = 1;
493 sd.SampleDesc.Quality = 0;
494 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
495 sd.BufferCount = 1;
496 sd.OutputWindow = mHwnd;
497 sd.Windowed = true;
498 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
499 sd.Flags = 0;
500
501 HTEST(mOutput.pDxgiFactory->CreateSwapChain(mOutput.pDevice, &sd, &mOutput.pSwapChain));
502
503 HTEST(mOutput.pSwapChain->ResizeBuffers(1, mRTWidth, mRTHeight, DXGI_FORMAT_B8G8R8A8_UNORM, 0));
504
505 HTEST(mOutput.pDevice->OpenSharedResource(mSharedHandle, __uuidof(ID3D11Texture2D), (void**)&mOutput.pSharedTexture));
506 HTEST(mOutput.pSharedTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), (LPVOID*)&mOutput.pDXGIKeyedMutex));
507 }
508 }
509
510 return hr;
511}
512
513void D3D11Test::parseCmdLine(int argc, char **argv)
514{
515 /* Very simple: a test identifier followed by the render mode. */
516
517 /* First number is the render id. */
518 if (argc >= 2)
519 miRenderId = RTStrToInt32(argv[1]);
520
521 /* Second number is the render/step mode. */
522 if (argc >= 3)
523 {
524 int i = RTStrToInt32(argv[2]);
525 switch (i)
526 {
527 default:
528 case 0: miRenderMode = RenderModeStep; break;
529 case 1: miRenderMode = RenderModeContinuous; break;
530 case 2: miRenderMode = RenderModeFPS; break;
531 }
532 }
533}
534
535HRESULT D3D11Test::Init(HINSTANCE hInstance, int argc, char **argv, int nCmdShow)
536{
537 parseCmdLine(argc, argv);
538
539 HRESULT hr = initWindow(hInstance, nCmdShow);
540 if (SUCCEEDED(hr))
541 {
542 mpRender = CreateRender(miRenderId);
543 if (mpRender)
544 {
545 hr = initDirect3D11();
546 if (SUCCEEDED(hr))
547 {
548 hr = mpRender->InitRender(this);
549 if (FAILED(hr))
550 {
551 D3DTestShowError(hr, "InitRender");
552 }
553 }
554 }
555 else
556 {
557 D3DTestShowError(0, "No render");
558 hr = E_FAIL;
559 }
560 }
561
562 return hr;
563}
564
565#include "d3d11blitter.hlsl.vs.h"
566#include "d3d11blitter.hlsl.ps.h"
567
568typedef struct D3D11BLITTER
569{
570 ID3D11Device *pDevice;
571 ID3D11DeviceContext *pImmediateContext;
572
573 ID3D11VertexShader *pVertexShader;
574 ID3D11PixelShader *pPixelShader;
575 ID3D11SamplerState *pSamplerState;
576 ID3D11RasterizerState *pRasterizerState;
577 ID3D11BlendState *pBlendState;
578} D3D11BLITTER;
579
580
581static void BlitRelease(D3D11BLITTER *pBlitter)
582{
583 D3D_RELEASE(pBlitter->pVertexShader);
584 D3D_RELEASE(pBlitter->pPixelShader);
585 D3D_RELEASE(pBlitter->pSamplerState);
586 D3D_RELEASE(pBlitter->pRasterizerState);
587 D3D_RELEASE(pBlitter->pBlendState);
588 RT_ZERO(*pBlitter);
589}
590
591
592static HRESULT BlitInit(D3D11BLITTER *pBlitter, ID3D11Device *pDevice, ID3D11DeviceContext *pImmediateContext)
593{
594 HRESULT hr;
595
596 RT_ZERO(*pBlitter);
597
598 pBlitter->pDevice = pDevice;
599 pBlitter->pImmediateContext = pImmediateContext;
600
601 HTEST(pBlitter->pDevice->CreateVertexShader(g_vs_blitter, sizeof(g_vs_blitter), NULL, &pBlitter->pVertexShader));
602 HTEST(pBlitter->pDevice->CreatePixelShader(g_ps_blitter, sizeof(g_ps_blitter), NULL, &pBlitter->pPixelShader));
603
604 D3D11_SAMPLER_DESC SamplerDesc;
605 SamplerDesc.Filter = D3D11_FILTER_ANISOTROPIC;
606 SamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
607 SamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
608 SamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
609 SamplerDesc.MipLODBias = 0.0f;
610 SamplerDesc.MaxAnisotropy = 4;
611 SamplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
612 SamplerDesc.BorderColor[0] = 0.0f;
613 SamplerDesc.BorderColor[1] = 0.0f;
614 SamplerDesc.BorderColor[2] = 0.0f;
615 SamplerDesc.BorderColor[3] = 0.0f;
616 SamplerDesc.MinLOD = 0.0f;
617 SamplerDesc.MaxLOD = 0.0f;
618 HTEST(pBlitter->pDevice->CreateSamplerState(&SamplerDesc, &pBlitter->pSamplerState));
619
620 D3D11_RASTERIZER_DESC RasterizerDesc;
621 RasterizerDesc.FillMode = D3D11_FILL_SOLID;
622 RasterizerDesc.CullMode = D3D11_CULL_NONE;
623 RasterizerDesc.FrontCounterClockwise = FALSE;
624 RasterizerDesc.DepthBias = 0;
625 RasterizerDesc.DepthBiasClamp = 0.0f;
626 RasterizerDesc.SlopeScaledDepthBias = 0.0f;
627 RasterizerDesc.DepthClipEnable = FALSE;
628 RasterizerDesc.ScissorEnable = FALSE;
629 RasterizerDesc.MultisampleEnable = FALSE;
630 RasterizerDesc.AntialiasedLineEnable = FALSE;
631 HTEST(pBlitter->pDevice->CreateRasterizerState(&RasterizerDesc, &pBlitter->pRasterizerState));
632
633 D3D11_BLEND_DESC BlendDesc;
634 BlendDesc.AlphaToCoverageEnable = FALSE;
635 BlendDesc.IndependentBlendEnable = FALSE;
636 for (unsigned i = 0; i < RT_ELEMENTS(BlendDesc.RenderTarget); ++i)
637 {
638 BlendDesc.RenderTarget[i].BlendEnable = FALSE;
639 BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_SRC_COLOR;
640 BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_ZERO;
641 BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
642 BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
643 BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
644 BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
645 BlendDesc.RenderTarget[i].RenderTargetWriteMask = 0xF;
646 }
647 HTEST(pBlitter->pDevice->CreateBlendState(&BlendDesc, &pBlitter->pBlendState));
648
649 return S_OK;
650}
651
652
653static HRESULT BlitFromTexture(D3D11BLITTER *pBlitter, ID3D11RenderTargetView *pDstRenderTargetView,
654 float cDstWidth, float cDstHeight, D3D11_RECT const &rectDst,
655 ID3D11ShaderResourceView *pSrcShaderResourceView)
656{
657 HRESULT hr;
658
659 /*
660 * Save pipeline state.
661 */
662 struct
663 {
664 D3D11_PRIMITIVE_TOPOLOGY Topology;
665 ID3D11InputLayout *pInputLayout;
666 ID3D11Buffer *pConstantBuffer;
667 ID3D11VertexShader *pVertexShader;
668 ID3D11ShaderResourceView *pShaderResourceView;
669 ID3D11PixelShader *pPixelShader;
670 ID3D11SamplerState *pSamplerState;
671 ID3D11RasterizerState *pRasterizerState;
672 ID3D11BlendState *pBlendState;
673 FLOAT BlendFactor[4];
674 UINT SampleMask;
675 ID3D11RenderTargetView *apRenderTargetView[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
676 ID3D11DepthStencilView *pDepthStencilView;
677 UINT NumViewports;
678 D3D11_VIEWPORT aViewport[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
679 } SavedState;
680
681 pBlitter->pImmediateContext->IAGetPrimitiveTopology(&SavedState.Topology);
682 pBlitter->pImmediateContext->IAGetInputLayout(&SavedState.pInputLayout);
683 pBlitter->pImmediateContext->VSGetConstantBuffers(0, 1, &SavedState.pConstantBuffer);
684 pBlitter->pImmediateContext->VSGetShader(&SavedState.pVertexShader, NULL, NULL);
685 pBlitter->pImmediateContext->PSGetShaderResources(0, 1, &SavedState.pShaderResourceView);
686 pBlitter->pImmediateContext->PSGetShader(&SavedState.pPixelShader, NULL, NULL);
687 pBlitter->pImmediateContext->PSGetSamplers(0, 1, &SavedState.pSamplerState);
688 pBlitter->pImmediateContext->RSGetState(&SavedState.pRasterizerState);
689 pBlitter->pImmediateContext->OMGetBlendState(&SavedState.pBlendState, SavedState.BlendFactor, &SavedState.SampleMask);
690 pBlitter->pImmediateContext->OMGetRenderTargets(RT_ELEMENTS(SavedState.apRenderTargetView), SavedState.apRenderTargetView, &SavedState.pDepthStencilView);
691 SavedState.NumViewports = RT_ELEMENTS(SavedState.aViewport);
692 pBlitter->pImmediateContext->RSGetViewports(&SavedState.NumViewports, &SavedState.aViewport[0]);
693
694 /*
695 * Setup pipeline for the blitter.
696 */
697
698 /* Render target is first.
699 * If the source texture is bound as a render target, then this call will unbind it
700 * and allow to use it as the shader resource.
701 */
702 pBlitter->pImmediateContext->OMSetRenderTargets(1, &pDstRenderTargetView, NULL);
703
704 /* Input assembler. */
705 pBlitter->pImmediateContext->IASetInputLayout(NULL);
706 pBlitter->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
707
708 /* Constant buffer. */
709 struct
710 {
711 float scaleX;
712 float scaleY;
713 float offsetX;
714 float offsetY;
715 } VSConstantBuffer;
716 VSConstantBuffer.scaleX = (float)(rectDst.right - rectDst.left) / cDstWidth;
717 VSConstantBuffer.scaleY = (float)(rectDst.bottom - rectDst.top) / cDstHeight;
718 VSConstantBuffer.offsetX = (float)(rectDst.right + rectDst.left) / cDstWidth - 1.0f;
719 VSConstantBuffer.offsetY = -((float)(rectDst.bottom + rectDst.top) / cDstHeight - 1.0f);
720
721 D3D11_SUBRESOURCE_DATA initialData;
722 initialData.pSysMem = &VSConstantBuffer;
723 initialData.SysMemPitch = sizeof(VSConstantBuffer);
724 initialData.SysMemSlicePitch = sizeof(VSConstantBuffer);
725
726 D3D11_BUFFER_DESC bd;
727 RT_ZERO(bd);
728 bd.ByteWidth = sizeof(VSConstantBuffer);
729 bd.Usage = D3D11_USAGE_IMMUTABLE;
730 bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
731
732 ID3D11Buffer *pConstantBuffer;
733 HTEST(pBlitter->pDevice->CreateBuffer(&bd, &initialData, &pConstantBuffer));
734 pBlitter->pImmediateContext->VSSetConstantBuffers(0, 1, &pConstantBuffer);
735 D3D_RELEASE(pConstantBuffer); /* xSSetConstantBuffers "will hold a reference to the interfaces passed in." */
736
737 /* Vertex shader. */
738 pBlitter->pImmediateContext->VSSetShader(pBlitter->pVertexShader, NULL, 0);
739
740 /* Shader resource view. */
741 pBlitter->pImmediateContext->PSSetShaderResources(0, 1, &pSrcShaderResourceView);
742
743 /* Pixel shader. */
744 pBlitter->pImmediateContext->PSSetShader(pBlitter->pPixelShader, NULL, 0);
745
746 /* Sampler. */
747 pBlitter->pImmediateContext->PSSetSamplers(0, 1, &pBlitter->pSamplerState);
748
749 /* Rasterizer. */
750 pBlitter->pImmediateContext->RSSetState(pBlitter->pRasterizerState);
751
752 /* Blend state. */
753 static FLOAT const BlendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
754 pBlitter->pImmediateContext->OMSetBlendState(pBlitter->pBlendState, BlendFactor, 0xffffffff);
755
756 /* Viewport. */
757 D3D11_VIEWPORT Viewport;
758 Viewport.TopLeftX = 0;
759 Viewport.TopLeftY = 0;
760 Viewport.Width = cDstWidth;
761 Viewport.Height = cDstHeight;
762 Viewport.MinDepth = 0.0f;
763 Viewport.MaxDepth = 1.0f;
764 pBlitter->pImmediateContext->RSSetViewports(1, &Viewport);
765
766 /* Draw. */
767 pBlitter->pImmediateContext->Draw(4, 0);
768
769 /*
770 * Restore pipeline state.
771 */
772 pBlitter->pImmediateContext->IASetPrimitiveTopology(SavedState.Topology);
773 pBlitter->pImmediateContext->IASetInputLayout(SavedState.pInputLayout);
774 D3D_RELEASE(SavedState.pInputLayout);
775 pBlitter->pImmediateContext->VSSetConstantBuffers(0, 1, &SavedState.pConstantBuffer);
776 D3D_RELEASE(SavedState.pConstantBuffer);
777 pBlitter->pImmediateContext->VSSetShader(SavedState.pVertexShader, NULL, 0);
778 D3D_RELEASE(SavedState.pVertexShader);
779 pBlitter->pImmediateContext->PSSetShaderResources(0, 1, &SavedState.pShaderResourceView);
780 D3D_RELEASE(SavedState.pShaderResourceView);
781 pBlitter->pImmediateContext->PSSetShader(SavedState.pPixelShader, NULL, 0);
782 D3D_RELEASE(SavedState.pPixelShader);
783 pBlitter->pImmediateContext->PSSetSamplers(0, 1, &SavedState.pSamplerState);
784 D3D_RELEASE(SavedState.pSamplerState);
785 pBlitter->pImmediateContext->RSSetState(SavedState.pRasterizerState);
786 D3D_RELEASE(SavedState.pRasterizerState);
787 pBlitter->pImmediateContext->OMSetBlendState(SavedState.pBlendState, SavedState.BlendFactor, SavedState.SampleMask);
788 D3D_RELEASE(SavedState.pBlendState);
789 pBlitter->pImmediateContext->OMSetRenderTargets(RT_ELEMENTS(SavedState.apRenderTargetView), SavedState.apRenderTargetView, SavedState.pDepthStencilView);
790 D3D_RELEASE_ARRAY(RT_ELEMENTS(SavedState.apRenderTargetView), SavedState.apRenderTargetView);
791 D3D_RELEASE(SavedState.pDepthStencilView);
792 pBlitter->pImmediateContext->RSSetViewports(SavedState.NumViewports, &SavedState.aViewport[0]);
793
794 return S_OK;
795}
796
797
798int D3D11Test::Run()
799{
800 HRESULT hr = S_OK;
801
802 bool fFirst = true;
803 MSG msg;
804
805 LARGE_INTEGER PerfFreq;
806 QueryPerformanceFrequency(&PerfFreq);
807 float const PerfPeriod = 1.0f / (float)PerfFreq.QuadPart; /* Period in seconds. */
808
809 LARGE_INTEGER PrevTS;
810 QueryPerformanceCounter(&PrevTS);
811
812 int cFrames = 0;
813 float elapsed = 0;
814
815 bool const fDirectOutput = mpRender->IsDirectOutputRequired(this);
816
817 D3D11BLITTER Blitter;
818 if (fDirectOutput)
819 RT_ZERO(Blitter);
820 else
821 BlitInit(&Blitter, mOutput.pDevice, mOutput.pImmediateContext);
822
823 do
824 {
825 BOOL fGotMessage;
826 if (miRenderMode == RenderModeStep)
827 {
828 fGotMessage = GetMessageA(&msg, 0, 0, 0);
829 }
830 else
831 {
832 fGotMessage = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
833 }
834
835 if (fGotMessage)
836 {
837 TranslateMessage(&msg);
838 DispatchMessageA(&msg);
839 }
840
841 BOOL fDoRender = FALSE;
842 if (miRenderMode == RenderModeStep)
843 {
844 if (msg.message == WM_CHAR)
845 {
846 if (msg.wParam == ' ')
847 {
848 fDoRender = TRUE;
849 }
850 }
851 }
852 else
853 {
854 fDoRender = TRUE;
855 }
856
857 if (fDoRender)
858 {
859 LARGE_INTEGER CurrTS;
860 QueryPerformanceCounter(&CurrTS);
861
862 /* Time in seconds since the previous render step. */
863 float dt = fFirst ? 0.0f : (float)(CurrTS.QuadPart - PrevTS.QuadPart) * PerfPeriod;
864 if (mpRender)
865 {
866 /*
867 * Render the scene.
868 */
869 mpRender->TimeAdvance(dt);
870
871 if (fDirectOutput)
872 {
873 ID3D11Texture2D *pBackBuffer = NULL;
874 HTEST(mOutput.pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer)));
875 if (pBackBuffer)
876 {
877 ID3D11RenderTargetView *pRenderTargetView = 0;
878 HTEST(mRender.pDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTargetView));
879
880 mRender.pImmediateContext->OMSetRenderTargets(1, &pRenderTargetView, mRender.pDepthStencilView);
881
882 mRender.pRenderTargetView = pRenderTargetView;
883 mpRender->DoRender(this);
884 mRender.pRenderTargetView = NULL;
885
886 D3D_RELEASE(pRenderTargetView);
887 D3D_RELEASE(pBackBuffer);
888 }
889 else
890 D3DTestShowError(hr, "pSwapChain->GetBuffer (DirectOutput)");
891 }
892 else
893 {
894 DWORD result = mRender.pDXGIKeyedMutex->AcquireSync(0, 1000);
895 if (result == WAIT_OBJECT_0)
896 {
897 /*
898 * Use the shared texture from the render device.
899 */
900 mRender.pImmediateContext->OMSetRenderTargets(1, &mRender.pRenderTargetView, mRender.pDepthStencilView);
901 mpRender->DoRender(this);
902 }
903 else
904 D3DTestShowError(hr, "Render.AcquireSync(0)");
905 result = mRender.pDXGIKeyedMutex->ReleaseSync(1);
906 if (result == WAIT_OBJECT_0)
907 { }
908 else
909 D3DTestShowError(hr, "Render.ReleaseSync(1)");
910
911 /*
912 * Copy the rendered scene to the backbuffer and present.
913 */
914 ID3D11Texture2D *pBackBuffer = NULL;
915 HTEST(mOutput.pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer)));
916 if (pBackBuffer)
917 {
918 result = mOutput.pDXGIKeyedMutex->AcquireSync(1, 1000);
919 if (result == WAIT_OBJECT_0)
920 {
921 /*
922 * Use the shared texture from the output device.
923 */
924 float cDstWidth = static_cast<float>(mRTWidth);
925 float cDstHeight = static_cast<float>(mRTHeight);
926
927 D3D11_RECT rectDst;
928 rectDst.left = 0;
929 rectDst.top = 0;
930 rectDst.right = mRTWidth;
931 rectDst.bottom = mRTHeight;
932
933 ID3D11ShaderResourceView *pShaderResourceView = 0;
934 HTEST(Blitter.pDevice->CreateShaderResourceView(mOutput.pSharedTexture, NULL, &pShaderResourceView));
935
936 ID3D11RenderTargetView *pRenderTargetView = 0;
937 HTEST(Blitter.pDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTargetView));
938
939 BlitFromTexture(&Blitter, pRenderTargetView, cDstWidth, cDstHeight, rectDst, pShaderResourceView);
940
941 D3D_RELEASE(pRenderTargetView);
942 D3D_RELEASE(pShaderResourceView);
943 }
944 else
945 D3DTestShowError(hr, "Output.AcquireSync(1)");
946 result = mOutput.pDXGIKeyedMutex->ReleaseSync(0);
947 if (result == WAIT_OBJECT_0)
948 { }
949 else
950 D3DTestShowError(hr, "Output.ReleaseSync(0)");
951
952 D3D_RELEASE(pBackBuffer);
953 }
954 }
955
956 HTEST(mOutput.pSwapChain->Present(0, 0));
957
958 fFirst = false;
959 }
960
961 if (miRenderMode == RenderModeFPS)
962 {
963 ++cFrames;
964 elapsed += dt;
965 if (elapsed > 1.0f)
966 {
967 float msPerFrame = elapsed * 1000.0f / (float)cFrames;
968 char sz[256];
969 RTStrPrintf(sz, sizeof(sz), "D3D11 Test FPS %d Frame Time %u.%03ums",
970 cFrames, (unsigned)msPerFrame, (unsigned)(msPerFrame * 1000) % 1000);
971 SetWindowTextA(mHwnd, sz);
972
973 cFrames = 0;
974 elapsed = 0.0f;
975 }
976 }
977
978 PrevTS = CurrTS;
979 }
980 } while (msg.message != WM_QUIT);
981
982 BlitRelease(&Blitter);
983 return msg.wParam;
984}
985
986ID3D11Device *D3D11Test::Device()
987{
988 return mRender.pDevice;
989}
990
991ID3D11DeviceContext *D3D11Test::ImmediateContext()
992{
993 return mRender.pImmediateContext;
994}
995
996ID3D11RenderTargetView *D3D11Test::RenderTargetView()
997{
998 return mRender.pRenderTargetView;
999}
1000
1001ID3D11DepthStencilView *D3D11Test::DepthStencilView()
1002{
1003 return mRender.pDepthStencilView;
1004}
1005
1006int main(int argc, char **argv)
1007{
1008 int rcExit = RTEXITCODE_FAILURE;
1009
1010 D3D11Test test;
1011 HRESULT hr = test.Init(GetModuleHandleW(NULL), argc, argv, SW_SHOWDEFAULT);
1012 if (SUCCEEDED(hr))
1013 rcExit = test.Run();
1014
1015 return rcExit;
1016}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use