d3d11-subsystem.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  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 <graphics/device-exports.h>
  26. #include <util/windows/ComPtr.hpp>
  27. #include <util/windows/HRError.hpp>
  28. struct shader_var;
  29. struct shader_sampler;
  30. struct gs_vertex_shader;
  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. size_t pos;
  274. vector<uint8_t> curValue;
  275. vector<uint8_t> defaultValue;
  276. bool changed;
  277. shader_param(shader_var &var, uint32_t &texCounter);
  278. };
  279. struct ShaderError {
  280. ComPtr<ID3D10Blob> errors;
  281. HRESULT hr;
  282. inline ShaderError(const ComPtr<ID3D10Blob> &errors, HRESULT hr)
  283. : errors (errors),
  284. hr (hr)
  285. {
  286. }
  287. };
  288. struct gs_shader {
  289. device_t device;
  290. shader_type type;
  291. vector<shader_param> params;
  292. ComPtr<ID3D11Buffer> constants;
  293. size_t constantSize;
  294. inline void UpdateParam(vector<uint8_t> &constData, shader_param &param,
  295. bool &upload);
  296. void UploadParams();
  297. void BuildConstantBuffer();
  298. void Compile(const char *shaderStr, const char *file,
  299. const char *target, ID3D10Blob **shader);
  300. inline gs_shader(device_t device, shader_type type)
  301. : device (device),
  302. type (type),
  303. constantSize (0)
  304. {
  305. }
  306. virtual ~gs_shader() {}
  307. };
  308. struct ShaderSampler {
  309. string name;
  310. gs_sampler_state sampler;
  311. inline ShaderSampler(const char *name, device_t device,
  312. gs_sampler_info *info)
  313. : name (name),
  314. sampler (device, info)
  315. {
  316. }
  317. };
  318. struct gs_vertex_shader : gs_shader {
  319. ComPtr<ID3D11VertexShader> shader;
  320. ComPtr<ID3D11InputLayout> layout;
  321. shader_param *world, *viewProj;
  322. bool hasNormals;
  323. bool hasColors;
  324. bool hasTangents;
  325. uint32_t nTexUnits;
  326. inline uint32_t NumBuffersExpected() const
  327. {
  328. uint32_t count = nTexUnits+1;
  329. if (hasNormals) count++;
  330. if (hasColors) count++;
  331. if (hasTangents) count++;
  332. return count;
  333. }
  334. void GetBuffersExpected(const vector<D3D11_INPUT_ELEMENT_DESC> &inputs);
  335. gs_vertex_shader(device_t device, const char *file,
  336. const char *shaderString);
  337. };
  338. struct gs_pixel_shader : gs_shader {
  339. ComPtr<ID3D11PixelShader> shader;
  340. vector<ShaderSampler> samplers;
  341. inline void GetSamplerStates(ID3D11SamplerState **states)
  342. {
  343. size_t i;
  344. for (i = 0; i < samplers.size(); i++)
  345. states[i] = samplers[i].sampler.state;
  346. for (; i < GS_MAX_TEXTURES; i++)
  347. states[i] = NULL;
  348. }
  349. gs_pixel_shader(device_t device, const char *file,
  350. const char *shaderString);
  351. };
  352. struct gs_swap_chain {
  353. gs_device *device;
  354. uint32_t numBuffers;
  355. HWND hwnd;
  356. gs_texture_2d target;
  357. gs_zstencil_buffer zs;
  358. ComPtr<IDXGISwapChain> swap;
  359. void InitTarget(uint32_t cx, uint32_t cy);
  360. void InitZStencilBuffer(uint32_t cx, uint32_t cy);
  361. void Resize(uint32_t cx, uint32_t cy);
  362. void Init(gs_init_data *data);
  363. inline gs_swap_chain()
  364. : device (NULL),
  365. numBuffers (0),
  366. hwnd (NULL)
  367. {
  368. }
  369. gs_swap_chain(gs_device *device, gs_init_data *data);
  370. };
  371. struct BlendState {
  372. bool blendEnabled;
  373. gs_blend_type srcFactor;
  374. gs_blend_type destFactor;
  375. bool redEnabled;
  376. bool greenEnabled;
  377. bool blueEnabled;
  378. bool alphaEnabled;
  379. inline BlendState()
  380. : blendEnabled (true),
  381. srcFactor (GS_BLEND_SRCALPHA),
  382. destFactor (GS_BLEND_INVSRCALPHA),
  383. redEnabled (true),
  384. greenEnabled (true),
  385. blueEnabled (true),
  386. alphaEnabled (true)
  387. {
  388. }
  389. inline BlendState(const BlendState &state)
  390. {
  391. memcpy(this, &state, sizeof(BlendState));
  392. }
  393. };
  394. struct SavedBlendState : BlendState {
  395. ComPtr<ID3D11BlendState> state;
  396. inline SavedBlendState(const BlendState &val) : BlendState(val)
  397. {
  398. }
  399. };
  400. struct StencilSide {
  401. gs_depth_test test;
  402. gs_stencil_op fail;
  403. gs_stencil_op zfail;
  404. gs_stencil_op zpass;
  405. inline StencilSide()
  406. : test (GS_ALWAYS),
  407. fail (GS_KEEP),
  408. zfail (GS_KEEP),
  409. zpass (GS_KEEP)
  410. {
  411. }
  412. };
  413. struct ZStencilState {
  414. bool depthEnabled;
  415. bool depthWriteEnabled;
  416. gs_depth_test depthFunc;
  417. bool stencilEnabled;
  418. bool stencilWriteEnabled;
  419. StencilSide stencilFront;
  420. StencilSide stencilBack;
  421. inline ZStencilState()
  422. : depthEnabled (true),
  423. depthWriteEnabled (true),
  424. depthFunc (GS_LESS),
  425. stencilEnabled (false),
  426. stencilWriteEnabled (true)
  427. {
  428. }
  429. inline ZStencilState(const ZStencilState &state)
  430. {
  431. memcpy(this, &state, sizeof(ZStencilState));
  432. }
  433. };
  434. struct SavedZStencilState : ZStencilState {
  435. ComPtr<ID3D11DepthStencilState> state;
  436. inline SavedZStencilState(const ZStencilState &val)
  437. : ZStencilState (val)
  438. {
  439. }
  440. };
  441. struct RasterState {
  442. gs_cull_mode cullMode;
  443. bool scissorEnabled;
  444. inline RasterState()
  445. : cullMode (GS_BACK),
  446. scissorEnabled (false)
  447. {
  448. }
  449. inline RasterState(const RasterState &state)
  450. {
  451. memcpy(this, &state, sizeof(RasterState));
  452. }
  453. };
  454. struct SavedRasterState : RasterState {
  455. ComPtr<ID3D11RasterizerState> state;
  456. inline SavedRasterState(const RasterState &val)
  457. : RasterState (val)
  458. {
  459. }
  460. };
  461. struct mat4float {
  462. float mat[16];
  463. };
  464. struct gs_device {
  465. ComPtr<IDXGIFactory1> factory;
  466. ComPtr<ID3D11Device> device;
  467. ComPtr<ID3D11DeviceContext> context;
  468. gs_swap_chain defaultSwap;
  469. gs_texture_2d *curRenderTarget;
  470. gs_zstencil_buffer *curZStencilBuffer;
  471. int curRenderSide;
  472. gs_texture *curTextures[GS_MAX_TEXTURES];
  473. gs_sampler_state *curSamplers[GS_MAX_TEXTURES];
  474. gs_vertex_buffer *curVertexBuffer;
  475. gs_index_buffer *curIndexBuffer;
  476. gs_vertex_shader *curVertexShader;
  477. gs_pixel_shader *curPixelShader;
  478. gs_swap_chain *curSwapChain;
  479. bool zstencilStateChanged;
  480. bool rasterStateChanged;
  481. bool blendStateChanged;
  482. ZStencilState zstencilState;
  483. RasterState rasterState;
  484. BlendState blendState;
  485. vector<SavedZStencilState> zstencilStates;
  486. vector<SavedRasterState> rasterStates;
  487. vector<SavedBlendState> blendStates;
  488. ID3D11DepthStencilState *curDepthStencilState;
  489. ID3D11RasterizerState *curRasterState;
  490. ID3D11BlendState *curBlendState;
  491. D3D11_PRIMITIVE_TOPOLOGY curToplogy;
  492. gs_rect viewport;
  493. vector<mat4float> projStack;
  494. matrix4 curProjMatrix;
  495. matrix4 curViewMatrix;
  496. matrix4 curViewProjMatrix;
  497. void InitFactory(uint32_t adapterIdx, IDXGIAdapter1 **adapter);
  498. void InitDevice(gs_init_data *data, IDXGIAdapter *adapter);
  499. ID3D11DepthStencilState *AddZStencilState();
  500. ID3D11RasterizerState *AddRasterState();
  501. ID3D11BlendState *AddBlendState();
  502. void UpdateZStencilState();
  503. void UpdateRasterState();
  504. void UpdateBlendState();
  505. inline void CopyTex(ID3D11Texture2D *dst, uint32_t dst_x, uint32_t dst_y,
  506. texture_t src, uint32_t src_x, uint32_t src_y,
  507. uint32_t src_w, uint32_t src_h);
  508. void UpdateViewProjMatrix();
  509. gs_device(gs_init_data *data);
  510. };