d3d11-capture.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. #include <d3d11.h>
  2. #include <dxgi.h>
  3. #include "dxgi-helpers.hpp"
  4. #include "graphics-hook.h"
  5. #include "../funchook.h"
  6. struct d3d11_data {
  7. ID3D11Device *device; /* do not release */
  8. ID3D11DeviceContext *context; /* do not release */
  9. uint32_t base_cx;
  10. uint32_t base_cy;
  11. uint32_t cx;
  12. uint32_t cy;
  13. DXGI_FORMAT format;
  14. bool using_shtex;
  15. bool using_scale;
  16. bool multisampled;
  17. ID3D11Texture2D *scale_tex;
  18. ID3D11ShaderResourceView *scale_resource;
  19. ID3D11VertexShader *vertex_shader;
  20. ID3D11InputLayout *vertex_layout;
  21. ID3D11PixelShader *pixel_shader;
  22. ID3D11SamplerState *sampler_state;
  23. ID3D11BlendState *blend_state;
  24. ID3D11DepthStencilState *zstencil_state;
  25. ID3D11RasterizerState *raster_state;
  26. ID3D11Buffer *vertex_buffer;
  27. union {
  28. /* shared texture */
  29. struct {
  30. struct shtex_data *shtex_info;
  31. ID3D11Texture2D *texture;
  32. ID3D11RenderTargetView *render_target;
  33. HANDLE handle;
  34. };
  35. /* shared memory */
  36. struct {
  37. ID3D11Texture2D *copy_surfaces[NUM_BUFFERS];
  38. ID3D11Texture2D *textures[NUM_BUFFERS];
  39. ID3D11RenderTargetView *render_targets[NUM_BUFFERS];
  40. bool texture_ready[NUM_BUFFERS];
  41. bool texture_mapped[NUM_BUFFERS];
  42. uint32_t pitch;
  43. struct shmem_data *shmem_info;
  44. int cur_tex;
  45. int copy_wait;
  46. };
  47. };
  48. };
  49. static struct d3d11_data data = {};
  50. void d3d11_free(void)
  51. {
  52. if (data.scale_tex)
  53. data.scale_tex->Release();
  54. if (data.scale_resource)
  55. data.scale_resource->Release();
  56. if (data.vertex_shader)
  57. data.vertex_shader->Release();
  58. if (data.vertex_layout)
  59. data.vertex_layout->Release();
  60. if (data.pixel_shader)
  61. data.pixel_shader->Release();
  62. if (data.sampler_state)
  63. data.sampler_state->Release();
  64. if (data.blend_state)
  65. data.blend_state->Release();
  66. if (data.zstencil_state)
  67. data.zstencil_state->Release();
  68. if (data.raster_state)
  69. data.raster_state->Release();
  70. if (data.vertex_buffer)
  71. data.vertex_buffer->Release();
  72. capture_free();
  73. if (data.using_shtex) {
  74. if (data.texture)
  75. data.texture->Release();
  76. if (data.render_target)
  77. data.render_target->Release();
  78. } else {
  79. for (size_t i = 0; i < NUM_BUFFERS; i++) {
  80. if (data.copy_surfaces[i]) {
  81. if (data.texture_mapped[i])
  82. data.context->Unmap(
  83. data.copy_surfaces[i],
  84. 0);
  85. data.copy_surfaces[i]->Release();
  86. }
  87. if (data.textures[i])
  88. data.textures[i]->Release();
  89. if (data.render_targets[i])
  90. data.render_targets[i]->Release();
  91. }
  92. }
  93. memset(&data, 0, sizeof(data));
  94. hlog("----------------- d3d11 capture freed ----------------");
  95. }
  96. static bool create_d3d11_stage_surface(ID3D11Texture2D **tex)
  97. {
  98. HRESULT hr;
  99. D3D11_TEXTURE2D_DESC desc = {};
  100. desc.Width = data.cx;
  101. desc.Height = data.cy;
  102. desc.Format = data.format;
  103. desc.MipLevels = 1;
  104. desc.ArraySize = 1;
  105. desc.SampleDesc.Count = 1;
  106. desc.Usage = D3D11_USAGE_STAGING;
  107. desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  108. hr = data.device->CreateTexture2D(&desc, nullptr, tex);
  109. if (FAILED(hr)) {
  110. hlog_hr("create_d3d11_stage_surface: failed to create texture",
  111. hr);
  112. return false;
  113. }
  114. return true;
  115. }
  116. static bool create_d3d11_tex(uint32_t cx, uint32_t cy,
  117. ID3D11Texture2D **tex,
  118. ID3D11ShaderResourceView **resource,
  119. ID3D11RenderTargetView **render_target,
  120. HANDLE *handle)
  121. {
  122. UINT flags = 0;
  123. UINT misc_flags = 0;
  124. HRESULT hr;
  125. if (!!resource)
  126. flags |= D3D11_BIND_SHADER_RESOURCE;
  127. if (!!render_target)
  128. flags |= D3D11_BIND_RENDER_TARGET;
  129. if (!!handle)
  130. misc_flags |= D3D11_RESOURCE_MISC_SHARED;
  131. D3D11_TEXTURE2D_DESC desc = {};
  132. desc.Width = cx;
  133. desc.Height = cy;
  134. desc.MipLevels = 1;
  135. desc.ArraySize = 1;
  136. desc.Format = data.format;
  137. desc.BindFlags = flags;
  138. desc.SampleDesc.Count = 1;
  139. desc.Usage = D3D11_USAGE_DEFAULT;
  140. desc.MiscFlags = misc_flags;
  141. hr = data.device->CreateTexture2D(&desc, nullptr, tex);
  142. if (FAILED(hr)) {
  143. hlog_hr("create_d3d11_tex: failed to create texture", hr);
  144. return false;
  145. }
  146. if (!!resource) {
  147. D3D11_SHADER_RESOURCE_VIEW_DESC res_desc = {};
  148. res_desc.Format = data.format;
  149. res_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
  150. res_desc.Texture2D.MipLevels = 1;
  151. hr = data.device->CreateShaderResourceView(*tex, &res_desc,
  152. resource);
  153. if (FAILED(hr)) {
  154. hlog_hr("create_d3d11_tex: failed to create resource "
  155. "view", hr);
  156. return false;
  157. }
  158. }
  159. if (!!render_target) {
  160. hr = data.device->CreateRenderTargetView(*tex, nullptr,
  161. render_target);
  162. if (FAILED(hr)) {
  163. hlog_hr("create_d3d11_tex: failed to create render "
  164. "target view", hr);
  165. return false;
  166. }
  167. }
  168. if (!!handle) {
  169. IDXGIResource *dxgi_res;
  170. hr = (*tex)->QueryInterface(__uuidof(IDXGIResource),
  171. (void**)&dxgi_res);
  172. if (FAILED(hr)) {
  173. hlog_hr("create_d3d11_tex: failed to query "
  174. "IDXGIResource interface from texture", hr);
  175. return false;
  176. }
  177. hr = dxgi_res->GetSharedHandle(handle);
  178. dxgi_res->Release();
  179. if (FAILED(hr)) {
  180. hlog_hr("create_d3d11_tex: failed to get shared handle",
  181. hr);
  182. return false;
  183. }
  184. }
  185. return true;
  186. }
  187. static inline bool d3d11_init_format(IDXGISwapChain *swap, HWND &window)
  188. {
  189. DXGI_SWAP_CHAIN_DESC desc;
  190. HRESULT hr;
  191. hr = swap->GetDesc(&desc);
  192. if (FAILED(hr)) {
  193. hlog_hr("d3d11_init_format: swap->GetDesc failed", hr);
  194. return false;
  195. }
  196. data.format = fix_dxgi_format(desc.BufferDesc.Format);
  197. data.multisampled = desc.SampleDesc.Count > 1;
  198. window = desc.OutputWindow;
  199. data.base_cx = desc.BufferDesc.Width;
  200. data.base_cy = desc.BufferDesc.Height;
  201. if (data.using_scale) {
  202. data.cx = global_hook_info->cx;
  203. data.cy = global_hook_info->cy;
  204. } else {
  205. data.cx = desc.BufferDesc.Width;
  206. data.cy = desc.BufferDesc.Height;
  207. }
  208. return true;
  209. }
  210. static inline bool d3d11_init_vertex_shader(void)
  211. {
  212. D3D11_INPUT_ELEMENT_DESC desc[2];
  213. uint8_t *vs_data;
  214. size_t size;
  215. HRESULT hr;
  216. vs_data = get_d3d1x_vertex_shader(&size);
  217. hr = data.device->CreateVertexShader(vs_data, size, nullptr,
  218. &data.vertex_shader);
  219. if (FAILED(hr)) {
  220. hlog_hr("d3d11_init_vertex_shader: failed to create shader",
  221. hr);
  222. return false;
  223. }
  224. desc[0].SemanticName = "SV_Position";
  225. desc[0].SemanticIndex = 0;
  226. desc[0].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
  227. desc[0].InputSlot = 0;
  228. desc[0].AlignedByteOffset = 0;
  229. desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
  230. desc[0].InstanceDataStepRate = 0;
  231. desc[1].SemanticName = "TEXCOORD";
  232. desc[1].SemanticIndex = 0;
  233. desc[1].Format = DXGI_FORMAT_R32G32_FLOAT;
  234. desc[1].InputSlot = 0;
  235. desc[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
  236. desc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
  237. desc[1].InstanceDataStepRate = 0;
  238. hr = data.device->CreateInputLayout(desc, 2, vs_data, size,
  239. &data.vertex_layout);
  240. if (FAILED(hr)) {
  241. hlog_hr("d3d11_init_vertex_shader: failed to create layout",
  242. hr);
  243. return false;
  244. }
  245. return true;
  246. }
  247. static inline bool d3d11_init_pixel_shader(void)
  248. {
  249. uint8_t *ps_data;
  250. size_t size;
  251. HRESULT hr;
  252. ps_data = get_d3d1x_pixel_shader(&size);
  253. hr = data.device->CreatePixelShader(ps_data, size, nullptr,
  254. &data.pixel_shader);
  255. if (FAILED(hr)) {
  256. hlog_hr("d3d11_init_pixel_shader: failed to create shader", hr);
  257. return false;
  258. }
  259. return true;
  260. }
  261. static inline bool d3d11_init_sampler_state(void)
  262. {
  263. HRESULT hr;
  264. D3D11_SAMPLER_DESC desc = {};
  265. desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  266. desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
  267. desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
  268. desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
  269. hr = data.device->CreateSamplerState(&desc, &data.sampler_state);
  270. if (FAILED(hr)) {
  271. hlog_hr("d3d11_init_sampler_state: failed to create sampler "
  272. "state", hr);
  273. return false;
  274. }
  275. return true;
  276. }
  277. static inline bool d3d11_init_blend_state(void)
  278. {
  279. D3D11_BLEND_DESC desc = {};
  280. HRESULT hr;
  281. for (size_t i = 0; i < 8; i++)
  282. desc.RenderTarget[i].RenderTargetWriteMask =
  283. D3D11_COLOR_WRITE_ENABLE_ALL;
  284. hr = data.device->CreateBlendState(&desc, &data.blend_state);
  285. if (FAILED(hr)) {
  286. hlog_hr("d3d11_init_blend_state: failed to create blend state",
  287. hr);
  288. return false;
  289. }
  290. return true;
  291. }
  292. static inline bool d3d11_init_zstencil_state(void)
  293. {
  294. D3D11_DEPTH_STENCIL_DESC desc = {}; /* defaults all to off */
  295. HRESULT hr;
  296. hr = data.device->CreateDepthStencilState(&desc, &data.zstencil_state);
  297. if (FAILED(hr)) {
  298. hlog_hr("d3d11_init_zstencil_state: failed to create "
  299. "zstencil state", hr);
  300. return false;
  301. }
  302. return true;
  303. }
  304. static inline bool d3d11_init_raster_state(void)
  305. {
  306. D3D11_RASTERIZER_DESC desc = {};
  307. HRESULT hr;
  308. desc.FillMode = D3D11_FILL_SOLID;
  309. desc.CullMode = D3D11_CULL_NONE;
  310. hr = data.device->CreateRasterizerState(&desc, &data.raster_state);
  311. if (FAILED(hr)) {
  312. hlog_hr("d3d11_init_raster_state: failed to create raster "
  313. "state", hr);
  314. return false;
  315. }
  316. return true;
  317. }
  318. #define NUM_VERTS 4
  319. static inline bool d3d11_init_vertex_buffer(void)
  320. {
  321. HRESULT hr;
  322. const vertex verts[NUM_VERTS] = {
  323. {{-1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
  324. {{-1.0f, -1.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
  325. {{ 1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
  326. {{ 1.0f, -1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}
  327. };
  328. D3D11_BUFFER_DESC desc;
  329. desc.ByteWidth = sizeof(vertex) * NUM_VERTS;
  330. desc.Usage = D3D11_USAGE_DEFAULT;
  331. desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  332. desc.CPUAccessFlags = 0;
  333. desc.MiscFlags = 0;
  334. D3D11_SUBRESOURCE_DATA srd = {};
  335. srd.pSysMem = (const void*)verts;
  336. hr = data.device->CreateBuffer(&desc, &srd, &data.vertex_buffer);
  337. if (FAILED(hr)) {
  338. hlog_hr("d3d11_init_vertex_buffer: failed to create vertex "
  339. "buffer", hr);
  340. return false;
  341. }
  342. return true;
  343. }
  344. static bool d3d11_init_scaling(void)
  345. {
  346. bool success;
  347. success = create_d3d11_tex(data.base_cx, data.base_cy,
  348. &data.scale_tex, &data.scale_resource, nullptr,
  349. nullptr);
  350. if (!success) {
  351. hlog("d3d11_init_scaling: failed to create scale texture");
  352. return false;
  353. }
  354. if (!d3d11_init_vertex_shader()) {
  355. return false;
  356. }
  357. if (!d3d11_init_pixel_shader()) {
  358. return false;
  359. }
  360. if (!d3d11_init_sampler_state()) {
  361. return false;
  362. }
  363. if (!d3d11_init_blend_state()) {
  364. return false;
  365. }
  366. if (!d3d11_init_zstencil_state()) {
  367. return false;
  368. }
  369. if (!d3d11_init_raster_state()) {
  370. return false;
  371. }
  372. if (!d3d11_init_vertex_buffer()) {
  373. return false;
  374. }
  375. return true;
  376. }
  377. static bool d3d11_shmem_init_buffers(size_t idx)
  378. {
  379. bool success;
  380. success = create_d3d11_stage_surface(&data.copy_surfaces[idx]);
  381. if (!success) {
  382. hlog("d3d11_shmem_init_buffers: failed to create copy surface");
  383. return false;
  384. }
  385. if (idx == 0) {
  386. D3D11_MAPPED_SUBRESOURCE map = {};
  387. HRESULT hr;
  388. hr = data.context->Map(data.copy_surfaces[idx], 0,
  389. D3D11_MAP_READ, 0, &map);
  390. if (FAILED(hr)) {
  391. hlog_hr("d3d11_shmem_init_buffers: failed to get "
  392. "pitch", hr);
  393. return false;
  394. }
  395. data.pitch = map.RowPitch;
  396. data.context->Unmap(data.copy_surfaces[idx], 0);
  397. }
  398. success = create_d3d11_tex(data.cx, data.cy, &data.textures[idx],
  399. nullptr, &data.render_targets[idx], nullptr);
  400. if (!success) {
  401. hlog("d3d11_shmem_init_buffers: failed to create texture");
  402. return false;
  403. }
  404. return true;
  405. }
  406. static bool d3d11_shmem_init(HWND window)
  407. {
  408. data.using_shtex = false;
  409. for (size_t i = 0; i < NUM_BUFFERS; i++) {
  410. if (!d3d11_shmem_init_buffers(i)) {
  411. return false;
  412. }
  413. }
  414. if (!capture_init_shmem(&data.shmem_info, window,
  415. data.base_cx, data.base_cy, data.cx, data.cy,
  416. data.pitch, data.format, false)) {
  417. return false;
  418. }
  419. hlog("d3d11 memory capture successful");
  420. return true;
  421. }
  422. static bool d3d11_shtex_init(HWND window)
  423. {
  424. ID3D11ShaderResourceView *resource = nullptr;
  425. bool success;
  426. data.using_shtex = true;
  427. success = create_d3d11_tex(data.cx, data.cy, &data.texture, &resource,
  428. &data.render_target, &data.handle);
  429. if (resource)
  430. resource->Release();
  431. if (!success) {
  432. hlog("d3d11_shtex_init: failed to create texture");
  433. return false;
  434. }
  435. if (!capture_init_shtex(&data.shtex_info, window,
  436. data.base_cx, data.base_cy, data.cx, data.cy,
  437. data.format, false, (uintptr_t)data.handle)) {
  438. return false;
  439. }
  440. hlog("d3d11 shared texture capture successful");
  441. return true;
  442. }
  443. static void d3d11_init(IDXGISwapChain *swap)
  444. {
  445. bool success = true;
  446. HWND window;
  447. HRESULT hr;
  448. data.using_scale = global_hook_info->use_scale;
  449. hr = swap->GetDevice(__uuidof(ID3D11Device), (void**)&data.device);
  450. if (FAILED(hr)) {
  451. hlog_hr("d3d11_init: failed to get device from swap", hr);
  452. return;
  453. }
  454. data.device->Release();
  455. data.device->GetImmediateContext(&data.context);
  456. data.context->Release();
  457. if (!d3d11_init_format(swap, window)) {
  458. return;
  459. }
  460. if (data.using_scale && !d3d11_init_scaling()) {
  461. hlog("d3d11_init: failed to initialize scaling");
  462. success = false;
  463. }
  464. if (success) {
  465. if (global_hook_info->force_shmem) {
  466. success = d3d11_shmem_init(window);
  467. } else {
  468. success = d3d11_shtex_init(window);
  469. }
  470. }
  471. if (!success)
  472. d3d11_free();
  473. }
  474. #define MAX_RENDER_TARGETS D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT
  475. #define MAX_SO_TARGETS 4
  476. #define MAX_CLASS_INSTS 256
  477. struct d3d11_state {
  478. ID3D11GeometryShader *geom_shader;
  479. ID3D11InputLayout *vertex_layout;
  480. D3D11_PRIMITIVE_TOPOLOGY topology;
  481. ID3D11Buffer *vertex_buffer;
  482. UINT vb_stride;
  483. UINT vb_offset;
  484. ID3D11BlendState *blend_state;
  485. float blend_factor[4];
  486. UINT sample_mask;
  487. ID3D11DepthStencilState *zstencil_state;
  488. UINT zstencil_ref;
  489. ID3D11RenderTargetView *render_targets[MAX_RENDER_TARGETS];
  490. ID3D11DepthStencilView *zstencil_view;
  491. ID3D11SamplerState *sampler_state;
  492. ID3D11PixelShader *pixel_shader;
  493. ID3D11ShaderResourceView *resource;
  494. ID3D11RasterizerState *raster_state;
  495. UINT num_viewports;
  496. D3D11_VIEWPORT *viewports;
  497. ID3D11Buffer *stream_output_targets[MAX_SO_TARGETS];
  498. ID3D11VertexShader *vertex_shader;
  499. ID3D11ClassInstance *gs_class_instances[MAX_CLASS_INSTS];
  500. ID3D11ClassInstance *ps_class_instances[MAX_CLASS_INSTS];
  501. ID3D11ClassInstance *vs_class_instances[MAX_CLASS_INSTS];
  502. UINT gs_class_inst_count;
  503. UINT ps_class_inst_count;
  504. UINT vs_class_inst_count;
  505. };
  506. static inline void d3d11_save_state(struct d3d11_state *state)
  507. {
  508. state->gs_class_inst_count = MAX_CLASS_INSTS;
  509. state->ps_class_inst_count = MAX_CLASS_INSTS;
  510. state->vs_class_inst_count = MAX_CLASS_INSTS;
  511. data.context->GSGetShader(&state->geom_shader,
  512. state->gs_class_instances,
  513. &state->gs_class_inst_count);
  514. data.context->IAGetInputLayout(&state->vertex_layout);
  515. data.context->IAGetPrimitiveTopology(&state->topology);
  516. data.context->IAGetVertexBuffers(0, 1, &state->vertex_buffer,
  517. &state->vb_stride, &state->vb_offset);
  518. data.context->OMGetBlendState(&state->blend_state, state->blend_factor,
  519. &state->sample_mask);
  520. data.context->OMGetDepthStencilState(&state->zstencil_state,
  521. &state->zstencil_ref);
  522. data.context->OMGetRenderTargets(MAX_RENDER_TARGETS,
  523. state->render_targets, &state->zstencil_view);
  524. data.context->PSGetSamplers(0, 1, &state->sampler_state);
  525. data.context->PSGetShader(&state->pixel_shader,
  526. state->ps_class_instances,
  527. &state->ps_class_inst_count);
  528. data.context->PSGetShaderResources(0, 1, &state->resource);
  529. data.context->RSGetState(&state->raster_state);
  530. data.context->RSGetViewports(&state->num_viewports, nullptr);
  531. if (state->num_viewports) {
  532. state->viewports = (D3D11_VIEWPORT*)malloc(
  533. sizeof(D3D11_VIEWPORT) * state->num_viewports);
  534. data.context->RSGetViewports(&state->num_viewports,
  535. state->viewports);
  536. }
  537. data.context->SOGetTargets(MAX_SO_TARGETS,
  538. state->stream_output_targets);
  539. data.context->VSGetShader(&state->vertex_shader,
  540. state->vs_class_instances,
  541. &state->vs_class_inst_count);
  542. }
  543. static inline void safe_release(IUnknown *p)
  544. {
  545. if (p) p->Release();
  546. }
  547. #define SO_APPEND ((UINT)-1)
  548. static inline void d3d11_restore_state(struct d3d11_state *state)
  549. {
  550. UINT so_offsets[MAX_SO_TARGETS] =
  551. {SO_APPEND, SO_APPEND, SO_APPEND, SO_APPEND};
  552. data.context->GSSetShader(state->geom_shader,
  553. state->gs_class_instances,
  554. state->gs_class_inst_count);
  555. data.context->IASetInputLayout(state->vertex_layout);
  556. data.context->IASetPrimitiveTopology(state->topology);
  557. data.context->IASetVertexBuffers(0, 1, &state->vertex_buffer,
  558. &state->vb_stride, &state->vb_offset);
  559. data.context->OMSetBlendState(state->blend_state, state->blend_factor,
  560. state->sample_mask);
  561. data.context->OMSetDepthStencilState(state->zstencil_state,
  562. state->zstencil_ref);
  563. data.context->OMSetRenderTargets(MAX_RENDER_TARGETS,
  564. state->render_targets,
  565. state->zstencil_view);
  566. data.context->PSSetSamplers(0, 1, &state->sampler_state);
  567. data.context->PSSetShader(state->pixel_shader,
  568. state->ps_class_instances,
  569. state->ps_class_inst_count);
  570. data.context->PSSetShaderResources(0, 1, &state->resource);
  571. data.context->RSSetState(state->raster_state);
  572. data.context->RSSetViewports(state->num_viewports, state->viewports);
  573. data.context->SOSetTargets(MAX_SO_TARGETS,
  574. state->stream_output_targets, so_offsets);
  575. data.context->VSSetShader(state->vertex_shader,
  576. state->vs_class_instances,
  577. state->vs_class_inst_count);
  578. safe_release(state->geom_shader);
  579. safe_release(state->vertex_layout);
  580. safe_release(state->vertex_buffer);
  581. safe_release(state->blend_state);
  582. safe_release(state->zstencil_state);
  583. for (size_t i = 0; i < MAX_RENDER_TARGETS; i++)
  584. safe_release(state->render_targets[i]);
  585. safe_release(state->zstencil_view);
  586. safe_release(state->sampler_state);
  587. safe_release(state->pixel_shader);
  588. safe_release(state->resource);
  589. safe_release(state->raster_state);
  590. for (size_t i = 0; i < MAX_SO_TARGETS; i++)
  591. safe_release(state->stream_output_targets[i]);
  592. safe_release(state->vertex_shader);
  593. for (size_t i = 0; i < state->gs_class_inst_count; i++)
  594. state->gs_class_instances[i]->Release();
  595. for (size_t i = 0; i < state->ps_class_inst_count; i++)
  596. state->ps_class_instances[i]->Release();
  597. for (size_t i = 0; i < state->vs_class_inst_count; i++)
  598. state->vs_class_instances[i]->Release();
  599. free(state->viewports);
  600. memset(state, 0, sizeof(*state));
  601. }
  602. static inline void d3d11_setup_pipeline(ID3D11RenderTargetView *target,
  603. ID3D11ShaderResourceView *resource)
  604. {
  605. const float factor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
  606. D3D11_VIEWPORT viewport = {0};
  607. UINT stride = sizeof(vertex);
  608. void *emptyptr = nullptr;
  609. UINT zero = 0;
  610. viewport.Width = (float)data.cx;
  611. viewport.Height = (float)data.cy;
  612. viewport.MaxDepth = 1.0f;
  613. data.context->GSSetShader(nullptr, nullptr, 0);
  614. data.context->IASetInputLayout(data.vertex_layout);
  615. data.context->IASetPrimitiveTopology(
  616. D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
  617. data.context->IASetVertexBuffers(0, 1, &data.vertex_buffer, &stride,
  618. &zero);
  619. data.context->OMSetBlendState(data.blend_state, factor, 0xFFFFFFFF);
  620. data.context->OMSetDepthStencilState(data.zstencil_state, 0);
  621. data.context->OMSetRenderTargets(1, &target, nullptr);
  622. data.context->PSSetSamplers(0, 1, &data.sampler_state);
  623. data.context->PSSetShader(data.pixel_shader, nullptr, 0);
  624. data.context->PSSetShaderResources(0, 1, &resource);
  625. data.context->RSSetState(data.raster_state);
  626. data.context->RSSetViewports(1, &viewport);
  627. data.context->SOSetTargets(1, (ID3D11Buffer**)&emptyptr, &zero);
  628. data.context->VSSetShader(data.vertex_shader, nullptr, 0);
  629. }
  630. static inline void d3d11_scale_texture(ID3D11RenderTargetView *target,
  631. ID3D11ShaderResourceView *resource)
  632. {
  633. static struct d3d11_state old_state = {0};
  634. d3d11_save_state(&old_state);
  635. d3d11_setup_pipeline(target, resource);
  636. data.context->Draw(4, 0);
  637. d3d11_restore_state(&old_state);
  638. }
  639. static inline void d3d11_copy_texture(ID3D11Resource *dst, ID3D11Resource *src)
  640. {
  641. if (data.multisampled) {
  642. data.context->ResolveSubresource(dst, 0, src, 0, data.format);
  643. } else {
  644. data.context->CopyResource(dst, src);
  645. }
  646. }
  647. static inline void d3d11_shtex_capture(ID3D11Resource *backbuffer)
  648. {
  649. if (data.using_scale) {
  650. d3d11_copy_texture(data.scale_tex, backbuffer);
  651. d3d11_scale_texture(data.render_target, data.scale_resource);
  652. } else {
  653. d3d11_copy_texture(data.texture, backbuffer);
  654. }
  655. }
  656. static inline void d3d11_shmem_queue_copy()
  657. {
  658. for (size_t i = 0; i < NUM_BUFFERS; i++) {
  659. D3D11_MAPPED_SUBRESOURCE map;
  660. HRESULT hr;
  661. if (data.texture_ready[i]) {
  662. data.texture_ready[i] = false;
  663. hr = data.context->Map(data.copy_surfaces[i], 0,
  664. D3D11_MAP_READ, 0, &map);
  665. if (SUCCEEDED(hr)) {
  666. data.texture_mapped[i] = true;
  667. shmem_copy_data(i, map.pData);
  668. }
  669. break;
  670. }
  671. }
  672. }
  673. static inline void d3d11_shmem_capture(ID3D11Resource *backbuffer)
  674. {
  675. int next_tex;
  676. d3d11_shmem_queue_copy();
  677. next_tex = (data.cur_tex == NUM_BUFFERS - 1) ? 0 : data.cur_tex + 1;
  678. if (data.using_scale) {
  679. d3d11_copy_texture(data.scale_tex, backbuffer);
  680. d3d11_scale_texture(data.render_targets[data.cur_tex],
  681. data.scale_resource);
  682. } else {
  683. d3d11_copy_texture(data.textures[data.cur_tex], backbuffer);
  684. }
  685. if (data.copy_wait < NUM_BUFFERS - 1) {
  686. data.copy_wait++;
  687. } else {
  688. ID3D11Texture2D *src = data.textures[next_tex];
  689. ID3D11Texture2D *dst = data.copy_surfaces[next_tex];
  690. if (shmem_texture_data_lock(next_tex)) {
  691. data.context->Unmap(dst, 0);
  692. data.texture_mapped[next_tex] = false;
  693. shmem_texture_data_unlock(next_tex);
  694. }
  695. d3d11_copy_texture(dst, src);
  696. data.texture_ready[next_tex] = true;
  697. }
  698. data.cur_tex = next_tex;
  699. }
  700. void d3d11_capture(void *swap_ptr, void *backbuffer_ptr, bool)
  701. {
  702. IDXGIResource *dxgi_backbuffer = (IDXGIResource*)backbuffer_ptr;
  703. IDXGISwapChain *swap = (IDXGISwapChain*)swap_ptr;
  704. HRESULT hr;
  705. if (capture_should_stop()) {
  706. d3d11_free();
  707. }
  708. if (capture_should_init()) {
  709. d3d11_init(swap);
  710. }
  711. if (capture_ready()) {
  712. ID3D11Resource *backbuffer;
  713. hr = dxgi_backbuffer->QueryInterface(__uuidof(ID3D11Resource),
  714. (void**)&backbuffer);
  715. if (FAILED(hr)) {
  716. hlog_hr("d3d11_shtex_capture: failed to get "
  717. "backbuffer", hr);
  718. return;
  719. }
  720. if (data.using_shtex)
  721. d3d11_shtex_capture(backbuffer);
  722. else
  723. d3d11_shmem_capture(backbuffer);
  724. backbuffer->Release();
  725. }
  726. }