GS_D3D11SubSystem.hpp 17 KB

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