gfxD3D11Cubemap.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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 "gfx/D3D11/gfxD3D11Cubemap.h"
  23. #include "gfx/gfxCardProfile.h"
  24. #include "gfx/gfxTextureManager.h"
  25. #include "gfx/D3D11/gfxD3D11EnumTranslate.h"
  26. #include "gfx/bitmap/imageUtils.h"
  27. GFXD3D11Cubemap::GFXD3D11Cubemap() : mTexture(NULL), mSRView(NULL), mDSView(NULL)
  28. {
  29. mDynamic = false;
  30. mAutoGenMips = false;
  31. mFaceFormat = GFXFormatR8G8B8A8;
  32. for (U32 i = 0; i < CubeFaces; i++)
  33. {
  34. mRTView[i] = NULL;
  35. }
  36. }
  37. GFXD3D11Cubemap::~GFXD3D11Cubemap()
  38. {
  39. releaseSurfaces();
  40. }
  41. void GFXD3D11Cubemap::releaseSurfaces()
  42. {
  43. if (mDynamic)
  44. GFXTextureManager::removeEventDelegate(this, &GFXD3D11Cubemap::_onTextureEvent);
  45. for (U32 i = 0; i < CubeFaces; i++)
  46. {
  47. SAFE_RELEASE(mRTView[i]);
  48. }
  49. SAFE_RELEASE(mDSView);
  50. SAFE_RELEASE(mSRView);
  51. SAFE_RELEASE(mTexture);
  52. }
  53. void GFXD3D11Cubemap::_onTextureEvent(GFXTexCallbackCode code)
  54. {
  55. if (code == GFXZombify)
  56. releaseSurfaces();
  57. else if (code == GFXResurrect)
  58. initDynamic(mTexSize);
  59. }
  60. void GFXD3D11Cubemap::initStatic(GFXTexHandle *faces)
  61. {
  62. AssertFatal( faces, "GFXD3D11Cubemap::initStatic - Got null GFXTexHandle!" );
  63. AssertFatal( *faces, "empty texture passed to CubeMap::create" );
  64. // NOTE - check tex sizes on all faces - they MUST be all same size
  65. mTexSize = faces->getWidth();
  66. mFaceFormat = faces->getFormat();
  67. bool compressed = ImageUtil::isCompressedFormat(mFaceFormat);
  68. UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
  69. UINT miscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
  70. if (!compressed)
  71. {
  72. bindFlags |= D3D11_BIND_RENDER_TARGET;
  73. miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
  74. }
  75. mMipMapLevels = faces->getPointer()->getMipLevels();
  76. if (mMipMapLevels < 1 && !compressed)
  77. mAutoGenMips = true;
  78. D3D11_TEXTURE2D_DESC desc;
  79. ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
  80. desc.Width = mTexSize;
  81. desc.Height = mTexSize;
  82. desc.MipLevels = mAutoGenMips ? 0 : mMipMapLevels;
  83. desc.ArraySize = 6;
  84. desc.Format = GFXD3D11TextureFormat[mFaceFormat];
  85. desc.SampleDesc.Count = 1;
  86. desc.SampleDesc.Quality = 0;
  87. desc.Usage = D3D11_USAGE_DEFAULT;
  88. desc.BindFlags = bindFlags;
  89. desc.MiscFlags = miscFlags;
  90. desc.CPUAccessFlags = 0;
  91. HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &mTexture);
  92. if (FAILED(hr))
  93. {
  94. AssertFatal(false, "GFXD3D11Cubemap:initStatic(GFXTexhandle *faces) - CreateTexture2D failure");
  95. }
  96. for (U32 i = 0; i < CubeFaces; i++)
  97. {
  98. GFXD3D11TextureObject *texObj = static_cast<GFXD3D11TextureObject*>((GFXTextureObject*)faces[i]);
  99. for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++)
  100. {
  101. U32 subResource = D3D11CalcSubresource(currentMip, i, mMipMapLevels);
  102. D3D11DEVICECONTEXT->CopySubresourceRegion(mTexture, subResource, 0, 0, 0, texObj->get2DTex(), currentMip, NULL);
  103. }
  104. }
  105. D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
  106. SMViewDesc.Format = GFXD3D11TextureFormat[mFaceFormat];
  107. SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
  108. SMViewDesc.TextureCube.MipLevels = mAutoGenMips ? -1 : mMipMapLevels;
  109. SMViewDesc.TextureCube.MostDetailedMip = 0;
  110. hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
  111. if (FAILED(hr))
  112. {
  113. AssertFatal(false, "GFXD3D11Cubemap::initStatic(GFXTexHandle *faces) - texcube shader resource view creation failure");
  114. }
  115. //Generate mips
  116. if (mAutoGenMips && !compressed)
  117. {
  118. D3D11DEVICECONTEXT->GenerateMips(mSRView);
  119. //get mip level count
  120. D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
  121. mSRView->GetDesc(&viewDesc);
  122. mMipMapLevels = viewDesc.TextureCube.MipLevels;
  123. }
  124. }
  125. void GFXD3D11Cubemap::initStatic(DDSFile *dds)
  126. {
  127. AssertFatal(dds, "GFXD3D11Cubemap::initStatic - Got null DDS file!");
  128. AssertFatal(dds->isCubemap(), "GFXD3D11Cubemap::initStatic - Got non-cubemap DDS file!");
  129. AssertFatal(dds->mSurfaces.size() == 6, "GFXD3D11Cubemap::initStatic - DDS has less than 6 surfaces!");
  130. // NOTE - check tex sizes on all faces - they MUST be all same size
  131. mTexSize = dds->getWidth();
  132. mFaceFormat = dds->getFormat();
  133. mMipMapLevels = dds->getMipLevels();
  134. D3D11_TEXTURE2D_DESC desc;
  135. desc.Width = mTexSize;
  136. desc.Height = mTexSize;
  137. desc.MipLevels = mMipMapLevels;
  138. desc.ArraySize = CubeFaces;
  139. desc.Format = GFXD3D11TextureFormat[mFaceFormat];
  140. desc.SampleDesc.Count = 1;
  141. desc.SampleDesc.Quality = 0;
  142. desc.Usage = D3D11_USAGE_IMMUTABLE;
  143. desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
  144. desc.CPUAccessFlags = 0;
  145. desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
  146. D3D11_SUBRESOURCE_DATA* pData = new D3D11_SUBRESOURCE_DATA[CubeFaces * mMipMapLevels];
  147. for (U32 currentFace = 0; currentFace < CubeFaces; currentFace++)
  148. {
  149. if (!dds->mSurfaces[currentFace])
  150. continue;
  151. // convert to Z up
  152. const U32 faceIndex = _zUpFaceIndex(currentFace);
  153. for(U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++)
  154. {
  155. const U32 dataIndex = faceIndex * mMipMapLevels + currentMip;
  156. pData[dataIndex].pSysMem = dds->mSurfaces[currentFace]->mMips[currentMip];
  157. pData[dataIndex].SysMemPitch = dds->getSurfacePitch(currentMip);
  158. pData[dataIndex].SysMemSlicePitch = 0;
  159. }
  160. }
  161. HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, pData, &mTexture);
  162. if (FAILED(hr))
  163. {
  164. AssertFatal(false, "GFXD3D11Cubemap::initStatic(DDSFile *dds) - CreateTexture2D failure");
  165. }
  166. delete [] pData;
  167. D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
  168. SMViewDesc.Format = GFXD3D11TextureFormat[mFaceFormat];
  169. SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
  170. SMViewDesc.TextureCube.MipLevels = mMipMapLevels;
  171. SMViewDesc.TextureCube.MostDetailedMip = 0;
  172. hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
  173. if(FAILED(hr))
  174. {
  175. AssertFatal(false, "GFXD3D11Cubemap::initStatic(DDSFile *dds) - CreateTexture2D call failure");
  176. }
  177. }
  178. void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
  179. {
  180. if(!mDynamic)
  181. GFXTextureManager::addEventDelegate(this, &GFXD3D11Cubemap::_onTextureEvent);
  182. mDynamic = true;
  183. mAutoGenMips = true;
  184. mTexSize = texSize;
  185. mFaceFormat = faceFormat;
  186. mMipMapLevels = 0;
  187. bool compressed = ImageUtil::isCompressedFormat(mFaceFormat);
  188. UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
  189. UINT miscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
  190. if (!compressed)
  191. {
  192. bindFlags |= D3D11_BIND_RENDER_TARGET;
  193. miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
  194. }
  195. D3D11_TEXTURE2D_DESC desc;
  196. desc.Width = mTexSize;
  197. desc.Height = mTexSize;
  198. desc.MipLevels = 0;
  199. desc.ArraySize = 6;
  200. desc.Format = GFXD3D11TextureFormat[mFaceFormat];
  201. desc.SampleDesc.Count = 1;
  202. desc.SampleDesc.Quality = 0;
  203. desc.Usage = D3D11_USAGE_DEFAULT;
  204. desc.BindFlags = bindFlags;
  205. desc.CPUAccessFlags = 0;
  206. desc.MiscFlags = miscFlags;
  207. HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &mTexture);
  208. D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
  209. SMViewDesc.Format = GFXD3D11TextureFormat[mFaceFormat];
  210. SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
  211. SMViewDesc.TextureCube.MipLevels = -1;
  212. SMViewDesc.TextureCube.MostDetailedMip = 0;
  213. hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
  214. if(FAILED(hr))
  215. {
  216. AssertFatal(false, "GFXD3D11Cubemap::initDynamic - CreateTexture2D call failure");
  217. }
  218. //Generate mips
  219. if (mAutoGenMips && !compressed)
  220. {
  221. D3D11DEVICECONTEXT->GenerateMips(mSRView);
  222. //get mip level count
  223. D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
  224. mSRView->GetDesc(&viewDesc);
  225. mMipMapLevels = viewDesc.TextureCube.MipLevels;
  226. }
  227. D3D11_RENDER_TARGET_VIEW_DESC viewDesc;
  228. viewDesc.Format = desc.Format;
  229. viewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
  230. viewDesc.Texture2DArray.ArraySize = 1;
  231. viewDesc.Texture2DArray.MipSlice = 0;
  232. for (U32 i = 0; i < CubeFaces; i++)
  233. {
  234. viewDesc.Texture2DArray.FirstArraySlice = i;
  235. hr = D3D11DEVICE->CreateRenderTargetView(mTexture, &viewDesc, &mRTView[i]);
  236. if(FAILED(hr))
  237. {
  238. AssertFatal(false, "GFXD3D11Cubemap::initDynamic - CreateRenderTargetView call failure");
  239. }
  240. }
  241. D3D11_TEXTURE2D_DESC depthTexDesc;
  242. depthTexDesc.Width = mTexSize;
  243. depthTexDesc.Height = mTexSize;
  244. depthTexDesc.MipLevels = 1;
  245. depthTexDesc.ArraySize = 1;
  246. depthTexDesc.SampleDesc.Count = 1;
  247. depthTexDesc.SampleDesc.Quality = 0;
  248. depthTexDesc.Format = DXGI_FORMAT_D32_FLOAT;
  249. depthTexDesc.Usage = D3D11_USAGE_DEFAULT;
  250. depthTexDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
  251. depthTexDesc.CPUAccessFlags = 0;
  252. depthTexDesc.MiscFlags = 0;
  253. ID3D11Texture2D* depthTex = 0;
  254. hr = D3D11DEVICE->CreateTexture2D(&depthTexDesc, 0, &depthTex);
  255. if(FAILED(hr))
  256. {
  257. AssertFatal(false, "GFXD3D11Cubemap::initDynamic - CreateTexture2D for depth stencil call failure");
  258. }
  259. // Create the depth stencil view for the entire cube
  260. D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
  261. dsvDesc.Format = depthTexDesc.Format; //The format must match the depth texture we created above
  262. dsvDesc.Flags = 0;
  263. dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
  264. dsvDesc.Texture2D.MipSlice = 0;
  265. hr = D3D11DEVICE->CreateDepthStencilView(depthTex, &dsvDesc, &mDSView);
  266. if(FAILED(hr))
  267. {
  268. AssertFatal(false, "GFXD3D11Cubemap::initDynamic - CreateDepthStencilView call failure");
  269. }
  270. SAFE_RELEASE(depthTex);
  271. }
  272. //-----------------------------------------------------------------------------
  273. // Set the cubemap to the specified texture unit num
  274. //-----------------------------------------------------------------------------
  275. void GFXD3D11Cubemap::setToTexUnit(U32 tuNum)
  276. {
  277. D3D11DEVICECONTEXT->PSSetShaderResources(tuNum, 1, &mSRView);
  278. }
  279. void GFXD3D11Cubemap::zombify()
  280. {
  281. // Static cubemaps are handled by D3D
  282. if( mDynamic )
  283. releaseSurfaces();
  284. }
  285. void GFXD3D11Cubemap::resurrect()
  286. {
  287. // Static cubemaps are handled by D3D
  288. if( mDynamic )
  289. initDynamic( mTexSize, mFaceFormat );
  290. }
  291. ID3D11ShaderResourceView* GFXD3D11Cubemap::getSRView()
  292. {
  293. return mSRView;
  294. }
  295. ID3D11RenderTargetView* GFXD3D11Cubemap::getRTView(U32 faceIdx)
  296. {
  297. AssertFatal(faceIdx < CubeFaces, "GFXD3D11Cubemap::getRTView - face index out of bounds");
  298. return mRTView[faceIdx];
  299. }
  300. ID3D11RenderTargetView** GFXD3D11Cubemap::getRTViewArray()
  301. {
  302. return mRTView;
  303. }
  304. ID3D11DepthStencilView* GFXD3D11Cubemap::getDSView()
  305. {
  306. return mDSView;
  307. }
  308. ID3D11Texture2D* GFXD3D11Cubemap::get2DTex()
  309. {
  310. return mTexture;
  311. }