d3d11-subsystem.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /******************************************************************************
  2. Copyright (C) 2013 by Hugh Bailey <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #pragma once
  15. #include <util/AlignedNew.hpp>
  16. #include <vector>
  17. #include <string>
  18. #include <windows.h>
  19. #include <dxgi.h>
  20. #include <d3d11.h>
  21. #include <d3dcompiler.h>
  22. #include <util/base.h>
  23. #include <graphics/matrix4.h>
  24. #include <graphics/graphics.h>
  25. #include <util/windows/ComPtr.hpp>
  26. #include <util/windows/HRError.hpp>
  27. struct shader_var;
  28. struct shader_sampler;
  29. struct gs_vertex_shader;
  30. #include "d3d11-exports.h"
  31. using namespace std;
  32. /*
  33. * Just to clarify, all structs, and all public. These are exporting only
  34. * via encapsulated C bindings, not C++ bindings, so the whole concept of
  35. * "public" and "private" does not matter at all for this subproject.
  36. */
  37. static inline uint32_t GetWinVer()
  38. {
  39. OSVERSIONINFO ovi;
  40. ovi.dwOSVersionInfoSize = sizeof(ovi);
  41. GetVersionEx(&ovi);
  42. return (ovi.dwMajorVersion << 8) | (ovi.dwMinorVersion);
  43. }
  44. static inline DXGI_FORMAT ConvertGSTextureFormat(gs_color_format format)
  45. {
  46. switch (format) {
  47. case GS_A8: return DXGI_FORMAT_A8_UNORM;
  48. case GS_R8: return DXGI_FORMAT_R8_UNORM;
  49. case GS_RGBA: return DXGI_FORMAT_R8G8B8A8_UNORM;
  50. case GS_BGRX: return DXGI_FORMAT_B8G8R8X8_UNORM;
  51. case GS_BGRA: return DXGI_FORMAT_B8G8R8A8_UNORM;
  52. case GS_R10G10B10A2: return DXGI_FORMAT_R10G10B10A2_UNORM;
  53. case GS_RGBA16: return DXGI_FORMAT_R16G16B16A16_UNORM;
  54. case GS_R16: return DXGI_FORMAT_R16_UNORM;
  55. case GS_RGBA16F: return DXGI_FORMAT_R16G16B16A16_FLOAT;
  56. case GS_RGBA32F: return DXGI_FORMAT_R32G32B32A32_FLOAT;
  57. case GS_RG16F: return DXGI_FORMAT_R16G16_FLOAT;
  58. case GS_RG32F: return DXGI_FORMAT_R32G32_FLOAT;
  59. case GS_R16F: return DXGI_FORMAT_R16_FLOAT;
  60. case GS_R32F: return DXGI_FORMAT_R32_FLOAT;
  61. case GS_DXT1: return DXGI_FORMAT_BC1_UNORM;
  62. case GS_DXT3: return DXGI_FORMAT_BC2_UNORM;
  63. case GS_DXT5: return DXGI_FORMAT_BC3_UNORM;
  64. }
  65. return DXGI_FORMAT_UNKNOWN;
  66. }
  67. static inline DXGI_FORMAT ConvertGSZStencilFormat(gs_zstencil_format format)
  68. {
  69. switch (format) {
  70. case GS_Z16: return DXGI_FORMAT_D16_UNORM;
  71. case GS_Z24_S8: return DXGI_FORMAT_D24_UNORM_S8_UINT;
  72. case GS_Z32F: return DXGI_FORMAT_D32_FLOAT;
  73. case GS_Z32F_S8X24: return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
  74. }
  75. return DXGI_FORMAT_UNKNOWN;
  76. }
  77. static inline D3D11_COMPARISON_FUNC ConvertGSDepthTest(gs_depth_test test)
  78. {
  79. switch (test) {
  80. case GS_NEVER: return D3D11_COMPARISON_NEVER;
  81. case GS_LESS: return D3D11_COMPARISON_LESS;
  82. case GS_LEQUAL: return D3D11_COMPARISON_LESS_EQUAL;
  83. case GS_EQUAL: return D3D11_COMPARISON_EQUAL;
  84. case GS_GEQUAL: return D3D11_COMPARISON_GREATER_EQUAL;
  85. case GS_GREATER: return D3D11_COMPARISON_GREATER;
  86. case GS_NOTEQUAL: return D3D11_COMPARISON_NOT_EQUAL;
  87. case GS_ALWAYS: return D3D11_COMPARISON_ALWAYS;
  88. }
  89. return D3D11_COMPARISON_NEVER;
  90. }
  91. static inline D3D11_STENCIL_OP ConvertGSStencilOp(gs_stencil_op op)
  92. {
  93. switch (op) {
  94. case GS_KEEP: return D3D11_STENCIL_OP_KEEP;
  95. case GS_ZERO: return D3D11_STENCIL_OP_ZERO;
  96. case GS_REPLACE: return D3D11_STENCIL_OP_REPLACE;
  97. case GS_INCR: return D3D11_STENCIL_OP_INCR;
  98. case GS_DECR: return D3D11_STENCIL_OP_DECR;
  99. case GS_INVERT: return D3D11_STENCIL_OP_INVERT;
  100. }
  101. return D3D11_STENCIL_OP_KEEP;
  102. }
  103. static inline D3D11_BLEND ConvertGSBlendType(gs_blend_type type)
  104. {
  105. switch (type) {
  106. case GS_BLEND_ZERO: return D3D11_BLEND_ZERO;
  107. case GS_BLEND_ONE: return D3D11_BLEND_ONE;
  108. case GS_BLEND_SRCCOLOR: return D3D11_BLEND_SRC_COLOR;
  109. case GS_BLEND_INVSRCCOLOR: return D3D11_BLEND_INV_SRC_COLOR;
  110. case GS_BLEND_SRCALPHA: return D3D11_BLEND_SRC_ALPHA;
  111. case GS_BLEND_INVSRCALPHA: return D3D11_BLEND_INV_SRC_ALPHA;
  112. case GS_BLEND_DSTCOLOR: return D3D11_BLEND_DEST_COLOR;
  113. case GS_BLEND_INVDSTCOLOR: return D3D11_BLEND_INV_DEST_COLOR;
  114. case GS_BLEND_DSTALPHA: return D3D11_BLEND_DEST_ALPHA;
  115. case GS_BLEND_INVDSTALPHA: return D3D11_BLEND_INV_DEST_ALPHA;
  116. case GS_BLEND_SRCALPHASAT: return D3D11_BLEND_SRC_ALPHA_SAT;
  117. }
  118. return D3D11_BLEND_ONE;
  119. }
  120. static inline D3D11_CULL_MODE ConvertGSCullMode(gs_cull_mode mode)
  121. {
  122. switch (mode) {
  123. case GS_BACK: return D3D11_CULL_BACK;
  124. case GS_FRONT: return D3D11_CULL_FRONT;
  125. case GS_NEITHER: return D3D11_CULL_NONE;
  126. }
  127. return D3D11_CULL_BACK;
  128. }
  129. static inline D3D11_PRIMITIVE_TOPOLOGY ConvertGSTopology(gs_draw_mode mode)
  130. {
  131. switch (mode) {
  132. case GS_POINTS: return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
  133. case GS_LINES: return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
  134. case GS_LINESTRIP: return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
  135. case GS_TRIS: return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  136. case GS_TRISTRIP: return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
  137. }
  138. return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
  139. }
  140. /* exception-safe RAII wrapper for vertex buffer data (NOTE: not copy-safe) */
  141. struct VBDataPtr {
  142. vb_data *data;
  143. inline VBDataPtr(vb_data *data) : data(data) {}
  144. inline ~VBDataPtr() {vbdata_destroy(data);}
  145. };
  146. struct gs_vertex_buffer {
  147. ComPtr<ID3D11Buffer> vertexBuffer;
  148. ComPtr<ID3D11Buffer> normalBuffer;
  149. ComPtr<ID3D11Buffer> colorBuffer;
  150. ComPtr<ID3D11Buffer> tangentBuffer;
  151. vector<ComPtr<ID3D11Buffer>> uvBuffers;
  152. device_t device;
  153. bool dynamic;
  154. VBDataPtr vbd;
  155. size_t numVerts;
  156. vector<size_t> uvSizes;
  157. void FlushBuffer(ID3D11Buffer *buffer, void *array,
  158. size_t elementSize);
  159. void MakeBufferList(gs_vertex_shader *shader,
  160. vector<ID3D11Buffer*> &buffers,
  161. vector<uint32_t> &strides);
  162. inline void InitBuffer(const size_t elementSize,
  163. const size_t numVerts, void *array,
  164. ID3D11Buffer **buffer);
  165. gs_vertex_buffer(device_t device, struct vb_data *data, uint32_t flags);
  166. };
  167. /* exception-safe RAII wrapper for index buffer data (NOTE: not copy-safe) */
  168. struct DataPtr {
  169. void *data;
  170. inline DataPtr(void *data) : data(data) {}
  171. inline ~DataPtr() {bfree(data);}
  172. };
  173. struct gs_index_buffer {
  174. ComPtr<ID3D11Buffer> indexBuffer;
  175. device_t device;
  176. bool dynamic;
  177. gs_index_type type;
  178. size_t indexSize;
  179. size_t num;
  180. DataPtr indices;
  181. void InitBuffer();
  182. gs_index_buffer(device_t device, enum gs_index_type type,
  183. void *indices, size_t num, uint32_t flags);
  184. };
  185. struct gs_texture {
  186. gs_texture_type type;
  187. gs_device *device;
  188. uint32_t levels;
  189. gs_color_format format;
  190. ComPtr<ID3D11ShaderResourceView> shaderRes;
  191. inline gs_texture(gs_device *device, gs_texture_type type,
  192. uint32_t levels, gs_color_format format)
  193. : device (device),
  194. type (type),
  195. levels (levels),
  196. format (format)
  197. {
  198. }
  199. virtual ~gs_texture() {}
  200. };
  201. struct gs_texture_2d : gs_texture {
  202. ComPtr<ID3D11Texture2D> texture;
  203. ComPtr<ID3D11RenderTargetView> renderTarget[6];
  204. ComPtr<IDXGISurface1> gdiSurface;
  205. uint32_t width, height;
  206. DXGI_FORMAT dxgiFormat;
  207. bool isRenderTarget;
  208. bool isGDICompatible;
  209. bool isDynamic;
  210. bool isShared;
  211. bool genMipmaps;
  212. HANDLE sharedHandle;
  213. void InitSRD(vector<D3D11_SUBRESOURCE_DATA> &srd, const void **data);
  214. void InitTexture(const void **data);
  215. void InitResourceView();
  216. void InitRenderTargets();
  217. inline gs_texture_2d()
  218. : gs_texture (NULL, GS_TEXTURE_2D, 0, GS_UNKNOWN),
  219. width (0),
  220. height (0),
  221. dxgiFormat (DXGI_FORMAT_UNKNOWN),
  222. isRenderTarget (false),
  223. isGDICompatible (false),
  224. isDynamic (false),
  225. isShared (false),
  226. genMipmaps (false),
  227. sharedHandle (NULL)
  228. {
  229. }
  230. gs_texture_2d(device_t device, uint32_t width, uint32_t height,
  231. gs_color_format colorFormat, uint32_t levels,
  232. const void **data, uint32_t flags, gs_texture_type type,
  233. bool gdiCompatible, bool shared);
  234. };
  235. struct gs_zstencil_buffer {
  236. ComPtr<ID3D11Texture2D> texture;
  237. ComPtr<ID3D11DepthStencilView> view;
  238. gs_device *device;
  239. uint32_t width, height;
  240. gs_zstencil_format format;
  241. DXGI_FORMAT dxgiFormat;
  242. void InitBuffer();
  243. inline gs_zstencil_buffer()
  244. : device (NULL),
  245. width (0),
  246. height (0),
  247. dxgiFormat (DXGI_FORMAT_UNKNOWN)
  248. {
  249. }
  250. gs_zstencil_buffer(device_t device, uint32_t width, uint32_t height,
  251. gs_zstencil_format format);
  252. };
  253. struct gs_stage_surface {
  254. ComPtr<ID3D11Texture2D> texture;
  255. gs_device *device;
  256. uint32_t width, height;
  257. gs_color_format format;
  258. DXGI_FORMAT dxgiFormat;
  259. gs_stage_surface(device_t device, uint32_t width, uint32_t height,
  260. gs_color_format colorFormat);
  261. };
  262. struct gs_sampler_state {
  263. ComPtr<ID3D11SamplerState> state;
  264. device_t device;
  265. gs_sampler_info info;
  266. gs_sampler_state(device_t device, gs_sampler_info *info);
  267. };
  268. struct shader_param {
  269. string name;
  270. shader_param_type type;
  271. uint32_t textureID;
  272. int arrayCount;
  273. vector<uint8_t> curValue;
  274. vector<uint8_t> defaultValue;
  275. bool changed;
  276. shader_param(shader_var &var, uint32_t &texCounter);
  277. };
  278. struct ShaderError {
  279. ComPtr<ID3D10Blob> errors;
  280. HRESULT hr;
  281. inline ShaderError(const ComPtr<ID3D10Blob> &errors, HRESULT hr)
  282. : errors (errors),
  283. hr (hr)
  284. {
  285. }
  286. };
  287. struct gs_shader {
  288. device_t device;
  289. shader_type type;
  290. vector<shader_param> params;
  291. ComPtr<ID3D11Buffer> constants;
  292. size_t constantSize;
  293. inline void UpdateParam(vector<uint8_t> &constData, shader_param &param,
  294. bool &upload);
  295. void UploadParams();
  296. void BuildConstantBuffer();
  297. void Compile(const char *shaderStr, const char *file,
  298. const char *target, ID3D10Blob **shader);
  299. inline gs_shader(device_t device, shader_type type)
  300. : device (device),
  301. type (type),
  302. constantSize (0)
  303. {
  304. }
  305. virtual ~gs_shader() {}
  306. };
  307. struct ShaderSampler {
  308. string name;
  309. gs_sampler_state sampler;
  310. inline ShaderSampler(const char *name, device_t device,
  311. gs_sampler_info *info)
  312. : name (name),
  313. sampler (device, info)
  314. {
  315. }
  316. };
  317. struct gs_vertex_shader : gs_shader {
  318. ComPtr<ID3D11VertexShader> shader;
  319. ComPtr<ID3D11InputLayout> layout;
  320. shader_param *world, *viewProj;
  321. bool hasNormals;
  322. bool hasColors;
  323. bool hasTangents;
  324. uint32_t nTexUnits;
  325. inline uint32_t NumBuffersExpected() const
  326. {
  327. uint32_t count = nTexUnits+1;
  328. if (hasNormals) count++;
  329. if (hasColors) count++;
  330. if (hasTangents) count++;
  331. return count;
  332. }
  333. void GetBuffersExpected(const vector<D3D11_INPUT_ELEMENT_DESC> &inputs);
  334. gs_vertex_shader(device_t device, const char *file,
  335. const char *shaderString);
  336. };
  337. struct gs_pixel_shader : gs_shader {
  338. ComPtr<ID3D11PixelShader> shader;
  339. vector<ShaderSampler> samplers;
  340. inline void GetSamplerStates(ID3D11SamplerState **states)
  341. {
  342. size_t i;
  343. for (i = 0; i < samplers.size(); i++)
  344. states[i] = samplers[i].sampler.state;
  345. for (; i < GS_MAX_TEXTURES; i++)
  346. states[i] = NULL;
  347. }
  348. gs_pixel_shader(device_t device, const char *file,
  349. const char *shaderString);
  350. };
  351. struct gs_swap_chain {
  352. gs_device *device;
  353. uint32_t numBuffers;
  354. HWND hwnd;
  355. gs_texture_2d target;
  356. gs_zstencil_buffer zs;
  357. ComPtr<IDXGISwapChain> swap;
  358. void InitTarget(uint32_t cx, uint32_t cy);
  359. void InitZStencilBuffer(uint32_t cx, uint32_t cy);
  360. void Resize(uint32_t cx, uint32_t cy);
  361. void Init(gs_init_data *data);
  362. inline gs_swap_chain()
  363. : device (NULL),
  364. numBuffers (0),
  365. hwnd (NULL)
  366. {
  367. }
  368. gs_swap_chain(gs_device *device, gs_init_data *data);
  369. };
  370. struct BlendState {
  371. bool blendEnabled;
  372. gs_blend_type srcFactor;
  373. gs_blend_type destFactor;
  374. bool redEnabled;
  375. bool greenEnabled;
  376. bool blueEnabled;
  377. bool alphaEnabled;
  378. inline BlendState()
  379. : blendEnabled (true),
  380. srcFactor (GS_BLEND_SRCALPHA),
  381. destFactor (GS_BLEND_INVSRCALPHA),
  382. redEnabled (true),
  383. greenEnabled (true),
  384. blueEnabled (true),
  385. alphaEnabled (true)
  386. {
  387. }
  388. inline BlendState(const BlendState &state)
  389. {
  390. memcpy(this, &state, sizeof(BlendState));
  391. }
  392. };
  393. struct SavedBlendState : BlendState {
  394. ComPtr<ID3D11BlendState> state;
  395. inline SavedBlendState(const BlendState &val) : BlendState(val)
  396. {
  397. }
  398. };
  399. struct StencilSide {
  400. gs_depth_test test;
  401. gs_stencil_op fail;
  402. gs_stencil_op zfail;
  403. gs_stencil_op zpass;
  404. inline StencilSide()
  405. : test (GS_ALWAYS),
  406. fail (GS_KEEP),
  407. zfail (GS_KEEP),
  408. zpass (GS_KEEP)
  409. {
  410. }
  411. };
  412. struct ZStencilState {
  413. bool depthEnabled;
  414. bool depthWriteEnabled;
  415. gs_depth_test depthFunc;
  416. bool stencilEnabled;
  417. bool stencilWriteEnabled;
  418. StencilSide stencilFront;
  419. StencilSide stencilBack;
  420. inline ZStencilState()
  421. : depthEnabled (true),
  422. depthWriteEnabled (true),
  423. depthFunc (GS_LESS),
  424. stencilEnabled (false),
  425. stencilWriteEnabled (true)
  426. {
  427. }
  428. inline ZStencilState(const ZStencilState &state)
  429. {
  430. memcpy(this, &state, sizeof(ZStencilState));
  431. }
  432. };
  433. struct SavedZStencilState : ZStencilState {
  434. ComPtr<ID3D11DepthStencilState> state;
  435. inline SavedZStencilState(const ZStencilState &val)
  436. : ZStencilState (val)
  437. {
  438. }
  439. };
  440. struct RasterState {
  441. gs_cull_mode cullMode;
  442. bool scissorEnabled;
  443. inline RasterState()
  444. : cullMode (GS_BACK),
  445. scissorEnabled (false)
  446. {
  447. }
  448. inline RasterState(const RasterState &state)
  449. {
  450. memcpy(this, &state, sizeof(RasterState));
  451. }
  452. };
  453. struct SavedRasterState : RasterState {
  454. ComPtr<ID3D11RasterizerState> state;
  455. inline SavedRasterState(const RasterState &val)
  456. : RasterState (val)
  457. {
  458. }
  459. };
  460. struct mat4float {
  461. float mat[16];
  462. };
  463. struct gs_device {
  464. ComPtr<IDXGIFactory1> factory;
  465. ComPtr<ID3D11Device> device;
  466. ComPtr<ID3D11DeviceContext> context;
  467. gs_swap_chain defaultSwap;
  468. gs_texture_2d *curRenderTarget;
  469. gs_zstencil_buffer *curZStencilBuffer;
  470. int curRenderSide;
  471. gs_texture *curTextures[GS_MAX_TEXTURES];
  472. gs_sampler_state *curSamplers[GS_MAX_TEXTURES];
  473. gs_vertex_buffer *curVertexBuffer;
  474. gs_index_buffer *curIndexBuffer;
  475. gs_vertex_shader *curVertexShader;
  476. gs_pixel_shader *curPixelShader;
  477. gs_swap_chain *curSwapChain;
  478. bool zstencilStateChanged;
  479. bool rasterStateChanged;
  480. bool blendStateChanged;
  481. ZStencilState zstencilState;
  482. RasterState rasterState;
  483. BlendState blendState;
  484. vector<SavedZStencilState> zstencilStates;
  485. vector<SavedRasterState> rasterStates;
  486. vector<SavedBlendState> blendStates;
  487. ID3D11DepthStencilState *curDepthStencilState;
  488. ID3D11RasterizerState *curRasterState;
  489. ID3D11BlendState *curBlendState;
  490. D3D11_PRIMITIVE_TOPOLOGY curToplogy;
  491. gs_rect viewport;
  492. vector<mat4float> projStack;
  493. matrix4 curProjMatrix;
  494. matrix4 curViewMatrix;
  495. matrix4 curViewProjMatrix;
  496. void InitFactory(uint32_t adapterIdx, IDXGIAdapter1 **adapter);
  497. void InitDevice(gs_init_data *data, IDXGIAdapter *adapter);
  498. ID3D11DepthStencilState *AddZStencilState();
  499. ID3D11RasterizerState *AddRasterState();
  500. ID3D11BlendState *AddBlendState();
  501. void UpdateZStencilState();
  502. void UpdateRasterState();
  503. void UpdateBlendState();
  504. inline void CopyTex(ID3D11Texture2D *dst, texture_t src);
  505. void UpdateViewProjMatrix();
  506. gs_device(gs_init_data *data);
  507. };