gfxD3D11Cubemap.cpp 11 KB

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