gfxD3D11Target.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2015 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "gfx/D3D11/gfxD3D11Target.h"
  24. #include "gfx/D3D11/gfxD3D11Cubemap.h"
  25. #include "gfx/D3D11/gfxD3D11EnumTranslate.h"
  26. #include "gfx/gfxDebugEvent.h"
  27. #include "gfx/gfxStringEnumTranslate.h"
  28. #include "windowManager/win32/win32Window.h"
  29. GFXD3D11TextureTarget::GFXD3D11TextureTarget()
  30. : mTargetSize( Point2I::Zero ),
  31. mTargetFormat( GFXFormatR8G8B8A8 )
  32. {
  33. for(S32 i=0; i<MaxRenderSlotId; i++)
  34. {
  35. mTargets[i] = NULL;
  36. mResolveTargets[i] = NULL;
  37. mTargetViews[i] = NULL;
  38. mTargetSRViews[i] = NULL;
  39. }
  40. }
  41. GFXD3D11TextureTarget::~GFXD3D11TextureTarget()
  42. {
  43. // Release anything we might be holding.
  44. for(S32 i=0; i<MaxRenderSlotId; i++)
  45. {
  46. mResolveTargets[i] = NULL;
  47. SAFE_RELEASE(mTargetViews[i]);
  48. SAFE_RELEASE(mTargets[i]);
  49. SAFE_RELEASE(mTargetSRViews[i]);
  50. }
  51. zombify();
  52. }
  53. void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *tex, U32 mipLevel/*=0*/, U32 zOffset /*= 0*/ )
  54. {
  55. GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_attachTexture, ColorI::RED );
  56. AssertFatal(slot < MaxRenderSlotId, "GFXD3D11TextureTarget::attachTexture - out of range slot.");
  57. // TODO: The way this is implemented... you can attach a texture
  58. // object multiple times and it will release and reset it.
  59. //
  60. // We should rework this to detect when no change has occured
  61. // and skip out early.
  62. // Mark state as dirty so device can know to update.
  63. invalidateState();
  64. // Release what we had, it's definitely going to change.
  65. SAFE_RELEASE(mTargetViews[slot]);
  66. SAFE_RELEASE(mTargets[slot]);
  67. SAFE_RELEASE(mTargetSRViews[slot]);
  68. mResolveTargets[slot] = NULL;
  69. if(slot == Color0)
  70. {
  71. mTargetSize = Point2I::Zero;
  72. mTargetFormat = GFXFormatR8G8B8A8;
  73. }
  74. // Are we clearing?
  75. if(!tex)
  76. {
  77. // Yup - just exit, it'll stay NULL.
  78. return;
  79. }
  80. // TODO: Mip map generation currently only supported on dynamic cubemaps
  81. mTargetSRViews[slot] = NULL;
  82. // Take care of default targets
  83. if( tex == GFXTextureTarget::sDefaultDepthStencil )
  84. {
  85. mTargets[slot] = D3D11->mDeviceDepthStencil;
  86. mTargetViews[slot] = D3D11->mDeviceDepthStencilView;
  87. mTargets[slot]->AddRef();
  88. mTargetViews[slot]->AddRef();
  89. }
  90. else
  91. {
  92. // Cast the texture object to D3D...
  93. AssertFatal(static_cast<GFXD3D11TextureObject*>(tex), "GFXD3D11TextureTarget::attachTexture - invalid texture object.");
  94. GFXD3D11TextureObject *d3dto = static_cast<GFXD3D11TextureObject*>(tex);
  95. // Grab the surface level.
  96. if( slot == DepthStencil )
  97. {
  98. mTargets[slot] = d3dto->getSurface();
  99. if ( mTargets[slot] )
  100. mTargets[slot]->AddRef();
  101. mTargetViews[slot] = d3dto->getDSView();
  102. if( mTargetViews[slot])
  103. mTargetViews[slot]->AddRef();
  104. }
  105. else
  106. {
  107. // getSurface will almost always return NULL. It will only return non-NULL
  108. // if the surface that it needs to render to is different than the mip level
  109. // in the actual texture. This will happen with MSAA.
  110. if( d3dto->getSurface() == NULL )
  111. {
  112. mTargets[slot] = d3dto->get2DTex();
  113. mTargets[slot]->AddRef();
  114. mTargetViews[slot] = d3dto->getRTView();
  115. mTargetViews[slot]->AddRef();
  116. }
  117. else
  118. {
  119. mTargets[slot] = d3dto->getSurface();
  120. mTargets[slot]->AddRef();
  121. mTargetViews[slot]->AddRef();
  122. // Only assign resolve target if d3dto has a surface to give us.
  123. //
  124. // That usually means there is an MSAA target involved, which is why
  125. // the resolve is needed to get the data out of the target.
  126. mResolveTargets[slot] = d3dto;
  127. if ( tex && slot == Color0 )
  128. {
  129. mTargetSize.set( tex->getSize().x, tex->getSize().y );
  130. mTargetFormat = tex->getFormat();
  131. }
  132. }
  133. }
  134. // Update surface size
  135. if(slot == Color0)
  136. {
  137. ID3D11Texture2D *surface = mTargets[Color0];
  138. if ( surface )
  139. {
  140. D3D11_TEXTURE2D_DESC sd;
  141. surface->GetDesc(&sd);
  142. mTargetSize = Point2I(sd.Width, sd.Height);
  143. S32 format = sd.Format;
  144. if (format == DXGI_FORMAT_R8G8B8A8_TYPELESS || format == DXGI_FORMAT_B8G8R8A8_TYPELESS)
  145. {
  146. mTargetFormat = GFXFormatR8G8B8A8;
  147. return;
  148. }
  149. GFXREVERSE_LOOKUP( GFXD3D11TextureFormat, GFXFormat, format );
  150. mTargetFormat = (GFXFormat)format;
  151. }
  152. }
  153. }
  154. }
  155. void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel/*=0*/ )
  156. {
  157. GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_attachTexture_Cubemap, ColorI::RED );
  158. AssertFatal(slot < MaxRenderSlotId, "GFXD3D11TextureTarget::attachTexture - out of range slot.");
  159. // Mark state as dirty so device can know to update.
  160. invalidateState();
  161. // Release what we had, it's definitely going to change.
  162. SAFE_RELEASE(mTargetViews[slot]);
  163. SAFE_RELEASE(mTargets[slot]);
  164. SAFE_RELEASE(mTargetSRViews[slot]);
  165. mResolveTargets[slot] = NULL;
  166. // Cast the texture object to D3D...
  167. AssertFatal(!tex || static_cast<GFXD3D11Cubemap*>(tex), "GFXD3DTextureTarget::attachTexture - invalid cubemap object.");
  168. if(slot == Color0)
  169. {
  170. mTargetSize = Point2I::Zero;
  171. mTargetFormat = GFXFormatR8G8B8A8;
  172. }
  173. // Are we clearing?
  174. if(!tex)
  175. {
  176. // Yup - just exit, it'll stay NULL.
  177. return;
  178. }
  179. GFXD3D11Cubemap *cube = static_cast<GFXD3D11Cubemap*>(tex);
  180. mTargets[slot] = cube->get2DTex();
  181. mTargets[slot]->AddRef();
  182. mTargetViews[slot] = cube->getRTView(face);
  183. mTargetViews[slot]->AddRef();
  184. mTargetSRViews[slot] = cube->getSRView();
  185. mTargetSRViews[slot]->AddRef();
  186. // Update surface size
  187. if(slot == Color0)
  188. {
  189. ID3D11Texture2D *surface = mTargets[Color0];
  190. if ( surface )
  191. {
  192. D3D11_TEXTURE2D_DESC sd;
  193. surface->GetDesc(&sd);
  194. mTargetSize = Point2I(sd.Width, sd.Height);
  195. S32 format = sd.Format;
  196. GFXREVERSE_LOOKUP( GFXD3D11TextureFormat, GFXFormat, format );
  197. mTargetFormat = (GFXFormat)format;
  198. }
  199. }
  200. }
  201. void GFXD3D11TextureTarget::activate()
  202. {
  203. GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_activate, ColorI::RED );
  204. AssertFatal( mTargets[GFXTextureTarget::Color0], "GFXD3D11TextureTarget::activate() - You can never have a NULL primary render target!" );
  205. // Clear the state indicator.
  206. stateApplied();
  207. // Now set all the new surfaces into the appropriate slots.
  208. ID3D11RenderTargetView* rtViews[MaxRenderSlotId] = { NULL, NULL, NULL, NULL, NULL, NULL };
  209. ID3D11DepthStencilView* dsView = (ID3D11DepthStencilView*)(mTargetViews[GFXTextureTarget::DepthStencil]);
  210. for (U32 i = 0; i < 6; i++)
  211. {
  212. rtViews[i] = (ID3D11RenderTargetView*)mTargetViews[GFXTextureTarget::Color0 + i];
  213. }
  214. D3D11DEVICECONTEXT->OMSetRenderTargets(MaxRenderSlotId, rtViews, dsView);
  215. }
  216. void GFXD3D11TextureTarget::deactivate()
  217. {
  218. //re-gen mip maps
  219. for (U32 i = 0; i < 6; i++)
  220. {
  221. ID3D11ShaderResourceView* pSRView = mTargetSRViews[GFXTextureTarget::Color0 + i];
  222. if (pSRView)
  223. D3D11DEVICECONTEXT->GenerateMips(pSRView);
  224. }
  225. }
  226. void GFXD3D11TextureTarget::resolve()
  227. {
  228. GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_resolve, ColorI::RED );
  229. for (U32 i = 0; i < MaxRenderSlotId; i++)
  230. {
  231. // We use existance @ mResolveTargets as a flag that we need to copy
  232. // data from the rendertarget into the texture.
  233. if (mResolveTargets[i])
  234. {
  235. D3D11_TEXTURE2D_DESC desc;
  236. mTargets[i]->GetDesc(&desc);
  237. D3D11DEVICECONTEXT->CopySubresourceRegion(mResolveTargets[i]->get2DTex(), 0, 0, 0, 0, mTargets[i], 0, NULL);
  238. }
  239. }
  240. }
  241. void GFXD3D11TextureTarget::resolveTo( GFXTextureObject *tex )
  242. {
  243. GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_resolveTo, ColorI::RED );
  244. if ( mTargets[Color0] == NULL )
  245. return;
  246. D3D11_TEXTURE2D_DESC desc;
  247. mTargets[Color0]->GetDesc(&desc);
  248. D3D11DEVICECONTEXT->CopySubresourceRegion(((GFXD3D11TextureObject*)(tex))->get2DTex(), 0, 0, 0, 0, mTargets[Color0], 0, NULL);
  249. }
  250. void GFXD3D11TextureTarget::zombify()
  251. {
  252. for(U32 i = 0; i < MaxRenderSlotId; i++)
  253. attachTexture(RenderSlot(i), NULL);
  254. }
  255. void GFXD3D11TextureTarget::resurrect()
  256. {
  257. }
  258. GFXD3D11WindowTarget::GFXD3D11WindowTarget()
  259. {
  260. mWindow = NULL;
  261. mBackbuffer = NULL;
  262. }
  263. GFXD3D11WindowTarget::~GFXD3D11WindowTarget()
  264. {
  265. SAFE_RELEASE(mBackbuffer);
  266. }
  267. void GFXD3D11WindowTarget::initPresentationParams()
  268. {
  269. // Get some video mode related info.
  270. GFXVideoMode vm = mWindow->getVideoMode();
  271. Win32Window* win = static_cast<Win32Window*>(mWindow);
  272. HWND hwnd = win->getHWND();
  273. mPresentationParams = D3D11->setupPresentParams(vm, hwnd);
  274. }
  275. const Point2I GFXD3D11WindowTarget::getSize()
  276. {
  277. return mWindow->getVideoMode().resolution;
  278. }
  279. GFXFormat GFXD3D11WindowTarget::getFormat()
  280. {
  281. S32 format = mPresentationParams.BufferDesc.Format;
  282. GFXREVERSE_LOOKUP( GFXD3D11TextureFormat, GFXFormat, format );
  283. return (GFXFormat)format;
  284. }
  285. bool GFXD3D11WindowTarget::present()
  286. {
  287. return (D3D11->getSwapChain()->Present(!D3D11->smDisableVSync, 0) == S_OK);
  288. }
  289. void GFXD3D11WindowTarget::setImplicitSwapChain()
  290. {
  291. if (!mBackbuffer)
  292. D3D11->mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackbuffer);
  293. }
  294. void GFXD3D11WindowTarget::resetMode()
  295. {
  296. mWindow->setSuppressReset(true);
  297. // Setup our presentation params.
  298. initPresentationParams();
  299. // Otherwise, we have to reset the device, if we're the implicit swapchain.
  300. D3D11->reset(mPresentationParams);
  301. // Update our size, too.
  302. mSize = Point2I(mPresentationParams.BufferDesc.Width, mPresentationParams.BufferDesc.Height);
  303. mWindow->setSuppressReset(false);
  304. GFX->beginReset();
  305. }
  306. void GFXD3D11WindowTarget::zombify()
  307. {
  308. SAFE_RELEASE(mBackbuffer);
  309. }
  310. void GFXD3D11WindowTarget::resurrect()
  311. {
  312. setImplicitSwapChain();
  313. }
  314. void GFXD3D11WindowTarget::activate()
  315. {
  316. GFXDEBUGEVENT_SCOPE(GFXPCD3D11WindowTarget_activate, ColorI::RED);
  317. //clear ther rendertargets first
  318. ID3D11RenderTargetView* rtViews[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  319. D3D11DEVICECONTEXT->OMSetRenderTargets(8, rtViews, NULL);
  320. D3D11DEVICECONTEXT->OMSetRenderTargets(1, &D3D11->mDeviceBackBufferView, D3D11->mDeviceDepthStencilView);
  321. DXGI_SWAP_CHAIN_DESC pp;
  322. D3D11->mSwapChain->GetDesc(&pp);
  323. // Update our video mode here, too.
  324. GFXVideoMode vm;
  325. vm = mWindow->getVideoMode();
  326. vm.resolution.x = pp.BufferDesc.Width;
  327. vm.resolution.y = pp.BufferDesc.Height;
  328. vm.fullScreen = !pp.Windowed;
  329. mSize = vm.resolution;
  330. }
  331. void GFXD3D11WindowTarget::resolveTo(GFXTextureObject *tex)
  332. {
  333. GFXDEBUGEVENT_SCOPE(GFXPCD3D11WindowTarget_resolveTo, ColorI::RED);
  334. D3D11_TEXTURE2D_DESC desc;
  335. ID3D11Texture2D* surf = ((GFXD3D11TextureObject*)(tex))->get2DTex();
  336. surf->GetDesc(&desc);
  337. D3D11DEVICECONTEXT->ResolveSubresource(surf, 0, D3D11->mDeviceBackbuffer, 0, desc.Format);
  338. }