之所以说是常规加速版,是因为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"。
Other// 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></=>
Other// 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>
[修改于 7年4个月前 - 2017/09/18 03:29:12]