gfxD3D11Cubemap.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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), mTexSize(0)
  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::_init(U32 size, GFXFormat format, U32 mipLevels, bool isDynamic, DDSFile* dds, GFXTexHandle* faces) {
  61. releaseSurfaces();
  62. mTexSize = size;
  63. mFaceFormat = format;
  64. mMipMapLevels = mipLevels;
  65. mDynamic = isDynamic;
  66. mAutoGenMips = (mipLevels == 0);
  67. bool compressed = ImageUtil::isCompressedFormat(mFaceFormat);
  68. UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
  69. UINT miscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
  70. if (!compressed) {
  71. bindFlags |= D3D11_BIND_RENDER_TARGET;
  72. miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
  73. }
  74. D3D11_TEXTURE2D_DESC desc = {};
  75. desc.Width = mTexSize;
  76. desc.Height = mTexSize;
  77. desc.MipLevels = mAutoGenMips ? 0 : mMipMapLevels;
  78. desc.ArraySize = CubeFaces;
  79. desc.Format = GFXD3D11TextureFormat[mFaceFormat];
  80. desc.SampleDesc.Count = 1;
  81. desc.Usage = D3D11_USAGE_DEFAULT;
  82. desc.BindFlags = bindFlags;
  83. desc.CPUAccessFlags = 0;
  84. desc.MiscFlags = miscFlags;
  85. D3D11_SUBRESOURCE_DATA* pData = nullptr;
  86. if (dds) {
  87. pData = new D3D11_SUBRESOURCE_DATA[CubeFaces * mMipMapLevels];
  88. for (U32 i = 0; i < CubeFaces; i++) {
  89. U32 faceIndex = zUpFaceIndex(i);
  90. for (U32 mip = 0; mip < mMipMapLevels; mip++) {
  91. U32 index = faceIndex * mMipMapLevels + mip;
  92. pData[index].pSysMem = dds->mSurfaces[i]->mMips[mip];
  93. pData[index].SysMemPitch = dds->getSurfacePitch(mip);
  94. pData[index].SysMemSlicePitch = 0;
  95. }
  96. }
  97. }
  98. HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, pData, &mTexture);
  99. delete[] pData;
  100. AssertFatal(SUCCEEDED(hr), "GFXD3D11Cubemap::_init - CreateTexture2D failed");
  101. if (faces)
  102. {
  103. for (U32 i = 0; i < CubeFaces; i++)
  104. {
  105. GFXD3D11TextureObject* texObj = static_cast<GFXD3D11TextureObject*>((GFXTextureObject*)faces[i]);
  106. for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++)
  107. {
  108. U32 subResource = D3D11CalcSubresource(currentMip, i, mMipMapLevels);
  109. D3D11DEVICECONTEXT->CopySubresourceRegion(mTexture, subResource, 0, 0, 0, texObj->get2DTex(), currentMip, NULL);
  110. }
  111. }
  112. }
  113. D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc = {};
  114. viewDesc.Format = GFXD3D11TextureFormat[mFaceFormat];
  115. viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
  116. viewDesc.TextureCube.MipLevels = mAutoGenMips ? -1 : mMipMapLevels;
  117. hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &viewDesc, &mSRView);
  118. AssertFatal(SUCCEEDED(hr), "GFXD3D11Cubemap::_init - CreateShaderResourceView failed");
  119. if (mAutoGenMips && !compressed) {
  120. D3D11DEVICECONTEXT->GenerateMips(mSRView);
  121. //get mip level count
  122. D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
  123. mSRView->GetDesc(&viewDesc);
  124. mMipMapLevels = viewDesc.TextureCube.MipLevels;
  125. }
  126. if (isDynamic) {
  127. for (U32 i = 0; i < CubeFaces; i++) {
  128. D3D11_RENDER_TARGET_VIEW_DESC rtViewDesc = {};
  129. rtViewDesc.Format = desc.Format;
  130. rtViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
  131. rtViewDesc.Texture2DArray.MipSlice = 0;
  132. rtViewDesc.Texture2DArray.FirstArraySlice = i;
  133. rtViewDesc.Texture2DArray.ArraySize = 1;
  134. hr = D3D11DEVICE->CreateRenderTargetView(mTexture, &rtViewDesc, &mRTView[i]);
  135. AssertFatal(SUCCEEDED(hr), "GFXD3D11Cubemap::_init - CreateRenderTargetView failed");
  136. }
  137. }
  138. }
  139. void GFXD3D11Cubemap::initStatic(GFXTexHandle *faces)
  140. {
  141. AssertFatal( faces, "GFXD3D11Cubemap::initStatic - Got null GFXTexHandle!" );
  142. AssertFatal( *faces, "empty texture passed to CubeMap::create" );
  143. _init(faces->getWidth(), faces->getFormat(), faces->getPointer()->getMipLevels(), false, nullptr, faces);
  144. }
  145. void GFXD3D11Cubemap::initStatic(DDSFile *dds)
  146. {
  147. AssertFatal(dds, "GFXD3D11Cubemap::initStatic - Got null DDS file!");
  148. AssertFatal(dds->isCubemap(), "GFXD3D11Cubemap::initStatic - Got non-cubemap DDS file!");
  149. AssertFatal(dds->mSurfaces.size() == 6, "GFXD3D11Cubemap::initStatic - DDS has less than 6 surfaces!");
  150. _init(dds->getWidth(), dds->getFormat(), dds->getMipLevels(), false, dds, nullptr);
  151. }
  152. void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat, U32 mipLevels)
  153. {
  154. _init(texSize, faceFormat, mipLevels, true);
  155. }
  156. void GFXD3D11Cubemap::generateMipMaps()
  157. {
  158. //Generate mips
  159. D3D11DEVICECONTEXT->GenerateMips(mSRView);
  160. //get mip level count
  161. D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
  162. mSRView->GetDesc(&viewDesc);
  163. mMipMapLevels = viewDesc.TextureCube.MipLevels;
  164. }
  165. //-----------------------------------------------------------------------------
  166. // Set the cubemap to the specified texture unit num
  167. //-----------------------------------------------------------------------------
  168. void GFXD3D11Cubemap::setToTexUnit(U32 tuNum)
  169. {
  170. D3D11DEVICECONTEXT->PSSetShaderResources(tuNum, 1, &mSRView);
  171. }
  172. void GFXD3D11Cubemap::zombify()
  173. {
  174. // Static cubemaps are handled by D3D
  175. if( mDynamic )
  176. releaseSurfaces();
  177. }
  178. void GFXD3D11Cubemap::resurrect()
  179. {
  180. // Static cubemaps are handled by D3D
  181. if( mDynamic )
  182. initDynamic( mTexSize, mFaceFormat );
  183. }
  184. ID3D11ShaderResourceView* GFXD3D11Cubemap::getSRView()
  185. {
  186. return mSRView;
  187. }
  188. ID3D11RenderTargetView* GFXD3D11Cubemap::getRTView(U32 faceIdx)
  189. {
  190. AssertFatal(faceIdx < CubeFaces, "GFXD3D11Cubemap::getRTView - face index out of bounds");
  191. return mRTView[faceIdx];
  192. }
  193. ID3D11DepthStencilView* GFXD3D11Cubemap::getDSView()
  194. {
  195. return mDSView;
  196. }
  197. ID3D11Texture2D* GFXD3D11Cubemap::get2DTex()
  198. {
  199. return mTexture;
  200. }
  201. //-----------------------------------------------------------------------------
  202. // Cubemap Array
  203. //-----------------------------------------------------------------------------
  204. GFXD3D11CubemapArray::GFXD3D11CubemapArray() : mTexture(NULL), mSRView(NULL)
  205. {
  206. }
  207. GFXD3D11CubemapArray::~GFXD3D11CubemapArray()
  208. {
  209. SAFE_RELEASE(mSRView);
  210. SAFE_RELEASE(mTexture);
  211. }
  212. void GFXD3D11CubemapArray::_init(U32 cubemapCount, U32 size, GFXFormat format) {
  213. SAFE_RELEASE(mSRView);
  214. SAFE_RELEASE(mTexture);
  215. mNumCubemaps = cubemapCount;
  216. mSize = size;
  217. mFormat = format;
  218. UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
  219. UINT miscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
  220. D3D11_TEXTURE2D_DESC desc = {};
  221. desc.Width = mSize;
  222. desc.Height = mSize;
  223. desc.MipLevels = mMipMapLevels;
  224. desc.ArraySize = CubeFaces * cubemapCount;
  225. desc.Format = GFXD3D11TextureFormat[mFormat];
  226. desc.SampleDesc.Count = 1;
  227. desc.Usage = D3D11_USAGE_DEFAULT;
  228. desc.BindFlags = bindFlags;
  229. desc.MiscFlags = miscFlags;
  230. desc.CPUAccessFlags = 0;
  231. if (desc.ArraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION)
  232. {
  233. AssertFatal(false, avar("CubemapArray size exceeds maximum array size of %d", D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION));
  234. return;
  235. }
  236. HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &mTexture);
  237. AssertFatal(SUCCEEDED(hr), "GFXD3D11CubemapArray::_init - CreateTexture2D failed");
  238. D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc = {};
  239. viewDesc.Format = GFXD3D11TextureFormat[mFormat];
  240. viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
  241. viewDesc.TextureCubeArray.MipLevels = mMipMapLevels;
  242. viewDesc.TextureCubeArray.MostDetailedMip = 0;
  243. viewDesc.TextureCubeArray.NumCubes = mNumCubemaps;
  244. viewDesc.TextureCubeArray.First2DArrayFace = 0;
  245. hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &viewDesc, &mSRView);
  246. AssertFatal(SUCCEEDED(hr), "GFXD3D11CubemapArray::_init - CreateShaderResourceView failed");
  247. }
  248. //TODO: really need a common private 'init' function to avoid code double up with these init* functions
  249. void GFXD3D11CubemapArray::init(GFXCubemapHandle *cubemaps, const U32 cubemapCount)
  250. {
  251. AssertFatal(cubemaps, "GFXD3D11CubemapArray::initStatic - Got null GFXCubemapHandle!");
  252. AssertFatal(*cubemaps, "GFXD3D11CubemapArray::initStatic - Got empty cubemap!");
  253. setCubeTexSize(cubemaps);
  254. _init(cubemapCount, cubemaps[0]->getSize(), cubemaps[0]->getFormat());
  255. }
  256. //Just allocate the cubemap array but we don't upload any data
  257. void GFXD3D11CubemapArray::init(const U32 cubemapCount, const U32 cubemapFaceSize, const GFXFormat format)
  258. {
  259. setCubeTexSize(cubemapFaceSize);
  260. _init(cubemapCount, cubemapFaceSize, format);
  261. }
  262. void GFXD3D11CubemapArray::updateTexture(const GFXCubemapHandle &cubemap, const U32 slot)
  263. {
  264. AssertFatal(slot <= mNumCubemaps, "GFXD3D11CubemapArray::updateTexture - trying to update a cubemap texture that is out of bounds!");
  265. AssertFatal(mFormat == cubemap->getFormat(), "GFXD3D11CubemapArray::updateTexture - Destination format doesn't match");
  266. AssertFatal(mMipMapLevels == cubemap->getMipMapLevels(), "GFXD3D11CubemapArray::updateTexture - Destination mip levels doesn't match");
  267. if (mSize != cubemap->getSize() || mFormat != cubemap->getFormat() || mMipMapLevels != cubemap->getMipMapLevels()) {
  268. _init(mNumCubemaps, cubemap->getSize(), cubemap->getFormat());
  269. }
  270. GFXD3D11Cubemap* pCubeObj = static_cast<GFXD3D11Cubemap*>((GFXCubemap*)cubemap);
  271. ID3D11Resource* pDstRes = pCubeObj->get2DTex();
  272. for (U32 face = 0; face < CubeFaces; face++) {
  273. const U32 arraySlice = face + CubeFaces * slot;
  274. for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++) {
  275. const U32 srcSubResource = D3D11CalcSubresource(currentMip, face, mMipMapLevels);
  276. const U32 dstSubResource = D3D11CalcSubresource(currentMip, arraySlice, mMipMapLevels);
  277. D3D11DEVICECONTEXT->CopySubresourceRegion(mTexture, dstSubResource, 0, 0, 0, pDstRes, srcSubResource, NULL);
  278. }
  279. }
  280. }
  281. void GFXD3D11CubemapArray::copyTo(GFXCubemapArray* pDstCubemap) {
  282. AssertFatal(pDstCubemap, "GFXD3D11CubemapArray::copyTo - Got null GFXCubemapArray");
  283. if (pDstCubemap->getSize() != mSize || pDstCubemap->getFormat() != mFormat || pDstCubemap->getMipMapLevels() != mMipMapLevels) {
  284. pDstCubemap->init(mNumCubemaps, mSize, mFormat);
  285. }
  286. GFXD3D11CubemapArray* pDstCube = static_cast<GFXD3D11CubemapArray*>(pDstCubemap);
  287. ID3D11Resource* pDstRes = pDstCube->get2DTex();
  288. for (U32 cubeMap = 0; cubeMap < mNumCubemaps; cubeMap++) {
  289. for (U32 face = 0; face < CubeFaces; face++) {
  290. const U32 arraySlice = face + CubeFaces * cubeMap;
  291. for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++) {
  292. const U32 subResource = D3D11CalcSubresource(currentMip, arraySlice, mMipMapLevels);
  293. D3D11DEVICECONTEXT->CopySubresourceRegion(pDstRes, subResource, 0, 0, 0, mTexture, subResource, NULL);
  294. }
  295. }
  296. }
  297. }
  298. void GFXD3D11CubemapArray::setToTexUnit(U32 tuNum)
  299. {
  300. D3D11DEVICECONTEXT->PSSetShaderResources(tuNum, 1, &mSRView);
  301. }
  302. void GFXD3D11CubemapArray::zombify()
  303. {
  304. // Static cubemaps are handled by D3D
  305. }
  306. void GFXD3D11CubemapArray::resurrect()
  307. {
  308. // Static cubemaps are handled by D3D
  309. }