之所以说是常规加速版,是因为DX11还有GPGPU计算加速功能Compute Shader,也就是所谓的DirectCompute,但是这里我们只用到了常规的图形流水线加速功能。
最低配置被设置为D3D_FEATURE_LEVEL_9_3和"ps_4_0_level_9_3"。如果将循环次数改多一点,由于"ps_4_0_level_9_3"不包含条件循环指令,循环操作实际上被展开了,指令数量很容易超过限制,这个时候就需要把最低配置改为D3D_FEATURE_LEVEL_10_0和"ps_4_0"。
<code class="language-hlsl">// shaders.txt struct VS_OUTPUT { float4 pos : SV_POSITION; float2 tex : TEXCOORD; }; void vs_common(float3 pos : POSITION, float2 tex : TEXCOORD, out VS_OUTPUT vso) { vso.pos = float4(pos, 1.0f); vso.tex = tex; } float4 ps_mandelbrot(VS_OUTPUT vso) : SV_TARGET { float2 zvar = float2(0, 0); float i; for (i = 0; i < 16 && zvar.x * zvar.x + zvar.y * zvar.y <= 16 4; i++) { float2 zvar2="zvar;" zvar.x="zvar2.x" * zvar2.x - zvar2.y + vso.tex.x; zvar.y="zvar2.x" vso.tex.y; } return float4(i 16.0, 0.0f, 1.0f); float4 ps_julia(vs_output vso) : sv_target zvar="vso.tex;" float i; for (i="0;" i < && 0.4f; 0.3f; code></=></code>
<code class="language-c">// main.c - 使用了C99语法,可使用VS2013-2017编译 #undef UNICODE #define UNICODE 1 #include <windows.h> #include <assert.h> #include <d3d11.h> #include <d3dcompiler.h> #pragma comment(lib, "d3d11.lib") #pragma comment(lib, "dxguid.lib") #pragma comment(lib, "d3dcompiler.lib") #define NOFAIL(x) assert(SUCCEEDED(x)) #define NOTZERO(x) assert(x) #define CLEANUP(x) if (x) { (x)->lpVtbl->Release(x); (x) = NULL; } HINSTANCE g_hinst; HWND g_hmainwnd; // DirectX D3D_FEATURE_LEVEL g_fl; ID3D11Device *g_dev; ID3D11DeviceContext *g_immctx; IDXGISwapChain *g_swpch; ID3D11Texture2D *g_backbuffer; ID3D11RenderTargetView *g_backbuffer_rtv; // DirectX资源 ID3D11VertexShader *g_vs_common; ID3D11PixelShader *g_ps_mandelbrot; ID3D11PixelShader *g_ps_julia; ID3D11PixelShader *g_ps_current; ID3D11InputLayout *g_inlayout; ID3D11Buffer *g_vertexbuffer; LRESULT MainWnd_OnCreate(HWND hWnd, LPCREATESTRUCT lpcs) { // 创建DirectX RECT rc; GetClientRect(hWnd, &rc); DXGI_MODE_DESC backbuf_mode_desc = { rc.right - rc.left, rc.bottom - rc.top, { 60, 1 }, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_MODE_SCALING_UNSPECIFIED, DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED, }; DXGI_SWAP_CHAIN_DESC swpch_desc = { backbuf_mode_desc, { 1, 0 }, DXGI_USAGE_RENDER_TARGET_OUTPUT, 1, hWnd, TRUE, DXGI_SWAP_EFFECT_DISCARD, 0, }; D3D_FEATURE_LEVEL fllist[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, }; if (FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, fllist, sizeof fllist / sizeof fllist[0], D3D11_SDK_VERSION, &swpch_desc, &g_swpch, &g_dev, &g_fl, &g_immctx))) { NOFAIL(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0, fllist, sizeof fllist / sizeof fllist[0], D3D11_SDK_VERSION, &swpch_desc, &g_swpch, &g_dev, &g_fl, &g_immctx)); } IDXGIFactory *dxgifac; NOFAIL(g_swpch->lpVtbl->GetParent(g_swpch, &IID_IDXGIFactory, (void**)&dxgifac)); NOFAIL(dxgifac->lpVtbl->MakeWindowAssociation(dxgifac, hWnd, DXGI_MWA_NO_ALT_ENTER)); CLEANUP(dxgifac); NOFAIL(g_swpch->lpVtbl->GetBuffer(g_swpch, 0, &IID_ID3D11Texture2D, (void**)&g_backbuffer)); NOFAIL(g_dev->lpVtbl->CreateRenderTargetView(g_dev, (ID3D11Resource *)g_backbuffer, NULL, &g_backbuffer_rtv)); // 创建绘制资源 // 读取shaders.txt static char shaders_txt[65536]; memset(shaders_txt, 0, sizeof shaders_txt); HANDLE hfile = CreateFile(L"shaders.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (hfile == INVALID_HANDLE_VALUE) { MessageBox(hWnd, L"不能打开shader.txt文件", L"文件错误", MB_OK); DestroyWindow(hWnd); return 0; } DWORD dwret; ReadFile(hfile, shaders_txt, sizeof shaders_txt - 1, &dwret, NULL); CloseHandle(hfile); // 编译shaders.txt并创建相关资源 ID3DBlob *bcode_ps_mandelbrot, *bcode_ps_julia, *bcode_vs_common, *errmsg; if (FAILED(D3DCompile(shaders_txt, strlen(shaders_txt), "shaders.txt", NULL, NULL, "ps_mandelbrot", "ps_4_0_level_9_3", 0, 0, &bcode_ps_mandelbrot, &errmsg)) || FAILED(D3DCompile(shaders_txt, strlen(shaders_txt), "shaders.txt", NULL, NULL, "ps_julia", "ps_4_0_level_9_3", 0, 0, &bcode_ps_julia, &errmsg)) || FAILED(D3DCompile(shaders_txt, strlen(shaders_txt), "shaders.txt", NULL, NULL, "vs_common", "vs_4_0_level_9_3", 0, 0, &bcode_vs_common, &errmsg))) { NOTZERO(errmsg); MessageBoxA(hWnd, errmsg->lpVtbl->GetBufferPointer(errmsg), "D3DCompile Error", MB_OK); CLEANUP(errmsg); CLEANUP(bcode_ps_mandelbrot); CLEANUP(bcode_ps_julia); CLEANUP(bcode_vs_common); DestroyWindow(hWnd); return 0; } NOFAIL(g_dev->lpVtbl->CreatePixelShader(g_dev, bcode_ps_mandelbrot->lpVtbl->GetBufferPointer(bcode_ps_mandelbrot), bcode_ps_mandelbrot->lpVtbl->GetBufferSize(bcode_ps_mandelbrot), NULL, &g_ps_mandelbrot)); NOFAIL(g_dev->lpVtbl->CreatePixelShader(g_dev, bcode_ps_julia->lpVtbl->GetBufferPointer(bcode_ps_julia), bcode_ps_julia->lpVtbl->GetBufferSize(bcode_ps_julia), NULL, &g_ps_julia)); NOFAIL(g_dev->lpVtbl->CreateVertexShader(g_dev, bcode_vs_common->lpVtbl->GetBufferPointer(bcode_vs_common), bcode_vs_common->lpVtbl->GetBufferSize(bcode_vs_common), NULL, &g_vs_common)); D3D11_INPUT_ELEMENT_DESC inputelements[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; NOFAIL(g_dev->lpVtbl->CreateInputLayout(g_dev, inputelements, sizeof inputelements / sizeof inputelements[0], bcode_vs_common->lpVtbl->GetBufferPointer(bcode_vs_common), bcode_vs_common->lpVtbl->GetBufferSize(bcode_vs_common), &g_inlayout)); CLEANUP(bcode_ps_mandelbrot); CLEANUP(bcode_ps_julia); CLEANUP(bcode_vs_common); float vertexdata[] = { -1.0f, -1.0f, 1.0f, -2.2f, -2.2f, -1.0f, 1.0f, 1.0f, -2.2f, 2.2f, 1.0f, -1.0f, 1.0f, 2.2f, -2.2f, 1.0f, 1.0f, 1.0f, 2.2f, 2.2f, }; D3D11_BUFFER_DESC bd = { sizeof vertexdata, D3D11_USAGE_DEFAULT, 0, 0, 0 }; D3D11_SUBRESOURCE_DATA srd = { vertexdata, 0, 0 }; NOFAIL(g_dev->lpVtbl->CreateBuffer(g_dev, &bd, &srd, &g_vertexbuffer)); g_ps_current = g_ps_mandelbrot; return 0; } LRESULT MainWnd_OnDestroy(HWND hWnd) { if (g_immctx) g_immctx->lpVtbl->ClearState(g_immctx); // 清理资源 CLEANUP(g_vertexbuffer); CLEANUP(g_inlayout); CLEANUP(g_vs_common); CLEANUP(g_ps_julia); CLEANUP(g_ps_mandelbrot); // 清理DirectX CLEANUP(g_backbuffer_rtv); CLEANUP(g_backbuffer); CLEANUP(g_swpch); CLEANUP(g_immctx); CLEANUP(g_dev); // 产生WM_QUIT消息,结束消息循环 PostQuitMessage(0); return 0; } LRESULT MainWnd_OnSize(HWND hWnd, WPARAM wParam, POINTS pts) { if (g_swpch && g_immctx && g_dev) { g_immctx->lpVtbl->ClearState(g_immctx); CLEANUP(g_backbuffer_rtv); CLEANUP(g_backbuffer); RECT rc; GetClientRect(hWnd, &rc); NOFAIL(g_swpch->lpVtbl->ResizeBuffers(g_swpch, 1, rc.right - rc.left, rc.bottom - rc.top, DXGI_FORMAT_UNKNOWN, 0)); NOFAIL(g_swpch->lpVtbl->GetBuffer(g_swpch, 0, &IID_ID3D11Texture2D, (void**)&g_backbuffer)); NOFAIL(g_dev->lpVtbl->CreateRenderTargetView(g_dev, g_backbuffer, NULL, &g_backbuffer_rtv)); } return 0; } LRESULT MainWnd_OnPaint(HWND hWnd) { // GDI例行任务 PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); // DirectX任务 // 清除背景 float backcolor[] = { 0.0f, 1.0f, 1.0f, 1.0f }; g_immctx->lpVtbl->ClearRenderTargetView(g_immctx, g_backbuffer_rtv, backcolor); // 设置状态并绘图 RECT rc; GetClientRect(hWnd, &rc); float ratio = (float)(rc.right - rc.left) / (float)(rc.bottom - rc.top); float vertexdata[] = { -1.0f, -1.0f, 1.0f, -2.2f * ratio, -2.2f, -1.0f, 1.0f, 1.0f, -2.2f * ratio, 2.2f, 1.0f, -1.0f, 1.0f, 2.2f * ratio, -2.2f, 1.0f, 1.0f, 1.0f, 2.2f * ratio, 2.2f, }; g_immctx->lpVtbl->UpdateSubresource(g_immctx, (ID3D11Resource *)g_vertexbuffer, 0, NULL, vertexdata, 0, 0); UINT stride = sizeof(float) * 5, offset = 0; g_immctx->lpVtbl->IASetVertexBuffers(g_immctx, 0, 1, &g_vertexbuffer, &stride, &offset); g_immctx->lpVtbl->IASetInputLayout(g_immctx, g_inlayout); g_immctx->lpVtbl->IASetPrimitiveTopology(g_immctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); g_immctx->lpVtbl->VSSetShader(g_immctx, g_vs_common, NULL, 0); D3D11_VIEWPORT viewport = { 0.0f, 0.0f, rc.right - rc.left, rc.bottom - rc.top, 0.0f, 1.0f }; g_immctx->lpVtbl->RSSetViewports(g_immctx, 1, &viewport); g_immctx->lpVtbl->PSSetShader(g_immctx, g_ps_current, NULL, 0); g_immctx->lpVtbl->OMSetRenderTargets(g_immctx, 1, &g_backbuffer_rtv, NULL); g_immctx->lpVtbl->Draw(g_immctx, 4, 0); // 上屏 NOFAIL(g_swpch->lpVtbl->Present(g_swpch, 0, 0)); return 0; } LRESULT MainWnd_OnLButtonDown(HWND hWnd, WPARAM wParam, POINTS pts) { g_ps_current = g_ps_mandelbrot; InvalidateRect(hWnd, NULL, FALSE); return 0; } LRESULT MainWnd_OnRButtonDown(HWND hWnd, WPARAM wParam, POINTS pts) { g_ps_current = g_ps_julia; InvalidateRect(hWnd, NULL, FALSE); return 0; } LRESULT __stdcall WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: return MainWnd_OnCreate(hWnd, (LPCREATESTRUCT)lParam); case WM_DESTROY: return MainWnd_OnDestroy(hWnd); case WM_SIZE: return MainWnd_OnSize(hWnd, wParam, MAKEPOINTS(lParam)); case WM_LBUTTONDOWN: return MainWnd_OnLButtonDown(hWnd, wParam, MAKEPOINTS(lParam)); case WM_RBUTTONDOWN: return MainWnd_OnRButtonDown(hWnd, wParam, MAKEPOINTS(lParam)); case WM_PAINT: return MainWnd_OnPaint(hWnd); default: return DefWindowProc(hWnd, msg, wParam, lParam); } } int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR szCmdLine, int nShowCmd) { WNDCLASSEX wcex = { sizeof wcex, CS_VREDRAW|CS_HREDRAW, WndProc, 0, 0, g_hinst = hInstance, LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW), NULL/*空画刷防闪烁*/, NULL, L"MainWndClass", LoadIcon(NULL, IDI_APPLICATION) }; RegisterClassEx(&wcex); RECT rc = { 0, 0, 480, 480 }; AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0); g_hmainwnd = CreateWindowEx(0, wcex.lpszClassName, L"D3D11主窗口", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL); ShowWindow(g_hmainwnd, nShowCmd); UpdateWindow(g_hmainwnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } </d3dcompiler.h></d3d11.h></assert.h></windows.h></code>
[修改于 7年3个月前 - 2017/09/18 03:29:12]
时段 | 个数 |
---|---|
{{f.startingTime}}点 - {{f.endTime}}点 | {{f.fileCount}} |