d3d11-subsystem.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  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 void Clear() {vbdata_destroy(data); data = nullptr;}
  144. inline VBDataPtr(vb_data *data) : data(data) {}
  145. inline ~VBDataPtr() {vbdata_destroy(data);}
  146. };
  147. struct gs_vertex_buffer {
  148. ComPtr<ID3D11Buffer> vertexBuffer;
  149. ComPtr<ID3D11Buffer> normalBuffer;
  150. ComPtr<ID3D11Buffer> colorBuffer;
  151. ComPtr<ID3D11Buffer> tangentBuffer;
  152. vector<ComPtr<ID3D11Buffer>> uvBuffers;
  153. device_t device;
  154. bool dynamic;
  155. VBDataPtr vbd;
  156. size_t numVerts;
  157. vector<size_t> uvSizes;
  158. void FlushBuffer(ID3D11Buffer *buffer, void *array,
  159. size_t elementSize);
  160. void MakeBufferList(gs_vertex_shader *shader,
  161. vector<ID3D11Buffer*> &buffers,
  162. vector<uint32_t> &strides);
  163. inline void InitBuffer(const size_t elementSize,
  164. const size_t numVerts, void *array,
  165. ID3D11Buffer **buffer);
  166. gs_vertex_buffer(device_t device, struct vb_data *data, uint32_t flags);
  167. };
  168. /* exception-safe RAII wrapper for index buffer data (NOTE: not copy-safe) */
  169. struct DataPtr {
  170. void *data;
  171. inline DataPtr(void *data) : data(data) {}
  172. inline ~DataPtr() {bfree(data);}
  173. };
  174. struct gs_index_buffer {
  175. ComPtr<ID3D11Buffer> indexBuffer;
  176. device_t device;
  177. bool dynamic;
  178. gs_index_type type;
  179. size_t indexSize;
  180. size_t num;
  181. DataPtr indices;
  182. void InitBuffer();
  183. gs_index_buffer(device_t device, enum gs_index_type type,
  184. void *indices, size_t num, uint32_t flags);
  185. };
  186. struct gs_texture {
  187. gs_texture_type type;
  188. gs_device *device;
  189. uint32_t levels;
  190. gs_color_format format;
  191. ComPtr<ID3D11ShaderResourceView> shaderRes;
  192. inline gs_texture(gs_device *device, gs_texture_type type,
  193. uint32_t levels, gs_color_format format)
  194. : device (device),
  195. type (type),
  196. levels (levels),
  197. format (format)
  198. {
  199. }
  200. virtual ~gs_texture() {}
  201. };
  202. struct gs_texture_2d : gs_texture {
  203. ComPtr<ID3D11Texture2D> texture;
  204. ComPtr<ID3D11RenderTargetView> renderTarget[6];
  205. ComPtr<IDXGISurface1> gdiSurface;
  206. uint32_t width, height;
  207. DXGI_FORMAT dxgiFormat;
  208. bool isRenderTarget;
  209. bool isGDICompatible;
  210. bool isDynamic;
  211. bool isShared;
  212. bool genMipmaps;
  213. HANDLE sharedHandle;
  214. void InitSRD(vector<D3D11_SUBRESOURCE_DATA> &srd, const void **data);
  215. void InitTexture(const void **data);
  216. void InitResourceView();
  217. void InitRenderTargets();
  218. inline gs_texture_2d()
  219. : gs_texture (NULL, GS_TEXTURE_2D, 0, GS_UNKNOWN),
  220. width (0),
  221. height (0),
  222. dxgiFormat (DXGI_FORMAT_UNKNOWN),
  223. isRenderTarget (false),
  224. isGDICompatible (false),
  225. isDynamic (false),
  226. isShared (false),
  227. genMipmaps (false),
  228. sharedHandle (NULL)
  229. {
  230. }
  231. gs_texture_2d(device_t device, uint32_t width, uint32_t height,
  232. gs_color_format colorFormat, uint32_t levels,
  233. const void **data, uint32_t flags, gs_texture_type type,
  234. bool gdiCompatible, bool shared);
  235. };
  236. struct gs_zstencil_buffer {
  237. ComPtr<ID3D11Texture2D> texture;
  238. ComPtr<ID3D11DepthStencilView> view;
  239. gs_device *device;
  240. uint32_t width, height;
  241. gs_zstencil_format format;
  242. DXGI_FORMAT dxgiFormat;
  243. void InitBuffer();
  244. inline gs_zstencil_buffer()
  245. : device (NULL),
  246. width (0),
  247. height (0),
  248. dxgiFormat (DXGI_FORMAT_UNKNOWN)
  249. {
  250. }
  251. gs_zstencil_buffer(device_t device, uint32_t width, uint32_t height,
  252. gs_zstencil_format format);
  253. };
  254. struct gs_stage_surface {
  255. ComPtr<ID3D11Texture2D> texture;
  256. gs_device *device;
  257. uint32_t width, height;
  258. gs_color_format format;
  259. DXGI_FORMAT dxgiFormat;
  260. gs_stage_surface(device_t device, uint32_t width, uint32_t height,
  261. gs_color_format colorFormat);
  262. };
  263. struct gs_sampler_state {
  264. ComPtr<ID3D11SamplerState> state;
  265. device_t device;
  266. gs_sampler_info info;
  267. gs_sampler_state(device_t device, gs_sampler_info *info);
  268. };
  269. struct shader_param {
  270. string name;
  271. shader_param_type type;
  272. uint32_t textureID;
  273. int arrayCount;
  274. size_t pos;
  275. vector<uint8_t> curValue;
  276. vector<uint8_t> defaultValue;
  277. bool changed;
  278. shader_param(shader_var &var, uint32_t &texCounter);
  279. };
  280. struct ShaderError {
  281. ComPtr<ID3D10Blob> errors;
  282. HRESULT hr;
  283. inline ShaderError(const ComPtr<ID3D10Blob> &errors, HRESULT hr)
  284. : errors (errors),
  285. hr (hr)
  286. {
  287. }
  288. };
  289. struct gs_shader {
  290. device_t device;
  291. shader_type type;
  292. vector<shader_param> params;
  293. ComPtr<ID3D11Buffer> constants;
  294. size_t constantSize;
  295. inline void UpdateParam(vector<uint8_t> &constData, shader_param &param,
  296. bool &upload);
  297. void UploadParams();
  298. void BuildConstantBuffer();
  299. void Compile(const char *shaderStr, const char *file,
  300. const char *target, ID3D10Blob **shader);
  301. inline gs_shader(device_t device, shader_type type)
  302. : device (device),
  303. type (type),
  304. constantSize (0)
  305. {
  306. }
  307. virtual ~gs_shader() {}
  308. };
  309. struct ShaderSampler {
  310. string name;
  311. gs_sampler_state sampler;
  312. inline ShaderSampler(const char *name, device_t device,
  313. gs_sampler_info *info)
  314. : name (name),
  315. sampler (device, info)
  316. {
  317. }
  318. };
  319. struct gs_vertex_shader : gs_shader {
  320. ComPtr<ID3D11VertexShader> shader;
  321. ComPtr<ID3D11InputLayout> layout;
  322. shader_param *world, *viewProj;
  323. bool hasNormals;
  324. bool hasColors;
  325. bool hasTangents;
  326. uint32_t nTexUnits;
  327. inline uint32_t NumBuffersExpected() const
  328. {
  329. uint32_t count = nTexUnits+1;
  330. if (hasNormals) count++;
  331. if (hasColors) count++;
  332. if (hasTangents) count++;
  333. return count;
  334. }
  335. void GetBuffersExpected(const vector<D3D11_INPUT_ELEMENT_DESC> &inputs);
  336. gs_vertex_shader(device_t device, const char *file,
  337. const char *shaderString);
  338. };
  339. struct gs_pixel_shader : gs_shader {
  340. ComPtr<ID3D11PixelShader> shader;
  341. vector<ShaderSampler> samplers;
  342. inline void GetSamplerStates(ID3D11SamplerState **states)
  343. {
  344. size_t i;
  345. for (i = 0; i < samplers.size(); i++)
  346. states[i] = samplers[i].sampler.state;
  347. for (; i < GS_MAX_TEXTURES; i++)
  348. states[i] = NULL;
  349. }
  350. gs_pixel_shader(device_t device, const char *file,
  351. const char *shaderString);
  352. };
  353. struct gs_swap_chain {
  354. gs_device *device;
  355. uint32_t numBuffers;
  356. HWND hwnd;
  357. gs_texture_2d target;
  358. gs_zstencil_buffer zs;
  359. ComPtr<IDXGISwapChain> swap;
  360. void InitTarget(uint32_t cx, uint32_t cy);
  361. void InitZStencilBuffer(uint32_t cx, uint32_t cy);
  362. void Resize(uint32_t cx, uint32_t cy);
  363. void Init(gs_init_data *data);
  364. inline gs_swap_chain()
  365. : device (NULL),
  366. numBuffers (0),
  367. hwnd (NULL)
  368. {
  369. }
  370. gs_swap_chain(gs_device *device, gs_init_data *data);
  371. };
  372. struct BlendState {
  373. bool blendEnabled;
  374. gs_blend_type srcFactor;
  375. gs_blend_type destFactor;
  376. bool redEnabled;
  377. bool greenEnabled;
  378. bool blueEnabled;
  379. bool alphaEnabled;
  380. inline BlendState()
  381. : blendEnabled (true),
  382. srcFactor (GS_BLEND_SRCALPHA),
  383. destFactor (GS_BLEND_INVSRCALPHA),
  384. redEnabled (true),
  385. greenEnabled (true),
  386. blueEnabled (true),
  387. alphaEnabled (true)
  388. {
  389. }
  390. inline BlendState(const BlendState &state)
  391. {
  392. memcpy(this, &state, sizeof(BlendState));
  393. }
  394. };
  395. struct SavedBlendState : BlendState {
  396. ComPtr<ID3D11BlendState> state;
  397. inline SavedBlendState(const BlendState &val) : BlendState(val)
  398. {
  399. }
  400. };
  401. struct StencilSide {
  402. gs_depth_test test;
  403. gs_stencil_op fail;
  404. gs_stencil_op zfail;
  405. gs_stencil_op zpass;
  406. inline StencilSide()
  407. : test (GS_ALWAYS),
  408. fail (GS_KEEP),
  409. zfail (GS_KEEP),
  410. zpass (GS_KEEP)
  411. {
  412. }
  413. };
  414. struct ZStencilState {
  415. bool depthEnabled;
  416. bool depthWriteEnabled;
  417. gs_depth_test depthFunc;
  418. bool stencilEnabled;
  419. bool stencilWriteEnabled;
  420. StencilSide stencilFront;
  421. StencilSide stencilBack;
  422. inline ZStencilState()
  423. : depthEnabled (true),
  424. depthWriteEnabled (true),
  425. depthFunc (GS_LESS),
  426. stencilEnabled (false),
  427. stencilWriteEnabled (true)
  428. {
  429. }
  430. inline ZStencilState(const ZStencilState &state)
  431. {
  432. memcpy(this, &state, sizeof(ZStencilState));
  433. }
  434. };
  435. struct SavedZStencilState : ZStencilState {
  436. ComPtr<ID3D11DepthStencilState> state;
  437. inline SavedZStencilState(const ZStencilState &val)
  438. : ZStencilState (val)
  439. {
  440. }
  441. };
  442. struct RasterState {
  443. gs_cull_mode cullMode;
  444. bool scissorEnabled;
  445. inline RasterState()
  446. : cullMode (GS_BACK),
  447. scissorEnabled (false)
  448. {
  449. }
  450. inline RasterState(const RasterState &state)
  451. {
  452. memcpy(this, &state, sizeof(RasterState));
  453. }
  454. };
  455. struct SavedRasterState : RasterState {
  456. ComPtr<ID3D11RasterizerState> state;
  457. inline SavedRasterState(const RasterState &val)
  458. : RasterState (val)
  459. {
  460. }
  461. };
  462. struct mat4float {
  463. float mat[16];
  464. };
  465. struct gs_device {
  466. ComPtr<IDXGIFactory1> factory;
  467. ComPtr<ID3D11Device> device;
  468. ComPtr<ID3D11DeviceContext> context;
  469. gs_swap_chain defaultSwap;
  470. gs_texture_2d *curRenderTarget;
  471. gs_zstencil_buffer *curZStencilBuffer;
  472. int curRenderSide;
  473. gs_texture *curTextures[GS_MAX_TEXTURES];
  474. gs_sampler_state *curSamplers[GS_MAX_TEXTURES];
  475. gs_vertex_buffer *curVertexBuffer;
  476. gs_index_buffer *curIndexBuffer;
  477. gs_vertex_shader *curVertexShader;
  478. gs_pixel_shader *curPixelShader;
  479. gs_swap_chain *curSwapChain;
  480. bool zstencilStateChanged;
  481. bool rasterStateChanged;
  482. bool blendStateChanged;
  483. ZStencilState zstencilState;
  484. RasterState rasterState;
  485. BlendState blendState;
  486. vector<SavedZStencilState> zstencilStates;
  487. vector<SavedRasterState> rasterStates;
  488. vector<SavedBlendState> blendStates;
  489. ID3D11DepthStencilState *curDepthStencilState;
  490. ID3D11RasterizerState *curRasterState;
  491. ID3D11BlendState *curBlendState;
  492. D3D11_PRIMITIVE_TOPOLOGY curToplogy;
  493. gs_rect viewport;
  494. vector<mat4float> projStack;
  495. matrix4 curProjMatrix;
  496. matrix4 curViewMatrix;
  497. matrix4 curViewProjMatrix;
  498. void InitFactory(uint32_t adapterIdx, IDXGIAdapter1 **adapter);
  499. void InitDevice(gs_init_data *data, IDXGIAdapter *adapter);
  500. ID3D11DepthStencilState *AddZStencilState();
  501. ID3D11RasterizerState *AddRasterState();
  502. ID3D11BlendState *AddBlendState();
  503. void UpdateZStencilState();
  504. void UpdateRasterState();
  505. void UpdateBlendState();
  506. inline void CopyTex(ID3D11Texture2D *dst, uint32_t dst_x, uint32_t dst_y,
  507. texture_t src, uint32_t src_x, uint32_t src_y,
  508. uint32_t src_w, uint32_t src_h);
  509. void UpdateViewProjMatrix();
  510. gs_device(gs_init_data *data);
  511. };