d3d11-subsystem.cpp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883
  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. #include <util/base.h>
  15. #include <util/platform.h>
  16. #include <graphics/matrix3.h>
  17. #include "d3d11-subsystem.hpp"
  18. struct UnsupportedHWError : HRError {
  19. inline UnsupportedHWError(const char *str, HRESULT hr)
  20. : HRError(str, hr)
  21. {
  22. }
  23. };
  24. #ifdef _MSC_VER
  25. /* alignment warning - despite the fact that alignment is already fixed */
  26. #pragma warning (disable : 4316)
  27. #endif
  28. static const IID dxgiFactory2 =
  29. {0x50c83a1c, 0xe072, 0x4c48, {0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0}};
  30. static inline void make_swap_desc(DXGI_SWAP_CHAIN_DESC &desc,
  31. const gs_init_data *data)
  32. {
  33. memset(&desc, 0, sizeof(desc));
  34. desc.BufferCount = data->num_backbuffers;
  35. desc.BufferDesc.Format = ConvertGSTextureFormat(data->format);
  36. desc.BufferDesc.Width = data->cx;
  37. desc.BufferDesc.Height = data->cy;
  38. desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  39. desc.OutputWindow = (HWND)data->window.hwnd;
  40. desc.SampleDesc.Count = 1;
  41. desc.Windowed = true;
  42. }
  43. void gs_swap_chain::InitTarget(uint32_t cx, uint32_t cy)
  44. {
  45. HRESULT hr;
  46. target.width = cx;
  47. target.height = cy;
  48. hr = swap->GetBuffer(0, __uuidof(ID3D11Texture2D),
  49. (void**)target.texture.Assign());
  50. if (FAILED(hr))
  51. throw HRError("Failed to get swap buffer texture", hr);
  52. hr = device->device->CreateRenderTargetView(target.texture, NULL,
  53. target.renderTarget[0].Assign());
  54. if (FAILED(hr))
  55. throw HRError("Failed to create swap render target view", hr);
  56. }
  57. void gs_swap_chain::InitZStencilBuffer(uint32_t cx, uint32_t cy)
  58. {
  59. zs.width = cx;
  60. zs.height = cy;
  61. if (zs.format != GS_ZS_NONE && cx != 0 && cy != 0) {
  62. zs.InitBuffer();
  63. } else {
  64. zs.texture.Clear();
  65. zs.view.Clear();
  66. }
  67. }
  68. void gs_swap_chain::Resize(uint32_t cx, uint32_t cy)
  69. {
  70. RECT clientRect;
  71. HRESULT hr;
  72. target.texture.Clear();
  73. target.renderTarget[0].Clear();
  74. zs.texture.Clear();
  75. zs.view.Clear();
  76. if (cx == 0 || cy == 0) {
  77. GetClientRect(hwnd, &clientRect);
  78. if (cx == 0) cx = clientRect.right;
  79. if (cy == 0) cy = clientRect.bottom;
  80. }
  81. hr = swap->ResizeBuffers(numBuffers, cx, cy, target.dxgiFormat, 0);
  82. if (FAILED(hr))
  83. throw HRError("Failed to resize swap buffers", hr);
  84. InitTarget(cx, cy);
  85. InitZStencilBuffer(cx, cy);
  86. }
  87. void gs_swap_chain::Init(const gs_init_data *data)
  88. {
  89. target.device = device;
  90. target.isRenderTarget = true;
  91. target.format = data->format;
  92. target.dxgiFormat = ConvertGSTextureFormat(data->format);
  93. InitTarget(data->cx, data->cy);
  94. zs.device = device;
  95. zs.format = data->zsformat;
  96. zs.dxgiFormat = ConvertGSZStencilFormat(data->zsformat);
  97. InitZStencilBuffer(data->cx, data->cy);
  98. }
  99. gs_swap_chain::gs_swap_chain(gs_device *device, const gs_init_data *data)
  100. : device (device),
  101. numBuffers (data->num_backbuffers),
  102. hwnd ((HWND)data->window.hwnd)
  103. {
  104. HRESULT hr;
  105. DXGI_SWAP_CHAIN_DESC swapDesc;
  106. make_swap_desc(swapDesc, data);
  107. hr = device->factory->CreateSwapChain(device->device, &swapDesc,
  108. swap.Assign());
  109. if (FAILED(hr))
  110. throw HRError("Failed to create swap chain", hr);
  111. Init(data);
  112. }
  113. void gs_device::InitCompiler()
  114. {
  115. char d3dcompiler[40] = {};
  116. int ver = 49;
  117. while (ver > 30) {
  118. sprintf_s(d3dcompiler, 40, "D3DCompiler_%02d.dll", ver);
  119. HMODULE module = LoadLibraryA(d3dcompiler);
  120. if (module) {
  121. d3dCompile = (pD3DCompile)GetProcAddress(module,
  122. "D3DCompile");
  123. if (d3dCompile) {
  124. return;
  125. }
  126. FreeLibrary(module);
  127. }
  128. ver--;
  129. }
  130. throw "Could not find any D3DCompiler libraries";
  131. }
  132. void gs_device::InitFactory(uint32_t adapterIdx, IDXGIAdapter1 **padapter)
  133. {
  134. HRESULT hr;
  135. IID factoryIID = (GetWinVer() >= 0x602) ? dxgiFactory2 :
  136. __uuidof(IDXGIFactory1);
  137. hr = CreateDXGIFactory1(factoryIID, (void**)factory.Assign());
  138. if (FAILED(hr))
  139. throw UnsupportedHWError("Failed to create DXGIFactory", hr);
  140. hr = factory->EnumAdapters1(adapterIdx, padapter);
  141. if (FAILED(hr))
  142. throw UnsupportedHWError("Failed to enumerate DXGIAdapter", hr);
  143. }
  144. const static D3D_FEATURE_LEVEL featureLevels[] =
  145. {
  146. D3D_FEATURE_LEVEL_11_0,
  147. D3D_FEATURE_LEVEL_10_1,
  148. D3D_FEATURE_LEVEL_10_0,
  149. D3D_FEATURE_LEVEL_9_3,
  150. };
  151. void gs_device::InitDevice(const gs_init_data *data, IDXGIAdapter *adapter)
  152. {
  153. wstring adapterName;
  154. DXGI_SWAP_CHAIN_DESC swapDesc;
  155. DXGI_ADAPTER_DESC desc;
  156. D3D_FEATURE_LEVEL levelUsed;
  157. HRESULT hr;
  158. make_swap_desc(swapDesc, data);
  159. uint32_t createFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
  160. #ifdef _DEBUG
  161. //createFlags |= D3D11_CREATE_DEVICE_DEBUG;
  162. #endif
  163. adapterName = (adapter->GetDesc(&desc) == S_OK) ? desc.Description :
  164. L"<unknown>";
  165. char *adapterNameUTF8;
  166. os_wcs_to_utf8_ptr(adapterName.c_str(), 0, &adapterNameUTF8);
  167. blog(LOG_INFO, "Loading up D3D11 on adapter %s", adapterNameUTF8);
  168. bfree(adapterNameUTF8);
  169. hr = D3D11CreateDeviceAndSwapChain(adapter, D3D_DRIVER_TYPE_UNKNOWN,
  170. NULL, createFlags, featureLevels,
  171. sizeof(featureLevels) / sizeof(D3D_FEATURE_LEVEL),
  172. D3D11_SDK_VERSION, &swapDesc,
  173. defaultSwap.swap.Assign(), device.Assign(),
  174. &levelUsed, context.Assign());
  175. if (FAILED(hr))
  176. throw UnsupportedHWError("Failed to create device and "
  177. "swap chain", hr);
  178. blog(LOG_INFO, "D3D11 loaded sucessfully, feature level used: %u",
  179. (uint32_t)levelUsed);
  180. defaultSwap.device = this;
  181. defaultSwap.hwnd = (HWND)data->window.hwnd;
  182. defaultSwap.numBuffers = data->num_backbuffers;
  183. defaultSwap.Init(data);
  184. }
  185. static inline void ConvertStencilSide(D3D11_DEPTH_STENCILOP_DESC &desc,
  186. const StencilSide &side)
  187. {
  188. desc.StencilFunc = ConvertGSDepthTest(side.test);
  189. desc.StencilFailOp = ConvertGSStencilOp(side.fail);
  190. desc.StencilDepthFailOp = ConvertGSStencilOp(side.zfail);
  191. desc.StencilPassOp = ConvertGSStencilOp(side.zpass);
  192. }
  193. ID3D11DepthStencilState *gs_device::AddZStencilState()
  194. {
  195. HRESULT hr;
  196. D3D11_DEPTH_STENCIL_DESC dsd;
  197. SavedZStencilState savedState(zstencilState);
  198. ID3D11DepthStencilState *state;
  199. dsd.DepthEnable = zstencilState.depthEnabled;
  200. dsd.DepthFunc = ConvertGSDepthTest(zstencilState.depthFunc);
  201. dsd.DepthWriteMask = zstencilState.depthWriteEnabled ?
  202. D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
  203. dsd.StencilEnable = zstencilState.stencilEnabled;
  204. dsd.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
  205. dsd.StencilWriteMask = zstencilState.stencilWriteEnabled ?
  206. D3D11_DEFAULT_STENCIL_WRITE_MASK : 0;
  207. ConvertStencilSide(dsd.FrontFace, zstencilState.stencilFront);
  208. ConvertStencilSide(dsd.BackFace, zstencilState.stencilBack);
  209. hr = device->CreateDepthStencilState(&dsd, savedState.state.Assign());
  210. if (FAILED(hr))
  211. throw HRError("Failed to create depth stencil state", hr);
  212. state = savedState.state;
  213. zstencilStates.push_back(savedState);
  214. return state;
  215. }
  216. ID3D11RasterizerState *gs_device::AddRasterState()
  217. {
  218. HRESULT hr;
  219. D3D11_RASTERIZER_DESC rd;
  220. SavedRasterState savedState(rasterState);
  221. ID3D11RasterizerState *state;
  222. memset(&rd, 0, sizeof(rd));
  223. /* use CCW to convert to a right-handed coordinate system */
  224. rd.FrontCounterClockwise = true;
  225. rd.FillMode = D3D11_FILL_SOLID;
  226. rd.CullMode = ConvertGSCullMode(rasterState.cullMode);
  227. rd.DepthClipEnable = true;
  228. rd.ScissorEnable = rasterState.scissorEnabled;
  229. hr = device->CreateRasterizerState(&rd, savedState.state.Assign());
  230. if (FAILED(hr))
  231. throw HRError("Failed to create rasterizer state", hr);
  232. state = savedState.state;
  233. rasterStates.push_back(savedState);
  234. return state;
  235. }
  236. ID3D11BlendState *gs_device::AddBlendState()
  237. {
  238. HRESULT hr;
  239. D3D11_BLEND_DESC bd;
  240. SavedBlendState savedState(blendState);
  241. ID3D11BlendState *state;
  242. memset(&bd, 0, sizeof(bd));
  243. for (int i = 0; i < 8; i++) {
  244. bd.RenderTarget[i].BlendEnable = blendState.blendEnabled;
  245. bd.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
  246. bd.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
  247. bd.RenderTarget[i].SrcBlend =
  248. ConvertGSBlendType(blendState.srcFactor);
  249. bd.RenderTarget[i].DestBlend =
  250. ConvertGSBlendType(blendState.destFactor);
  251. bd.RenderTarget[i].SrcBlendAlpha =
  252. bd.RenderTarget[i].SrcBlend;
  253. bd.RenderTarget[i].DestBlendAlpha =
  254. bd.RenderTarget[i].DestBlend;
  255. bd.RenderTarget[i].RenderTargetWriteMask =
  256. D3D11_COLOR_WRITE_ENABLE_ALL;
  257. }
  258. hr = device->CreateBlendState(&bd, savedState.state.Assign());
  259. if (FAILED(hr))
  260. throw HRError("Failed to create disabled blend state", hr);
  261. state = savedState.state;
  262. blendStates.push_back(savedState);
  263. return state;
  264. }
  265. void gs_device::UpdateZStencilState()
  266. {
  267. ID3D11DepthStencilState *state = NULL;
  268. if (!zstencilStateChanged)
  269. return;
  270. for (size_t i = 0; i < zstencilStates.size(); i++) {
  271. SavedZStencilState &s = zstencilStates[i];
  272. if (memcmp(&s, &zstencilState, sizeof(zstencilState)) == 0) {
  273. state = s.state;
  274. break;
  275. }
  276. }
  277. if (!state)
  278. state = AddZStencilState();
  279. if (state != curDepthStencilState) {
  280. context->OMSetDepthStencilState(state, 0);
  281. curDepthStencilState = state;
  282. }
  283. zstencilStateChanged = false;
  284. }
  285. void gs_device::UpdateRasterState()
  286. {
  287. ID3D11RasterizerState *state = NULL;
  288. if (!rasterStateChanged)
  289. return;
  290. for (size_t i = 0; i < rasterStates.size(); i++) {
  291. SavedRasterState &s = rasterStates[i];
  292. if (memcmp(&s, &rasterState, sizeof(rasterState)) == 0) {
  293. state = s.state;
  294. break;
  295. }
  296. }
  297. if (!state)
  298. state = AddRasterState();
  299. if (state != curRasterState) {
  300. context->RSSetState(state);
  301. curRasterState = state;
  302. }
  303. rasterStateChanged = false;
  304. }
  305. void gs_device::UpdateBlendState()
  306. {
  307. ID3D11BlendState *state = NULL;
  308. if (!blendStateChanged)
  309. return;
  310. for (size_t i = 0; i < blendStates.size(); i++) {
  311. SavedBlendState &s = blendStates[i];
  312. if (memcmp(&s, &blendState, sizeof(blendState)) == 0) {
  313. state = s.state;
  314. break;
  315. }
  316. }
  317. if (!state)
  318. state = AddBlendState();
  319. if (state != curBlendState) {
  320. float f[4] = {1.0f, 1.0f, 1.0f, 1.0f};
  321. context->OMSetBlendState(state, f, 0xFFFFFFFF);
  322. curBlendState = state;
  323. }
  324. blendStateChanged = false;
  325. }
  326. void gs_device::UpdateViewProjMatrix()
  327. {
  328. gs_matrix_get(&curViewMatrix);
  329. /* negate Z col of the view matrix for right-handed coordinate system */
  330. curViewMatrix.x.z = -curViewMatrix.x.z;
  331. curViewMatrix.y.z = -curViewMatrix.y.z;
  332. curViewMatrix.z.z = -curViewMatrix.z.z;
  333. curViewMatrix.t.z = -curViewMatrix.t.z;
  334. matrix4_mul(&curViewProjMatrix, &curViewMatrix, &curProjMatrix);
  335. matrix4_transpose(&curViewProjMatrix, &curViewProjMatrix);
  336. if (curVertexShader->viewProj)
  337. gs_shader_set_matrix4(curVertexShader->viewProj,
  338. &curViewProjMatrix);
  339. }
  340. gs_device::gs_device(const gs_init_data *data)
  341. : curRenderTarget (NULL),
  342. curZStencilBuffer (NULL),
  343. curRenderSide (0),
  344. curIndexBuffer (NULL),
  345. curVertexBuffer (NULL),
  346. curVertexShader (NULL),
  347. curPixelShader (NULL),
  348. curSwapChain (&defaultSwap),
  349. zstencilStateChanged (true),
  350. rasterStateChanged (true),
  351. blendStateChanged (true),
  352. curDepthStencilState (NULL),
  353. curRasterState (NULL),
  354. curBlendState (NULL),
  355. curToplogy (D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED)
  356. {
  357. ComPtr<IDXGIAdapter1> adapter;
  358. matrix4_identity(&curProjMatrix);
  359. matrix4_identity(&curViewMatrix);
  360. matrix4_identity(&curViewProjMatrix);
  361. memset(&viewport, 0, sizeof(viewport));
  362. for (size_t i = 0; i < GS_MAX_TEXTURES; i++) {
  363. curTextures[i] = NULL;
  364. curSamplers[i] = NULL;
  365. }
  366. InitCompiler();
  367. InitFactory(data->adapter, adapter.Assign());
  368. InitDevice(data, adapter);
  369. device_set_render_target(this, NULL, NULL);
  370. }
  371. const char *device_get_name(void)
  372. {
  373. return "Direct3D 11";
  374. }
  375. int device_get_type(void)
  376. {
  377. return GS_DEVICE_DIRECT3D_11;
  378. }
  379. const char *device_preprocessor_name(void)
  380. {
  381. return "_D3D11";
  382. }
  383. int device_create(gs_device_t **p_device, const gs_init_data *data)
  384. {
  385. gs_device *device = NULL;
  386. int errorcode = GS_SUCCESS;
  387. try {
  388. device = new gs_device(data);
  389. } catch (UnsupportedHWError error) {
  390. blog(LOG_ERROR, "device_create (D3D11): %s (%08lX)", error.str,
  391. error.hr);
  392. errorcode = GS_ERROR_NOT_SUPPORTED;
  393. } catch (HRError error) {
  394. blog(LOG_ERROR, "device_create (D3D11): %s (%08lX)", error.str,
  395. error.hr);
  396. errorcode = GS_ERROR_FAIL;
  397. }
  398. *p_device = device;
  399. return errorcode;
  400. }
  401. void device_destroy(gs_device_t *device)
  402. {
  403. delete device;
  404. }
  405. void device_enter_context(gs_device_t *device)
  406. {
  407. /* does nothing */
  408. UNUSED_PARAMETER(device);
  409. }
  410. void device_leave_context(gs_device_t *device)
  411. {
  412. /* does nothing */
  413. UNUSED_PARAMETER(device);
  414. }
  415. gs_swapchain_t *device_swapchain_create(gs_device_t *device,
  416. const struct gs_init_data *data)
  417. {
  418. gs_swap_chain *swap = NULL;
  419. try {
  420. swap = new gs_swap_chain(device, data);
  421. } catch (HRError error) {
  422. blog(LOG_ERROR, "device_swapchain_create (D3D11): %s (%08lX)",
  423. error.str, error.hr);
  424. }
  425. return swap;
  426. }
  427. void device_resize(gs_device_t *device, uint32_t cx, uint32_t cy)
  428. {
  429. try {
  430. ID3D11RenderTargetView *renderView = NULL;
  431. ID3D11DepthStencilView *depthView = NULL;
  432. int i = device->curRenderSide;
  433. device->context->OMSetRenderTargets(1, &renderView, depthView);
  434. device->curSwapChain->Resize(cx, cy);
  435. if (device->curRenderTarget)
  436. renderView = device->curRenderTarget->renderTarget[i];
  437. if (device->curZStencilBuffer)
  438. depthView = device->curZStencilBuffer->view;
  439. device->context->OMSetRenderTargets(1, &renderView, depthView);
  440. } catch (HRError error) {
  441. blog(LOG_ERROR, "device_resize (D3D11): %s (%08lX)",
  442. error.str, error.hr);
  443. }
  444. }
  445. void device_get_size(const gs_device_t *device, uint32_t *cx, uint32_t *cy)
  446. {
  447. *cx = device->curSwapChain->target.width;
  448. *cy = device->curSwapChain->target.height;
  449. }
  450. uint32_t device_get_width(const gs_device_t *device)
  451. {
  452. return device->curSwapChain->target.width;
  453. }
  454. uint32_t device_get_height(const gs_device_t *device)
  455. {
  456. return device->curSwapChain->target.height;
  457. }
  458. gs_texture_t *device_texture_create(gs_device_t *device, uint32_t width,
  459. uint32_t height, enum gs_color_format color_format,
  460. uint32_t levels, const uint8_t **data, uint32_t flags)
  461. {
  462. gs_texture *texture = NULL;
  463. try {
  464. texture = new gs_texture_2d(device, width, height, color_format,
  465. levels, data, flags, GS_TEXTURE_2D, false,
  466. false);
  467. } catch (HRError error) {
  468. blog(LOG_ERROR, "device_texture_create (D3D11): %s (%08lX)",
  469. error.str, error.hr);
  470. } catch (const char *error) {
  471. blog(LOG_ERROR, "device_texture_create (D3D11): %s", error);
  472. }
  473. return texture;
  474. }
  475. gs_texture_t *device_cubetexture_create(gs_device_t *device, uint32_t size,
  476. enum gs_color_format color_format, uint32_t levels,
  477. const uint8_t **data, uint32_t flags)
  478. {
  479. gs_texture *texture = NULL;
  480. try {
  481. texture = new gs_texture_2d(device, size, size, color_format,
  482. levels, data, flags, GS_TEXTURE_CUBE, false,
  483. false);
  484. } catch (HRError error) {
  485. blog(LOG_ERROR, "device_cubetexture_create (D3D11): %s "
  486. "(%08lX)",
  487. error.str, error.hr);
  488. } catch (const char *error) {
  489. blog(LOG_ERROR, "device_cubetexture_create (D3D11): %s",
  490. error);
  491. }
  492. return texture;
  493. }
  494. gs_texture_t *device_voltexture_create(gs_device_t *device, uint32_t width,
  495. uint32_t height, uint32_t depth,
  496. enum gs_color_format color_format, uint32_t levels,
  497. const uint8_t **data, uint32_t flags)
  498. {
  499. /* TODO */
  500. UNUSED_PARAMETER(device);
  501. UNUSED_PARAMETER(width);
  502. UNUSED_PARAMETER(height);
  503. UNUSED_PARAMETER(depth);
  504. UNUSED_PARAMETER(color_format);
  505. UNUSED_PARAMETER(levels);
  506. UNUSED_PARAMETER(data);
  507. UNUSED_PARAMETER(flags);
  508. return NULL;
  509. }
  510. gs_zstencil_t *device_zstencil_create(gs_device_t *device, uint32_t width,
  511. uint32_t height, enum gs_zstencil_format format)
  512. {
  513. gs_zstencil_buffer *zstencil = NULL;
  514. try {
  515. zstencil = new gs_zstencil_buffer(device, width, height,
  516. format);
  517. } catch (HRError error) {
  518. blog(LOG_ERROR, "device_zstencil_create (D3D11): %s (%08lX)",
  519. error.str, error.hr);
  520. }
  521. return zstencil;
  522. }
  523. gs_stagesurf_t *device_stagesurface_create(gs_device_t *device, uint32_t width,
  524. uint32_t height, enum gs_color_format color_format)
  525. {
  526. gs_stage_surface *surf = NULL;
  527. try {
  528. surf = new gs_stage_surface(device, width, height,
  529. color_format);
  530. } catch (HRError error) {
  531. blog(LOG_ERROR, "device_stagesurface_create (D3D11): %s "
  532. "(%08lX)",
  533. error.str, error.hr);
  534. }
  535. return surf;
  536. }
  537. gs_samplerstate_t *device_samplerstate_create(gs_device_t *device,
  538. const struct gs_sampler_info *info)
  539. {
  540. gs_sampler_state *ss = NULL;
  541. try {
  542. ss = new gs_sampler_state(device, info);
  543. } catch (HRError error) {
  544. blog(LOG_ERROR, "device_samplerstate_create (D3D11): %s "
  545. "(%08lX)",
  546. error.str, error.hr);
  547. }
  548. return ss;
  549. }
  550. gs_shader_t *device_vertexshader_create(gs_device_t *device,
  551. const char *shader_string, const char *file,
  552. char **error_string)
  553. {
  554. gs_vertex_shader *shader = NULL;
  555. try {
  556. shader = new gs_vertex_shader(device, file, shader_string);
  557. } catch (HRError error) {
  558. blog(LOG_ERROR, "device_vertexshader_create (D3D11): %s "
  559. "(%08lX)",
  560. error.str, error.hr);
  561. } catch (ShaderError error) {
  562. const char *buf = (const char*)error.errors->GetBufferPointer();
  563. if (error_string)
  564. *error_string = bstrdup(buf);
  565. blog(LOG_ERROR, "device_vertexshader_create (D3D11): "
  566. "Compile warnings/errors for %s:\n%s",
  567. file, buf);
  568. } catch (const char *error) {
  569. blog(LOG_ERROR, "device_vertexshader_create (D3D11): %s",
  570. error);
  571. }
  572. return shader;
  573. }
  574. gs_shader_t *device_pixelshader_create(gs_device_t *device,
  575. const char *shader_string, const char *file,
  576. char **error_string)
  577. {
  578. gs_pixel_shader *shader = NULL;
  579. try {
  580. shader = new gs_pixel_shader(device, file, shader_string);
  581. } catch (HRError error) {
  582. blog(LOG_ERROR, "device_pixelshader_create (D3D11): %s "
  583. "(%08lX)",
  584. error.str, error.hr);
  585. } catch (ShaderError error) {
  586. const char *buf = (const char*)error.errors->GetBufferPointer();
  587. if (error_string)
  588. *error_string = bstrdup(buf);
  589. blog(LOG_ERROR, "device_pixelshader_create (D3D11): "
  590. "Compiler warnings/errors for %s:\n%s",
  591. file, buf);
  592. } catch (const char *error) {
  593. blog(LOG_ERROR, "device_pixelshader_create (D3D11): %s",
  594. error);
  595. }
  596. return shader;
  597. }
  598. gs_vertbuffer_t *device_vertexbuffer_create(gs_device_t *device,
  599. struct gs_vb_data *data, uint32_t flags)
  600. {
  601. gs_vertex_buffer *buffer = NULL;
  602. try {
  603. buffer = new gs_vertex_buffer(device, data, flags);
  604. } catch (HRError error) {
  605. blog(LOG_ERROR, "device_vertexbuffer_create (D3D11): %s "
  606. "(%08lX)",
  607. error.str, error.hr);
  608. } catch (const char *error) {
  609. blog(LOG_ERROR, "device_vertexbuffer_create (D3D11): %s",
  610. error);
  611. }
  612. return buffer;
  613. }
  614. gs_indexbuffer_t *device_indexbuffer_create(gs_device_t *device,
  615. enum gs_index_type type, void *indices, size_t num,
  616. uint32_t flags)
  617. {
  618. gs_index_buffer *buffer = NULL;
  619. try {
  620. buffer = new gs_index_buffer(device, type, indices, num, flags);
  621. } catch (HRError error) {
  622. blog(LOG_ERROR, "device_indexbuffer_create (D3D11): %s (%08lX)",
  623. error.str, error.hr);
  624. }
  625. return buffer;
  626. }
  627. enum gs_texture_type device_get_texture_type(const gs_texture_t *texture)
  628. {
  629. return texture->type;
  630. }
  631. void device_load_vertexbuffer(gs_device_t *device, gs_vertbuffer_t *vertbuffer)
  632. {
  633. if (device->curVertexBuffer == vertbuffer)
  634. return;
  635. device->curVertexBuffer = vertbuffer;
  636. if (!device->curVertexShader)
  637. return;
  638. vector<ID3D11Buffer*> buffers;
  639. vector<uint32_t> strides;
  640. vector<uint32_t> offsets;
  641. if (vertbuffer) {
  642. vertbuffer->MakeBufferList(device->curVertexShader,
  643. buffers, strides);
  644. } else {
  645. size_t buffersToClear =
  646. device->curVertexShader->NumBuffersExpected();
  647. buffers.resize(buffersToClear);
  648. strides.resize(buffersToClear);
  649. }
  650. offsets.resize(buffers.size());
  651. device->context->IASetVertexBuffers(0, (UINT)buffers.size(),
  652. buffers.data(), strides.data(), offsets.data());
  653. }
  654. void device_load_indexbuffer(gs_device_t *device, gs_indexbuffer_t *indexbuffer)
  655. {
  656. DXGI_FORMAT format;
  657. ID3D11Buffer *buffer;
  658. if (device->curIndexBuffer == indexbuffer)
  659. return;
  660. if (indexbuffer) {
  661. switch (indexbuffer->indexSize) {
  662. case 2: format = DXGI_FORMAT_R16_UINT; break;
  663. default:
  664. case 4: format = DXGI_FORMAT_R32_UINT; break;
  665. }
  666. buffer = indexbuffer->indexBuffer;
  667. } else {
  668. buffer = NULL;
  669. format = DXGI_FORMAT_R32_UINT;
  670. }
  671. device->curIndexBuffer = indexbuffer;
  672. device->context->IASetIndexBuffer(buffer, format, 0);
  673. }
  674. void device_load_texture(gs_device_t *device, gs_texture_t *tex, int unit)
  675. {
  676. ID3D11ShaderResourceView *view = NULL;
  677. if (device->curTextures[unit] == tex)
  678. return;
  679. if (tex)
  680. view = tex->shaderRes;
  681. device->curTextures[unit] = tex;
  682. device->context->PSSetShaderResources(unit, 1, &view);
  683. }
  684. void device_load_samplerstate(gs_device_t *device,
  685. gs_samplerstate_t *samplerstate, int unit)
  686. {
  687. ID3D11SamplerState *state = NULL;
  688. if (device->curSamplers[unit] == samplerstate)
  689. return;
  690. if (samplerstate)
  691. state = samplerstate->state;
  692. device->curSamplers[unit] = samplerstate;
  693. device->context->PSSetSamplers(unit, 1, &state);
  694. }
  695. void device_load_vertexshader(gs_device_t *device, gs_shader_t *vertshader)
  696. {
  697. ID3D11VertexShader *shader = NULL;
  698. ID3D11InputLayout *layout = NULL;
  699. ID3D11Buffer *constants = NULL;
  700. if (device->curVertexShader == vertshader)
  701. return;
  702. gs_vertex_shader *vs = static_cast<gs_vertex_shader*>(vertshader);
  703. gs_vertex_buffer *curVB = device->curVertexBuffer;
  704. if (vertshader) {
  705. if (vertshader->type != GS_SHADER_VERTEX) {
  706. blog(LOG_ERROR, "device_load_vertexshader (D3D11): "
  707. "Specified shader is not a vertex "
  708. "shader");
  709. return;
  710. }
  711. if (curVB)
  712. device_load_vertexbuffer(device, NULL);
  713. shader = vs->shader;
  714. layout = vs->layout;
  715. constants = vs->constants;
  716. }
  717. device->curVertexShader = vs;
  718. device->context->VSSetShader(shader, NULL, 0);
  719. device->context->IASetInputLayout(layout);
  720. device->context->VSSetConstantBuffers(0, 1, &constants);
  721. if (vertshader && curVB)
  722. device_load_vertexbuffer(device, curVB);
  723. }
  724. static inline void clear_textures(gs_device_t *device)
  725. {
  726. ID3D11ShaderResourceView *views[GS_MAX_TEXTURES];
  727. memset(views, 0, sizeof(views));
  728. memset(device->curTextures, 0, sizeof(device->curTextures));
  729. device->context->PSSetShaderResources(0, GS_MAX_TEXTURES, views);
  730. }
  731. void device_load_pixelshader(gs_device_t *device, gs_shader_t *pixelshader)
  732. {
  733. ID3D11PixelShader *shader = NULL;
  734. ID3D11Buffer *constants = NULL;
  735. ID3D11SamplerState *states[GS_MAX_TEXTURES];
  736. if (device->curPixelShader == pixelshader)
  737. return;
  738. gs_pixel_shader *ps = static_cast<gs_pixel_shader*>(pixelshader);
  739. if (pixelshader) {
  740. if (pixelshader->type != GS_SHADER_PIXEL) {
  741. blog(LOG_ERROR, "device_load_pixelshader (D3D11): "
  742. "Specified shader is not a pixel "
  743. "shader");
  744. return;
  745. }
  746. shader = ps->shader;
  747. constants = ps->constants;
  748. ps->GetSamplerStates(states);
  749. } else {
  750. memset(states, 0, sizeof(states));
  751. }
  752. clear_textures(device);
  753. device->curPixelShader = ps;
  754. device->context->PSSetShader(shader, NULL, 0);
  755. device->context->PSSetConstantBuffers(0, 1, &constants);
  756. device->context->PSSetSamplers(0, GS_MAX_TEXTURES, states);
  757. for (int i = 0; i < GS_MAX_TEXTURES; i++)
  758. if (device->curSamplers[i] &&
  759. device->curSamplers[i]->state != states[i])
  760. device->curSamplers[i] = nullptr;
  761. }
  762. void device_load_default_samplerstate(gs_device_t *device, bool b_3d, int unit)
  763. {
  764. /* TODO */
  765. UNUSED_PARAMETER(device);
  766. UNUSED_PARAMETER(b_3d);
  767. UNUSED_PARAMETER(unit);
  768. }
  769. gs_shader_t *device_get_vertex_shader(const gs_device_t *device)
  770. {
  771. return device->curVertexShader;
  772. }
  773. gs_shader_t *device_get_pixel_shader(const gs_device_t *device)
  774. {
  775. return device->curPixelShader;
  776. }
  777. gs_texture_t *device_get_render_target(const gs_device_t *device)
  778. {
  779. if (device->curRenderTarget == &device->curSwapChain->target)
  780. return NULL;
  781. return device->curRenderTarget;
  782. }
  783. gs_zstencil_t *device_get_zstencil_target(const gs_device_t *device)
  784. {
  785. if (device->curZStencilBuffer == &device->curSwapChain->zs)
  786. return NULL;
  787. return device->curZStencilBuffer;
  788. }
  789. void device_set_render_target(gs_device_t *device, gs_texture_t *tex,
  790. gs_zstencil_t *zstencil)
  791. {
  792. if (!tex)
  793. tex = &device->curSwapChain->target;
  794. if (!zstencil)
  795. zstencil = &device->curSwapChain->zs;
  796. if (device->curRenderTarget == tex &&
  797. device->curZStencilBuffer == zstencil)
  798. return;
  799. if (tex->type != GS_TEXTURE_2D) {
  800. blog(LOG_ERROR, "device_set_render_target (D3D11): "
  801. "texture is not a 2D texture");
  802. return;
  803. }
  804. gs_texture_2d *tex2d = static_cast<gs_texture_2d*>(tex);
  805. if (!tex2d->renderTarget[0]) {
  806. blog(LOG_ERROR, "device_set_render_target (D3D11): "
  807. "texture is not a render target");
  808. return;
  809. }
  810. ID3D11RenderTargetView *rt = tex2d->renderTarget[0];
  811. device->curRenderTarget = tex2d;
  812. device->curRenderSide = 0;
  813. device->curZStencilBuffer = zstencil;
  814. device->context->OMSetRenderTargets(1, &rt, zstencil->view);
  815. }
  816. void device_set_cube_render_target(gs_device_t *device, gs_texture_t *tex,
  817. int side, gs_zstencil_t *zstencil)
  818. {
  819. if (!tex) {
  820. tex = &device->curSwapChain->target;
  821. side = 0;
  822. }
  823. if (!zstencil)
  824. zstencil = &device->curSwapChain->zs;
  825. if (device->curRenderTarget == tex &&
  826. device->curRenderSide == side &&
  827. device->curZStencilBuffer == zstencil)
  828. return;
  829. if (tex->type != GS_TEXTURE_CUBE) {
  830. blog(LOG_ERROR, "device_set_cube_render_target (D3D11): "
  831. "texture is not a cube texture");
  832. return;
  833. }
  834. gs_texture_2d *tex2d = static_cast<gs_texture_2d*>(tex);
  835. if (!tex2d->renderTarget[side]) {
  836. blog(LOG_ERROR, "device_set_cube_render_target (D3D11): "
  837. "texture is not a render target");
  838. return;
  839. }
  840. ID3D11RenderTargetView *rt = tex2d->renderTarget[0];
  841. device->curRenderTarget = tex2d;
  842. device->curRenderSide = side;
  843. device->curZStencilBuffer = zstencil;
  844. device->context->OMSetRenderTargets(1, &rt, zstencil->view);
  845. }
  846. inline void gs_device::CopyTex(ID3D11Texture2D *dst,
  847. uint32_t dst_x, uint32_t dst_y,
  848. gs_texture_t *src, uint32_t src_x, uint32_t src_y,
  849. uint32_t src_w, uint32_t src_h)
  850. {
  851. if (src->type != GS_TEXTURE_2D)
  852. throw "Source texture must be a 2D texture";
  853. gs_texture_2d *tex2d = static_cast<gs_texture_2d*>(src);
  854. if (dst_x == 0 && dst_y == 0 &&
  855. src_x == 0 && src_y == 0 &&
  856. src_w == 0 && src_h == 0) {
  857. context->CopyResource(dst, tex2d->texture);
  858. } else {
  859. D3D11_BOX sbox;
  860. sbox.left = src_x;
  861. if (src_w > 0)
  862. sbox.right = src_x + src_w;
  863. else
  864. sbox.right = tex2d->width - 1;
  865. sbox.top = src_y;
  866. if (src_h > 0)
  867. sbox.bottom = src_y + src_h;
  868. else
  869. sbox.bottom = tex2d->height - 1;
  870. sbox.front = 0;
  871. sbox.back = 1;
  872. context->CopySubresourceRegion(dst, 0, dst_x, dst_y, 0,
  873. tex2d->texture, 0, &sbox);
  874. }
  875. }
  876. void device_copy_texture_region(gs_device_t *device,
  877. gs_texture_t *dst, uint32_t dst_x, uint32_t dst_y,
  878. gs_texture_t *src, uint32_t src_x, uint32_t src_y,
  879. uint32_t src_w, uint32_t src_h)
  880. {
  881. try {
  882. gs_texture_2d *src2d = static_cast<gs_texture_2d*>(src);
  883. gs_texture_2d *dst2d = static_cast<gs_texture_2d*>(dst);
  884. if (!src)
  885. throw "Source texture is NULL";
  886. if (!dst)
  887. throw "Destination texture is NULL";
  888. if (src->type != GS_TEXTURE_2D || dst->type != GS_TEXTURE_2D)
  889. throw "Source and destination textures must be a 2D "
  890. "textures";
  891. if (dst->format != src->format)
  892. throw "Source and destination formats do not match";
  893. /* apparently casting to the same type that the variable
  894. * already exists as is supposed to prevent some warning
  895. * when used with the conditional operator? */
  896. uint32_t copyWidth = (uint32_t)src_w ?
  897. (uint32_t)src_w : (src2d->width - src_x);
  898. uint32_t copyHeight = (uint32_t)src_h ?
  899. (uint32_t)src_h : (src2d->height - src_y);
  900. uint32_t dstWidth = dst2d->width - dst_x;
  901. uint32_t dstHeight = dst2d->height - dst_y;
  902. if (dstWidth < copyWidth || dstHeight < copyHeight)
  903. throw "Destination texture region is not big "
  904. "enough to hold the source region";
  905. if (dst_x == 0 && dst_y == 0 &&
  906. src_x == 0 && src_y == 0 &&
  907. src_w == 0 && src_h == 0) {
  908. copyWidth = 0;
  909. copyHeight = 0;
  910. }
  911. device->CopyTex(dst2d->texture, dst_x, dst_y,
  912. src, src_x, src_y, copyWidth, copyHeight);
  913. } catch(const char *error) {
  914. blog(LOG_ERROR, "device_copy_texture (D3D11): %s", error);
  915. }
  916. }
  917. void device_copy_texture(gs_device_t *device, gs_texture_t *dst,
  918. gs_texture_t *src)
  919. {
  920. device_copy_texture_region(device, dst, 0, 0, src, 0, 0, 0, 0);
  921. }
  922. void device_stage_texture(gs_device_t *device, gs_stagesurf_t *dst,
  923. gs_texture_t *src)
  924. {
  925. try {
  926. gs_texture_2d *src2d = static_cast<gs_texture_2d*>(src);
  927. if (!src)
  928. throw "Source texture is NULL";
  929. if (src->type != GS_TEXTURE_2D)
  930. throw "Source texture must be a 2D texture";
  931. if (!dst)
  932. throw "Destination surface is NULL";
  933. if (dst->format != src->format)
  934. throw "Source and destination formats do not match";
  935. if (dst->width != src2d->width ||
  936. dst->height != src2d->height)
  937. throw "Source and destination must have the same "
  938. "dimensions";
  939. device->CopyTex(dst->texture, 0, 0, src, 0, 0, 0, 0);
  940. } catch (const char *error) {
  941. blog(LOG_ERROR, "device_copy_texture (D3D11): %s", error);
  942. }
  943. }
  944. void device_begin_scene(gs_device_t *device)
  945. {
  946. clear_textures(device);
  947. }
  948. void device_draw(gs_device_t *device, enum gs_draw_mode draw_mode,
  949. uint32_t start_vert, uint32_t num_verts)
  950. {
  951. try {
  952. if (!device->curVertexShader)
  953. throw "No vertex shader specified";
  954. if (!device->curPixelShader)
  955. throw "No pixel shader specified";
  956. if (!device->curVertexBuffer)
  957. throw "No vertex buffer specified";
  958. gs_effect_t *effect = gs_get_effect();
  959. if (effect)
  960. gs_effect_update_params(effect);
  961. device->UpdateBlendState();
  962. device->UpdateRasterState();
  963. device->UpdateZStencilState();
  964. device->UpdateViewProjMatrix();
  965. device->curVertexShader->UploadParams();
  966. device->curPixelShader->UploadParams();
  967. } catch (const char *error) {
  968. blog(LOG_ERROR, "device_draw (D3D11): %s", error);
  969. return;
  970. } catch (HRError error) {
  971. blog(LOG_ERROR, "device_draw (D3D11): %s (%08lX)", error.str,
  972. error.hr);
  973. return;
  974. }
  975. D3D11_PRIMITIVE_TOPOLOGY newTopology = ConvertGSTopology(draw_mode);
  976. if (device->curToplogy != newTopology) {
  977. device->context->IASetPrimitiveTopology(newTopology);
  978. device->curToplogy = newTopology;
  979. }
  980. if (device->curIndexBuffer) {
  981. if (num_verts == 0)
  982. num_verts = (uint32_t)device->curIndexBuffer->num;
  983. device->context->DrawIndexed(num_verts, start_vert, 0);
  984. } else {
  985. if (num_verts == 0)
  986. num_verts = (uint32_t)device->curVertexBuffer->numVerts;
  987. device->context->Draw(num_verts, start_vert);
  988. }
  989. }
  990. void device_end_scene(gs_device_t *device)
  991. {
  992. /* does nothing in D3D11 */
  993. UNUSED_PARAMETER(device);
  994. }
  995. void device_load_swapchain(gs_device_t *device, gs_swapchain_t *swapchain)
  996. {
  997. gs_texture_t *target = device->curRenderTarget;
  998. gs_zstencil_t *zs = device->curZStencilBuffer;
  999. bool is_cube = device->curRenderTarget->type == GS_TEXTURE_CUBE;
  1000. if (target == &device->curSwapChain->target)
  1001. target = NULL;
  1002. if (zs == &device->curSwapChain->zs)
  1003. zs = NULL;
  1004. if (swapchain == NULL)
  1005. swapchain = &device->defaultSwap;
  1006. device->curSwapChain = swapchain;
  1007. if (is_cube)
  1008. device_set_cube_render_target(device, target,
  1009. device->curRenderSide, zs);
  1010. else
  1011. device_set_render_target(device, target, zs);
  1012. }
  1013. void device_clear(gs_device_t *device, uint32_t clear_flags,
  1014. const struct vec4 *color, float depth, uint8_t stencil)
  1015. {
  1016. int side = device->curRenderSide;
  1017. if ((clear_flags & GS_CLEAR_COLOR) != 0 && device->curRenderTarget)
  1018. device->context->ClearRenderTargetView(
  1019. device->curRenderTarget->renderTarget[side],
  1020. color->ptr);
  1021. if (device->curZStencilBuffer) {
  1022. uint32_t flags = 0;
  1023. if ((clear_flags & GS_CLEAR_DEPTH) != 0)
  1024. flags |= D3D11_CLEAR_DEPTH;
  1025. if ((clear_flags & GS_CLEAR_STENCIL) != 0)
  1026. flags |= D3D11_CLEAR_STENCIL;
  1027. if (flags && device->curZStencilBuffer->view)
  1028. device->context->ClearDepthStencilView(
  1029. device->curZStencilBuffer->view,
  1030. flags, depth, stencil);
  1031. }
  1032. }
  1033. void device_present(gs_device_t *device)
  1034. {
  1035. device->curSwapChain->swap->Present(0, 0);
  1036. }
  1037. void device_flush(gs_device_t *device)
  1038. {
  1039. device->context->Flush();
  1040. }
  1041. void device_set_cull_mode(gs_device_t *device, enum gs_cull_mode mode)
  1042. {
  1043. if (mode == device->rasterState.cullMode)
  1044. return;
  1045. device->rasterState.cullMode = mode;
  1046. device->rasterStateChanged = true;
  1047. }
  1048. enum gs_cull_mode device_get_cull_mode(const gs_device_t *device)
  1049. {
  1050. return device->rasterState.cullMode;
  1051. }
  1052. void device_enable_blending(gs_device_t *device, bool enable)
  1053. {
  1054. if (enable == device->blendState.blendEnabled)
  1055. return;
  1056. device->blendState.blendEnabled = enable;
  1057. device->blendStateChanged = true;
  1058. }
  1059. void device_enable_depth_test(gs_device_t *device, bool enable)
  1060. {
  1061. if (enable == device->zstencilState.depthEnabled)
  1062. return;
  1063. device->zstencilState.depthEnabled = enable;
  1064. device->zstencilStateChanged = true;
  1065. }
  1066. void device_enable_stencil_test(gs_device_t *device, bool enable)
  1067. {
  1068. if (enable == device->zstencilState.stencilEnabled)
  1069. return;
  1070. device->zstencilState.stencilEnabled = enable;
  1071. device->zstencilStateChanged = true;
  1072. }
  1073. void device_enable_stencil_write(gs_device_t *device, bool enable)
  1074. {
  1075. if (enable == device->zstencilState.stencilWriteEnabled)
  1076. return;
  1077. device->zstencilState.stencilWriteEnabled = enable;
  1078. device->zstencilStateChanged = true;
  1079. }
  1080. void device_enable_color(gs_device_t *device, bool red, bool green,
  1081. bool blue, bool alpha)
  1082. {
  1083. if (device->blendState.redEnabled == red &&
  1084. device->blendState.greenEnabled == green &&
  1085. device->blendState.blueEnabled == blue &&
  1086. device->blendState.alphaEnabled == alpha)
  1087. return;
  1088. device->blendState.redEnabled = red;
  1089. device->blendState.greenEnabled = green;
  1090. device->blendState.blueEnabled = blue;
  1091. device->blendState.alphaEnabled = alpha;
  1092. device->blendStateChanged = true;
  1093. }
  1094. void device_blend_function(gs_device_t *device, enum gs_blend_type src,
  1095. enum gs_blend_type dest)
  1096. {
  1097. if (device->blendState.srcFactor == src &&
  1098. device->blendState.destFactor == dest)
  1099. return;
  1100. device->blendState.srcFactor = src;
  1101. device->blendState.destFactor = dest;
  1102. device->blendStateChanged = true;
  1103. }
  1104. void device_depth_function(gs_device_t *device, enum gs_depth_test test)
  1105. {
  1106. if (device->zstencilState.depthFunc == test)
  1107. return;
  1108. device->zstencilState.depthFunc = test;
  1109. device->zstencilStateChanged = true;
  1110. }
  1111. static inline void update_stencilside_test(gs_device_t *device,
  1112. StencilSide &side, gs_depth_test test)
  1113. {
  1114. if (side.test == test)
  1115. return;
  1116. side.test = test;
  1117. device->zstencilStateChanged = true;
  1118. }
  1119. void device_stencil_function(gs_device_t *device, enum gs_stencil_side side,
  1120. enum gs_depth_test test)
  1121. {
  1122. int sideVal = (int)side;
  1123. if (sideVal & GS_STENCIL_FRONT)
  1124. update_stencilside_test(device,
  1125. device->zstencilState.stencilFront, test);
  1126. if (sideVal & GS_STENCIL_BACK)
  1127. update_stencilside_test(device,
  1128. device->zstencilState.stencilBack, test);
  1129. }
  1130. static inline void update_stencilside_op(gs_device_t *device, StencilSide &side,
  1131. enum gs_stencil_op_type fail, enum gs_stencil_op_type zfail,
  1132. enum gs_stencil_op_type zpass)
  1133. {
  1134. if (side.fail == fail && side.zfail == zfail && side.zpass == zpass)
  1135. return;
  1136. side.fail = fail;
  1137. side.zfail = zfail;
  1138. side.zpass = zpass;
  1139. device->zstencilStateChanged = true;
  1140. }
  1141. void device_stencil_op(gs_device_t *device, enum gs_stencil_side side,
  1142. enum gs_stencil_op_type fail, enum gs_stencil_op_type zfail,
  1143. enum gs_stencil_op_type zpass)
  1144. {
  1145. int sideVal = (int)side;
  1146. if (sideVal & GS_STENCIL_FRONT)
  1147. update_stencilside_op(device,
  1148. device->zstencilState.stencilFront,
  1149. fail, zfail, zpass);
  1150. if (sideVal & GS_STENCIL_BACK)
  1151. update_stencilside_op(device,
  1152. device->zstencilState.stencilBack,
  1153. fail, zfail, zpass);
  1154. }
  1155. void device_set_viewport(gs_device_t *device, int x, int y, int width,
  1156. int height)
  1157. {
  1158. D3D11_VIEWPORT vp;
  1159. memset(&vp, 0, sizeof(vp));
  1160. vp.MaxDepth = 1.0f;
  1161. vp.TopLeftX = (float)x;
  1162. vp.TopLeftY = (float)y;
  1163. vp.Width = (float)width;
  1164. vp.Height = (float)height;
  1165. device->context->RSSetViewports(1, &vp);
  1166. device->viewport.x = x;
  1167. device->viewport.y = y;
  1168. device->viewport.cx = width;
  1169. device->viewport.cy = height;
  1170. }
  1171. void device_get_viewport(const gs_device_t *device, struct gs_rect *rect)
  1172. {
  1173. memcpy(rect, &device->viewport, sizeof(gs_rect));
  1174. }
  1175. void device_set_scissor_rect(gs_device_t *device, const struct gs_rect *rect)
  1176. {
  1177. D3D11_RECT d3drect;
  1178. device->rasterState.scissorEnabled = (rect != NULL);
  1179. if (rect != NULL) {
  1180. d3drect.left = rect->x;
  1181. d3drect.top = rect->y;
  1182. d3drect.right = rect->x + rect->cx;
  1183. d3drect.bottom = rect->y + rect->cy;
  1184. device->context->RSSetScissorRects(1, &d3drect);
  1185. }
  1186. device->rasterStateChanged = true;
  1187. }
  1188. void device_ortho(gs_device_t *device, float left, float right, float top,
  1189. float bottom, float zNear, float zFar)
  1190. {
  1191. matrix4 *dst = &device->curProjMatrix;
  1192. float rml = right-left;
  1193. float bmt = bottom-top;
  1194. float fmn = zFar-zNear;
  1195. vec4_zero(&dst->x);
  1196. vec4_zero(&dst->y);
  1197. vec4_zero(&dst->z);
  1198. vec4_zero(&dst->t);
  1199. dst->x.x = 2.0f / rml;
  1200. dst->t.x = (left+right) / -rml;
  1201. dst->y.y = 2.0f / -bmt;
  1202. dst->t.y = (bottom+top) / bmt;
  1203. dst->z.z = 1.0f / fmn;
  1204. dst->t.z = zNear / -fmn;
  1205. dst->t.w = 1.0f;
  1206. }
  1207. void device_frustum(gs_device_t *device, float left, float right, float top,
  1208. float bottom, float zNear, float zFar)
  1209. {
  1210. matrix4 *dst = &device->curProjMatrix;
  1211. float rml = right-left;
  1212. float bmt = bottom-top;
  1213. float fmn = zFar-zNear;
  1214. float nearx2 = 2.0f*zNear;
  1215. vec4_zero(&dst->x);
  1216. vec4_zero(&dst->y);
  1217. vec4_zero(&dst->z);
  1218. vec4_zero(&dst->t);
  1219. dst->x.x = nearx2 / rml;
  1220. dst->z.x = (left+right) / -rml;
  1221. dst->y.y = nearx2 / -bmt;
  1222. dst->z.y = (bottom+top) / bmt;
  1223. dst->z.z = zFar / fmn;
  1224. dst->t.z = (zNear*zFar) / -fmn;
  1225. dst->z.w = 1.0f;
  1226. }
  1227. void device_projection_push(gs_device_t *device)
  1228. {
  1229. mat4float mat;
  1230. memcpy(&mat, &device->curProjMatrix, sizeof(matrix4));
  1231. device->projStack.push_back(mat);
  1232. }
  1233. void device_projection_pop(gs_device_t *device)
  1234. {
  1235. if (!device->projStack.size())
  1236. return;
  1237. mat4float *mat = device->projStack.data();
  1238. size_t end = device->projStack.size()-1;
  1239. /* XXX - does anyone know a better way of doing this? */
  1240. memcpy(&device->curProjMatrix, mat+end, sizeof(matrix4));
  1241. device->projStack.pop_back();
  1242. }
  1243. void gs_swapchain_destroy(gs_swapchain_t *swapchain)
  1244. {
  1245. if (!swapchain)
  1246. return;
  1247. gs_device *device = swapchain->device;
  1248. if (device->curSwapChain == swapchain)
  1249. device->curSwapChain = &device->defaultSwap;
  1250. delete swapchain;
  1251. }
  1252. void gs_texture_destroy(gs_texture_t *tex)
  1253. {
  1254. delete tex;
  1255. }
  1256. uint32_t gs_texture_get_width(const gs_texture_t *tex)
  1257. {
  1258. if (tex->type != GS_TEXTURE_2D)
  1259. return 0;
  1260. return static_cast<const gs_texture_2d*>(tex)->width;
  1261. }
  1262. uint32_t gs_texture_get_height(const gs_texture_t *tex)
  1263. {
  1264. if (tex->type != GS_TEXTURE_2D)
  1265. return 0;
  1266. return static_cast<const gs_texture_2d*>(tex)->height;
  1267. }
  1268. enum gs_color_format gs_texture_get_color_format(const gs_texture_t *tex)
  1269. {
  1270. if (tex->type != GS_TEXTURE_2D)
  1271. return GS_UNKNOWN;
  1272. return static_cast<const gs_texture_2d*>(tex)->format;
  1273. }
  1274. bool gs_texture_map(gs_texture_t *tex, uint8_t **ptr, uint32_t *linesize)
  1275. {
  1276. HRESULT hr;
  1277. if (tex->type != GS_TEXTURE_2D)
  1278. return false;
  1279. gs_texture_2d *tex2d = static_cast<gs_texture_2d*>(tex);
  1280. D3D11_MAPPED_SUBRESOURCE map;
  1281. hr = tex2d->device->context->Map(tex2d->texture, 0,
  1282. D3D11_MAP_WRITE_DISCARD, 0, &map);
  1283. if (FAILED(hr))
  1284. return false;
  1285. *ptr = (uint8_t*)map.pData;
  1286. *linesize = map.RowPitch;
  1287. return true;
  1288. }
  1289. void gs_texture_unmap(gs_texture_t *tex)
  1290. {
  1291. if (tex->type != GS_TEXTURE_2D)
  1292. return;
  1293. gs_texture_2d *tex2d = static_cast<gs_texture_2d*>(tex);
  1294. tex2d->device->context->Unmap(tex2d->texture, 0);
  1295. }
  1296. void *gs_texture_get_obj(gs_texture_t *tex)
  1297. {
  1298. if (tex->type != GS_TEXTURE_2D)
  1299. return nullptr;
  1300. gs_texture_2d *tex2d = static_cast<gs_texture_2d*>(tex);
  1301. return tex2d->texture.Get();
  1302. }
  1303. void gs_cubetexture_destroy(gs_texture_t *cubetex)
  1304. {
  1305. delete cubetex;
  1306. }
  1307. uint32_t gs_cubetexture_get_size(const gs_texture_t *cubetex)
  1308. {
  1309. if (cubetex->type != GS_TEXTURE_CUBE)
  1310. return 0;
  1311. const gs_texture_2d *tex = static_cast<const gs_texture_2d*>(cubetex);
  1312. return tex->width;
  1313. }
  1314. enum gs_color_format gs_cubetexture_get_color_format(
  1315. const gs_texture_t *cubetex)
  1316. {
  1317. if (cubetex->type != GS_TEXTURE_CUBE)
  1318. return GS_UNKNOWN;
  1319. const gs_texture_2d *tex = static_cast<const gs_texture_2d*>(cubetex);
  1320. return tex->format;
  1321. }
  1322. void gs_voltexture_destroy(gs_texture_t *voltex)
  1323. {
  1324. delete voltex;
  1325. }
  1326. uint32_t gs_voltexture_get_width(const gs_texture_t *voltex)
  1327. {
  1328. /* TODO */
  1329. UNUSED_PARAMETER(voltex);
  1330. return 0;
  1331. }
  1332. uint32_t gs_voltexture_get_height(const gs_texture_t *voltex)
  1333. {
  1334. /* TODO */
  1335. UNUSED_PARAMETER(voltex);
  1336. return 0;
  1337. }
  1338. uint32_t gs_voltexture_getdepth(const gs_texture_t *voltex)
  1339. {
  1340. /* TODO */
  1341. UNUSED_PARAMETER(voltex);
  1342. return 0;
  1343. }
  1344. enum gs_color_format gs_voltexture_get_color_format(const gs_texture_t *voltex)
  1345. {
  1346. /* TODO */
  1347. UNUSED_PARAMETER(voltex);
  1348. return GS_UNKNOWN;
  1349. }
  1350. void gs_stagesurface_destroy(gs_stagesurf_t *stagesurf)
  1351. {
  1352. delete stagesurf;
  1353. }
  1354. uint32_t gs_stagesurface_get_width(const gs_stagesurf_t *stagesurf)
  1355. {
  1356. return stagesurf->width;
  1357. }
  1358. uint32_t gs_stagesurface_get_height(const gs_stagesurf_t *stagesurf)
  1359. {
  1360. return stagesurf->height;
  1361. }
  1362. enum gs_color_format gs_stagesurface_get_color_format(
  1363. const gs_stagesurf_t *stagesurf)
  1364. {
  1365. return stagesurf->format;
  1366. }
  1367. bool gs_stagesurface_map(gs_stagesurf_t *stagesurf, uint8_t **data,
  1368. uint32_t *linesize)
  1369. {
  1370. D3D11_MAPPED_SUBRESOURCE map;
  1371. if (FAILED(stagesurf->device->context->Map(stagesurf->texture, 0,
  1372. D3D11_MAP_READ, 0, &map)))
  1373. return false;
  1374. *data = (uint8_t*)map.pData;
  1375. *linesize = map.RowPitch;
  1376. return true;
  1377. }
  1378. void gs_stagesurface_unmap(gs_stagesurf_t *stagesurf)
  1379. {
  1380. stagesurf->device->context->Unmap(stagesurf->texture, 0);
  1381. }
  1382. void gs_zstencil_destroy(gs_zstencil_t *zstencil)
  1383. {
  1384. delete zstencil;
  1385. }
  1386. void gs_samplerstate_destroy(gs_samplerstate_t *samplerstate)
  1387. {
  1388. if (!samplerstate)
  1389. return;
  1390. if (samplerstate->device)
  1391. for (int i = 0; i < GS_MAX_TEXTURES; i++)
  1392. if (samplerstate->device->curSamplers[i] ==
  1393. samplerstate)
  1394. samplerstate->device->curSamplers[i] = nullptr;
  1395. delete samplerstate;
  1396. }
  1397. void gs_vertexbuffer_destroy(gs_vertbuffer_t *vertbuffer)
  1398. {
  1399. delete vertbuffer;
  1400. }
  1401. void gs_vertexbuffer_flush(gs_vertbuffer_t *vertbuffer)
  1402. {
  1403. if (!vertbuffer->dynamic) {
  1404. blog(LOG_ERROR, "gs_vertexbuffer_flush: vertex buffer is "
  1405. "not dynamic");
  1406. return;
  1407. }
  1408. vertbuffer->FlushBuffer(vertbuffer->vertexBuffer,
  1409. vertbuffer->vbd.data->points, sizeof(vec3));
  1410. if (vertbuffer->normalBuffer)
  1411. vertbuffer->FlushBuffer(vertbuffer->normalBuffer,
  1412. vertbuffer->vbd.data->normals, sizeof(vec3));
  1413. if (vertbuffer->tangentBuffer)
  1414. vertbuffer->FlushBuffer(vertbuffer->tangentBuffer,
  1415. vertbuffer->vbd.data->tangents, sizeof(vec3));
  1416. if (vertbuffer->colorBuffer)
  1417. vertbuffer->FlushBuffer(vertbuffer->colorBuffer,
  1418. vertbuffer->vbd.data->colors, sizeof(uint32_t));
  1419. for (size_t i = 0; i < vertbuffer->uvBuffers.size(); i++) {
  1420. gs_tvertarray &tv = vertbuffer->vbd.data->tvarray[i];
  1421. vertbuffer->FlushBuffer(vertbuffer->uvBuffers[i],
  1422. tv.array, tv.width*sizeof(float));
  1423. }
  1424. }
  1425. struct gs_vb_data *gs_vertexbuffer_get_data(const gs_vertbuffer_t *vertbuffer)
  1426. {
  1427. return vertbuffer->vbd.data;
  1428. }
  1429. void gs_indexbuffer_destroy(gs_indexbuffer_t *indexbuffer)
  1430. {
  1431. delete indexbuffer;
  1432. }
  1433. void gs_indexbuffer_flush(gs_indexbuffer_t *indexbuffer)
  1434. {
  1435. HRESULT hr;
  1436. if (!indexbuffer->dynamic)
  1437. return;
  1438. D3D11_MAPPED_SUBRESOURCE map;
  1439. hr = indexbuffer->device->context->Map(indexbuffer->indexBuffer, 0,
  1440. D3D11_MAP_WRITE_DISCARD, 0, &map);
  1441. if (FAILED(hr))
  1442. return;
  1443. memcpy(map.pData, indexbuffer->indices.data,
  1444. indexbuffer->num * indexbuffer->indexSize);
  1445. indexbuffer->device->context->Unmap(indexbuffer->indexBuffer, 0);
  1446. }
  1447. void *gs_indexbuffer_get_data(const gs_indexbuffer_t *indexbuffer)
  1448. {
  1449. return indexbuffer->indices.data;
  1450. }
  1451. size_t gs_indexbuffer_get_num_indices(const gs_indexbuffer_t *indexbuffer)
  1452. {
  1453. return indexbuffer->num;
  1454. }
  1455. enum gs_index_type gs_indexbuffer_get_type(const gs_indexbuffer_t *indexbuffer)
  1456. {
  1457. return indexbuffer->type;
  1458. }
  1459. extern "C" EXPORT bool device_gdi_texture_available(void)
  1460. {
  1461. return true;
  1462. }
  1463. extern "C" EXPORT bool device_shared_texture_available(void)
  1464. {
  1465. return true;
  1466. }
  1467. extern "C" EXPORT gs_texture_t *device_texture_create_gdi(gs_device_t *device,
  1468. uint32_t width, uint32_t height)
  1469. {
  1470. gs_texture *texture = nullptr;
  1471. try {
  1472. texture = new gs_texture_2d(device, width, height, GS_BGRA,
  1473. 1, nullptr, GS_RENDER_TARGET, GS_TEXTURE_2D,
  1474. true, false);
  1475. } catch (HRError error) {
  1476. blog(LOG_ERROR, "device_texture_create_gdi (D3D11): %s (%08lX)",
  1477. error.str, error.hr);
  1478. } catch (const char *error) {
  1479. blog(LOG_ERROR, "device_texture_create_gdi (D3D11): %s", error);
  1480. }
  1481. return texture;
  1482. }
  1483. static inline bool TextureGDICompatible(gs_texture_2d *tex2d, const char *func)
  1484. {
  1485. if (!tex2d->isGDICompatible) {
  1486. blog(LOG_ERROR, "%s (D3D11): Texture is not GDI compatible",
  1487. func);
  1488. return false;
  1489. }
  1490. return true;
  1491. }
  1492. extern "C" EXPORT void *gs_texture_get_dc(gs_texture_t *tex)
  1493. {
  1494. HDC hDC = nullptr;
  1495. if (tex->type != GS_TEXTURE_2D)
  1496. return nullptr;
  1497. gs_texture_2d *tex2d = static_cast<gs_texture_2d*>(tex);
  1498. if (!TextureGDICompatible(tex2d, "gs_texture_get_dc"))
  1499. return nullptr;
  1500. tex2d->gdiSurface->GetDC(true, &hDC);
  1501. return hDC;
  1502. }
  1503. extern "C" EXPORT void gs_texture_release_dc(gs_texture_t *tex)
  1504. {
  1505. if (tex->type != GS_TEXTURE_2D)
  1506. return;
  1507. gs_texture_2d *tex2d = static_cast<gs_texture_2d*>(tex);
  1508. if (!TextureGDICompatible(tex2d, "gs_texture_release_dc"))
  1509. return;
  1510. tex2d->gdiSurface->ReleaseDC(nullptr);
  1511. }
  1512. extern "C" EXPORT gs_texture_t *device_texture_open_shared(gs_device_t *device,
  1513. uint32_t handle)
  1514. {
  1515. gs_texture *texture = nullptr;
  1516. try {
  1517. texture = new gs_texture_2d(device, handle);
  1518. } catch (HRError error) {
  1519. blog(LOG_ERROR, "gs_texture_open_shared (D3D11): %s (%08lX)",
  1520. error.str, error.hr);
  1521. } catch (const char *error) {
  1522. blog(LOG_ERROR, "gs_texture_open_shared (D3D11): %s", error);
  1523. }
  1524. return texture;
  1525. }