GS_D3D11SubSystem.hpp 17 KB

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