dx11test

annotate main.cc @ 0:647ba0689512

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 21 Jun 2013 07:33:06 +0300
parents
children
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <stdlib.h>
nuclear@0 3 #include <math.h>
nuclear@0 4 #include <stddef.h>
nuclear@0 5 #include <d3d11.h>
nuclear@0 6 #include <d3dx11.h>
nuclear@0 7 #include "vec.h"
nuclear@0 8
nuclear@0 9 struct Vertex {
nuclear@0 10 float pos[3];
nuclear@0 11 float color[4];
nuclear@0 12 };
nuclear@0 13
nuclear@0 14 struct RenderState {
nuclear@0 15 float modelview[16];
nuclear@0 16 float projection[16];
nuclear@0 17 };
nuclear@0 18
nuclear@0 19 static bool init();
nuclear@0 20 static void cleanup();
nuclear@0 21 static void display();
nuclear@0 22 static void reshape(int x, int y);
nuclear@0 23 static void keyb(int key, bool pressed);
nuclear@0 24 static HWND create_window(int xsz, int ysz);
nuclear@0 25 static void destroy_window(HWND win);
nuclear@0 26 static void main_loop();
nuclear@0 27 static long CALLBACK win_proc(HWND win, unsigned int msg, unsigned int wparam, long lparam);
nuclear@0 28
nuclear@0 29 static int width, height;
nuclear@0 30
nuclear@0 31 static HWND win;
nuclear@0 32 static IDXGISwapChain *swap;
nuclear@0 33 static ID3D11Device *dev;
nuclear@0 34 static ID3D11DeviceContext *ctx;
nuclear@0 35 static ID3D11RenderTargetView *rtarg_view;
nuclear@0 36 static ID3D11InputLayout *vertex_layout;
nuclear@0 37 static ID3D11VertexShader *vsdr;
nuclear@0 38 static ID3D11PixelShader *psdr;
nuclear@0 39 static ID3D11Buffer *vbuf;
nuclear@0 40 static ID3D11Buffer *rstate_buf;
nuclear@0 41
nuclear@0 42 static RenderState rstate;
nuclear@0 43
nuclear@0 44 int main()
nuclear@0 45 {
nuclear@0 46 if(!init()) {
nuclear@0 47 return 1;
nuclear@0 48 }
nuclear@0 49 atexit(cleanup);
nuclear@0 50
nuclear@0 51 main_loop();
nuclear@0 52 return 0;
nuclear@0 53 }
nuclear@0 54
nuclear@0 55 static bool init()
nuclear@0 56 {
nuclear@0 57 if(!(win = create_window(800, 600))) {
nuclear@0 58 return false;
nuclear@0 59 }
nuclear@0 60
nuclear@0 61 unsigned int sdrflags = 0;//D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_DEBUG;
nuclear@0 62
nuclear@0 63 ID3DBlob *vsbuf, *psbuf, *msgblob;
nuclear@0 64 if(D3DX11CompileFromFile("shader.hlsl", 0, 0, "vertex_main", "vs_4_0", sdrflags, 0, 0, &vsbuf, &msgblob, 0) != 0) {
nuclear@0 65 fprintf(stderr, "failed to load vertex shader\n");
nuclear@0 66 if(msgblob->GetBufferSize() > 0) {
nuclear@0 67 fprintf(stderr, "Vertex Shader:\n%s\n", (char*)msgblob->GetBufferPointer());
nuclear@0 68 }
nuclear@0 69 return false;
nuclear@0 70 }
nuclear@0 71 if(D3DX11CompileFromFile("shader.hlsl", 0, 0, "pixel_main", "ps_4_0", sdrflags, 0, 0, &psbuf, &msgblob, 0) != 0) {
nuclear@0 72 fprintf(stderr, "failed to load pixel shader\n");
nuclear@0 73 if(msgblob->GetBufferSize() > 0) {
nuclear@0 74 fprintf(stderr, "Pixel Shader:\n%s\n", (char*)msgblob->GetBufferPointer());
nuclear@0 75 }
nuclear@0 76 return false;
nuclear@0 77 }
nuclear@0 78
nuclear@0 79 if(dev->CreateVertexShader(vsbuf->GetBufferPointer(), vsbuf->GetBufferSize(), 0, &vsdr) != 0) {
nuclear@0 80 fprintf(stderr, "failed to create vertex shader\n");
nuclear@0 81 return false;
nuclear@0 82 }
nuclear@0 83 if(dev->CreatePixelShader(psbuf->GetBufferPointer(), psbuf->GetBufferSize(), 0, &psdr) != 0) {
nuclear@0 84 fprintf(stderr, "failed to create pixel shader\n");
nuclear@0 85 return false;
nuclear@0 86 }
nuclear@0 87
nuclear@0 88 D3D11_INPUT_ELEMENT_DESC elem_desc[2];
nuclear@0 89 elem_desc[0].SemanticName = "position";
nuclear@0 90 elem_desc[0].SemanticIndex = 0;
nuclear@0 91 elem_desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
nuclear@0 92 elem_desc[0].InputSlot = 0;
nuclear@0 93 elem_desc[0].AlignedByteOffset = 0;
nuclear@0 94 elem_desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
nuclear@0 95 elem_desc[0].InstanceDataStepRate = 0;
nuclear@0 96
nuclear@0 97 elem_desc[1].SemanticName = "color";
nuclear@0 98 elem_desc[1].SemanticIndex = 0;
nuclear@0 99 elem_desc[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
nuclear@0 100 elem_desc[1].InputSlot = 0;
nuclear@0 101 elem_desc[1].AlignedByteOffset = offsetof(Vertex, color);
nuclear@0 102 elem_desc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
nuclear@0 103 elem_desc[1].InstanceDataStepRate = 0;
nuclear@0 104
nuclear@0 105 if(dev->CreateInputLayout(elem_desc, 2, vsbuf->GetBufferPointer(), vsbuf->GetBufferSize(), &vertex_layout) != 0) {
nuclear@0 106 fprintf(stderr, "failed to create vertex layout\n");
nuclear@0 107 return 0;
nuclear@0 108 }
nuclear@0 109 vsbuf->Release();
nuclear@0 110 psbuf->Release();
nuclear@0 111
nuclear@0 112 // --- create vertex buffer ---
nuclear@0 113 Vertex varr[] = {
nuclear@0 114 {{-0.6, -0.4, 0}, {1, 0, 0, 1}},
nuclear@0 115 {{0.0, 0.6, 0}, {0, 1, 0, 1}},
nuclear@0 116 {{0.6, -0.4, 0}, {0, 0, 1, 1}}
nuclear@0 117 };
nuclear@0 118
nuclear@0 119 D3D11_BUFFER_DESC buf_desc;
nuclear@0 120 memset(&buf_desc, 0, sizeof buf_desc);
nuclear@0 121 buf_desc.Usage = D3D11_USAGE_DEFAULT;
nuclear@0 122 buf_desc.ByteWidth = sizeof varr;
nuclear@0 123 buf_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
nuclear@0 124
nuclear@0 125 D3D11_SUBRESOURCE_DATA subdata;
nuclear@0 126 memset(&subdata, 0, sizeof subdata);
nuclear@0 127 subdata.pSysMem = varr;
nuclear@0 128 if(dev->CreateBuffer(&buf_desc, &subdata, &vbuf) != 0) {
nuclear@0 129 fprintf(stderr, "failed to create vertex buffer\n");
nuclear@0 130 return false;
nuclear@0 131 }
nuclear@0 132
nuclear@0 133 // render state buffer
nuclear@0 134 memset(&buf_desc, 0, sizeof buf_desc);
nuclear@0 135 buf_desc.Usage = D3D11_USAGE_DEFAULT;
nuclear@0 136 buf_desc.ByteWidth = sizeof(RenderState);
nuclear@0 137 buf_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
nuclear@0 138
nuclear@0 139 memset(&subdata, 0, sizeof subdata);
nuclear@0 140 subdata.pSysMem = &rstate;
nuclear@0 141 if(dev->CreateBuffer(&buf_desc, &subdata, &rstate_buf) != 0) {
nuclear@0 142 fprintf(stderr, "failed to create render state buffer\n");
nuclear@0 143 return false;
nuclear@0 144 }
nuclear@0 145
nuclear@0 146 return true;
nuclear@0 147 }
nuclear@0 148
nuclear@0 149 static void cleanup()
nuclear@0 150 {
nuclear@0 151 vbuf->Release();
nuclear@0 152 rstate_buf->Release();
nuclear@0 153 vsdr->Release();
nuclear@0 154 psdr->Release();
nuclear@0 155 vertex_layout->Release();
nuclear@0 156 destroy_window(win);
nuclear@0 157 }
nuclear@0 158
nuclear@0 159 static void set_identity(float *mat)
nuclear@0 160 {
nuclear@0 161 mat[0] = mat[5] = mat[10] = mat[15] = 1.0;
nuclear@0 162 mat[1] = mat[2] = mat[3] = mat[4] = mat[6] = mat[7] = mat[8] = mat[9] = mat[11] = mat[12] = mat[13] = mat[14] = 0.0;
nuclear@0 163 }
nuclear@0 164
nuclear@0 165 static void set_rotation_z(float *mat, float angle)
nuclear@0 166 {
nuclear@0 167 set_identity(mat);
nuclear@0 168
nuclear@0 169 mat[0] = cos(angle);
nuclear@0 170 mat[1] = -sin(angle);
nuclear@0 171 mat[4] = sin(angle);
nuclear@0 172 mat[5] = cos(angle);
nuclear@0 173 }
nuclear@0 174
nuclear@0 175 static void set_ortho(float *mat, float aspect)
nuclear@0 176 {
nuclear@0 177 set_identity(mat);
nuclear@0 178 mat[0] = 1.0 / aspect;
nuclear@0 179 }
nuclear@0 180
nuclear@0 181 static void display()
nuclear@0 182 {
nuclear@0 183 unsigned int msec = timeGetTime();
nuclear@0 184
nuclear@0 185 float fbcolor[] = {0.2f, 0.2f, 0.2f, 1.0f};
nuclear@0 186 ctx->ClearRenderTargetView(rtarg_view, fbcolor);
nuclear@0 187
nuclear@0 188 // set render state constant buffer data
nuclear@0 189 set_ortho(rstate.projection, (float)width / (float)height);
nuclear@0 190 set_rotation_z(rstate.modelview, msec / 1000.0);
nuclear@0 191
nuclear@0 192 ctx->UpdateSubresource(rstate_buf, 0, 0, &rstate, 0, 0);
nuclear@0 193 ctx->VSSetConstantBuffers(0, 1, &rstate_buf);
nuclear@0 194
nuclear@0 195
nuclear@0 196 unsigned int stride = sizeof(Vertex);
nuclear@0 197 unsigned int offset = 0;
nuclear@0 198 ctx->IASetVertexBuffers(0, 1, &vbuf, &stride, &offset);
nuclear@0 199 ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
nuclear@0 200 ctx->IASetInputLayout(vertex_layout);
nuclear@0 201
nuclear@0 202 ctx->VSSetShader(vsdr, 0, 0);
nuclear@0 203 ctx->PSSetShader(psdr, 0, 0);
nuclear@0 204
nuclear@0 205 ctx->Draw(3, 0);
nuclear@0 206
nuclear@0 207 swap->Present(0, 0);
nuclear@0 208 }
nuclear@0 209
nuclear@0 210 static void reshape(int x, int y)
nuclear@0 211 {
nuclear@0 212 width = x;
nuclear@0 213 height = y;
nuclear@0 214
nuclear@0 215 D3D11_VIEWPORT vp;
nuclear@0 216 vp.Width = (float)x;
nuclear@0 217 vp.Height = (float)y;
nuclear@0 218 vp.MinDepth = 0;
nuclear@0 219 vp.MaxDepth = 1;
nuclear@0 220 vp.TopLeftX = 0;
nuclear@0 221 vp.TopLeftY = 0;
nuclear@0 222 ctx->RSSetViewports(1, &vp);
nuclear@0 223
nuclear@0 224 // TODO probably we also need to resize render targets or whatever...
nuclear@0 225 }
nuclear@0 226
nuclear@0 227 static void keyb(int key, bool pressed)
nuclear@0 228 {
nuclear@0 229 if(key == 27) {
nuclear@0 230 exit(0);
nuclear@0 231 }
nuclear@0 232 }
nuclear@0 233
nuclear@0 234 // ---- system crap ----
nuclear@0 235
nuclear@0 236 static HWND create_window(int xsz, int ysz)
nuclear@0 237 {
nuclear@0 238 HINSTANCE app_inst = GetModuleHandle(0);
nuclear@0 239
nuclear@0 240 WNDCLASS wclass;
nuclear@0 241 memset(&wclass, 0, sizeof wclass);
nuclear@0 242 wclass.hInstance = app_inst;
nuclear@0 243 wclass.lpfnWndProc = win_proc;
nuclear@0 244 wclass.lpszClassName = "mutantstargoatwin";
nuclear@0 245 wclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
nuclear@0 246 wclass.hIcon = LoadIcon(0, IDI_APPLICATION);
nuclear@0 247 wclass.hCursor = LoadCursor(0, IDC_ARROW);
nuclear@0 248 wclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
nuclear@0 249 RegisterClass(&wclass);
nuclear@0 250
nuclear@0 251 int posx = (GetSystemMetrics(SM_CXSCREEN) - xsz) / 2;
nuclear@0 252 int posy = (GetSystemMetrics(SM_CYSCREEN) - ysz) / 2;
nuclear@0 253
nuclear@0 254 HWND win = CreateWindow("mutantstargoatwin", "DX11 Test", WS_OVERLAPPEDWINDOW, posx, posy,
nuclear@0 255 xsz, ysz, 0, 0, app_inst, 0);
nuclear@0 256 ShowWindow(win, SW_SHOW);
nuclear@0 257
nuclear@0 258 // initialize D3D device
nuclear@0 259 DXGI_SWAP_CHAIN_DESC swap_desc;
nuclear@0 260 memset(&swap_desc, 0, sizeof swap_desc);
nuclear@0 261 swap_desc.BufferCount = 1;
nuclear@0 262 swap_desc.BufferDesc.Width = xsz;
nuclear@0 263 swap_desc.BufferDesc.Height = ysz;
nuclear@0 264 swap_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
nuclear@0 265 swap_desc.BufferDesc.RefreshRate.Numerator = 60;
nuclear@0 266 swap_desc.BufferDesc.RefreshRate.Denominator = 1;
nuclear@0 267 swap_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
nuclear@0 268 swap_desc.OutputWindow = win;
nuclear@0 269 swap_desc.SampleDesc.Count = 1;
nuclear@0 270 swap_desc.SampleDesc.Quality = 0;
nuclear@0 271 swap_desc.Windowed = 1;
nuclear@0 272
nuclear@0 273 D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0;
nuclear@0 274
nuclear@0 275 if(D3D11CreateDeviceAndSwapChain(0, D3D_DRIVER_TYPE_HARDWARE, 0, 0, &feature_level, 1,
nuclear@0 276 D3D11_SDK_VERSION, &swap_desc, &swap, &dev, 0, &ctx) != 0) {
nuclear@0 277 fprintf(stderr, "Failed to create d3d device and swap chain\n");
nuclear@0 278 return 0;
nuclear@0 279 }
nuclear@0 280
nuclear@0 281 ID3D11Texture2D *rtex;
nuclear@0 282 if(swap->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&rtex) != 0) {
nuclear@0 283 fprintf(stderr, "Failed to get default render target texture\n");
nuclear@0 284 return 0;
nuclear@0 285 }
nuclear@0 286 if(dev->CreateRenderTargetView(rtex, 0, &rtarg_view) != 0) {
nuclear@0 287 fprintf(stderr, "Failed to create render target view\n");
nuclear@0 288 rtex->Release();
nuclear@0 289 return 0;
nuclear@0 290 }
nuclear@0 291 rtex->Release();
nuclear@0 292 ctx->OMSetRenderTargets(1, &rtarg_view, 0);
nuclear@0 293
nuclear@0 294 reshape(xsz, ysz);
nuclear@0 295 return win;
nuclear@0 296 }
nuclear@0 297
nuclear@0 298 static void destroy_window(HWND win)
nuclear@0 299 {
nuclear@0 300 CloseWindow(win);
nuclear@0 301 UnregisterClass("mutantstargoatwin", GetModuleHandle(0));
nuclear@0 302
nuclear@0 303 rtarg_view->Release();
nuclear@0 304 ctx->Release();
nuclear@0 305 dev->Release();
nuclear@0 306 swap->Release();
nuclear@0 307 }
nuclear@0 308
nuclear@0 309 static void main_loop()
nuclear@0 310 {
nuclear@0 311 MSG msg;
nuclear@0 312
nuclear@0 313 for(;;) {
nuclear@0 314 while(PeekMessage(&msg, win, 0, 0, PM_REMOVE)) {
nuclear@0 315 TranslateMessage(&msg);
nuclear@0 316 DispatchMessage(&msg);
nuclear@0 317
nuclear@0 318 if(msg.message == WM_QUIT) {
nuclear@0 319 return;
nuclear@0 320 }
nuclear@0 321 }
nuclear@0 322
nuclear@0 323 display();
nuclear@0 324 }
nuclear@0 325 }
nuclear@0 326
nuclear@0 327 static long CALLBACK win_proc(HWND win, unsigned int msg, unsigned int wparam, long lparam)
nuclear@0 328 {
nuclear@0 329 switch(msg) {
nuclear@0 330 case WM_KEYDOWN:
nuclear@0 331 keyb(wparam, true);
nuclear@0 332 break;
nuclear@0 333
nuclear@0 334 case WM_KEYUP:
nuclear@0 335 keyb(wparam, false);
nuclear@0 336 break;
nuclear@0 337
nuclear@0 338 default:
nuclear@0 339 return DefWindowProc(win, msg, wparam, lparam);
nuclear@0 340 }
nuclear@0 341 return 0;
nuclear@0 342 }