Browse Source

Merge pull request #1416 from marauder2k9-torque/Fix-CubemapBaking-Resizing

fix and cleanup
Brian Roberts 6 months ago
parent
commit
77e336627b
2 changed files with 120 additions and 302 deletions
  1. 117 302
      Engine/source/gfx/D3D11/gfxD3D11Cubemap.cpp
  2. 3 0
      Engine/source/gfx/D3D11/gfxD3D11Cubemap.h

+ 117 - 302
Engine/source/gfx/D3D11/gfxD3D11Cubemap.cpp

@@ -65,200 +65,62 @@ void GFXD3D11Cubemap::_onTextureEvent(GFXTexCallbackCode code)
       initDynamic(mTexSize);
 }
 
-void GFXD3D11Cubemap::initStatic(GFXTexHandle *faces)
-{
-   AssertFatal( faces, "GFXD3D11Cubemap::initStatic - Got null GFXTexHandle!" );
-	AssertFatal( *faces, "empty texture passed to CubeMap::create" );
-  
-	// NOTE - check tex sizes on all faces - they MUST be all same size
-	mTexSize = faces->getWidth();
-	mFaceFormat = faces->getFormat();
-   bool compressed = ImageUtil::isCompressedFormat(mFaceFormat);
-
-   UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
-   UINT miscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
-   if (!compressed)
-   {
-      bindFlags |= D3D11_BIND_RENDER_TARGET;
-      miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
-   }
-
-   mMipMapLevels = faces->getPointer()->getMipLevels();
-   if (mMipMapLevels < 1 && !compressed)
-      mAutoGenMips = true;
-
-	D3D11_TEXTURE2D_DESC desc;
-	ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
-	desc.Width = mTexSize;
-	desc.Height = mTexSize;
-   desc.MipLevels = mAutoGenMips ? 0 : mMipMapLevels;
-	desc.ArraySize = CubeFaces;
-	desc.Format = GFXD3D11TextureFormat[mFaceFormat];
-	desc.SampleDesc.Count = 1;
-	desc.SampleDesc.Quality = 0;
-	desc.Usage = D3D11_USAGE_DEFAULT;
-	desc.BindFlags = bindFlags;
-	desc.MiscFlags = miscFlags;
-	desc.CPUAccessFlags = 0;
-
-	HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &mTexture);
-
-	if (FAILED(hr))
-	{
-		AssertFatal(false, "GFXD3D11Cubemap:initStatic(GFXTexhandle *faces) - CreateTexture2D failure");
-	}
-   
-   for (U32 i = 0; i < CubeFaces; i++)
-   {
-      GFXD3D11TextureObject *texObj = static_cast<GFXD3D11TextureObject*>((GFXTextureObject*)faces[i]);
-      for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++)
-      {
-         U32 subResource = D3D11CalcSubresource(currentMip, i, mMipMapLevels);
-         D3D11DEVICECONTEXT->CopySubresourceRegion(mTexture, subResource, 0, 0, 0, texObj->get2DTex(), currentMip, NULL);
-      }
-   }
-   
-	D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
-	SMViewDesc.Format = GFXD3D11TextureFormat[mFaceFormat];
-	SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
-   SMViewDesc.TextureCube.MipLevels = mAutoGenMips ? -1 : mMipMapLevels;
-	SMViewDesc.TextureCube.MostDetailedMip = 0;
-
-	hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
-	if (FAILED(hr))
-	{
-		AssertFatal(false, "GFXD3D11Cubemap::initStatic(GFXTexHandle *faces) - texcube shader resource view  creation failure");
-	} 
-
-   //Generate mips
-   if (mAutoGenMips && !compressed)
-   {
-      D3D11DEVICECONTEXT->GenerateMips(mSRView);
-      //get mip level count
-      D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
-      mSRView->GetDesc(&viewDesc);
-      mMipMapLevels = viewDesc.TextureCube.MipLevels;
-   }
-
-}
-
-void GFXD3D11Cubemap::initStatic(DDSFile *dds)
-{
-   AssertFatal(dds, "GFXD3D11Cubemap::initStatic - Got null DDS file!");
-   AssertFatal(dds->isCubemap(), "GFXD3D11Cubemap::initStatic - Got non-cubemap DDS file!");
-   AssertFatal(dds->mSurfaces.size() == 6, "GFXD3D11Cubemap::initStatic - DDS has less than 6 surfaces!");  
-   
-   // NOTE - check tex sizes on all faces - they MUST be all same size
-   mTexSize = dds->getWidth();
-   mFaceFormat = dds->getFormat();
-   mMipMapLevels = dds->getMipLevels();
-
-	D3D11_TEXTURE2D_DESC desc;
-
-	desc.Width = mTexSize;
-	desc.Height = mTexSize;
-   desc.MipLevels = mMipMapLevels;
-	desc.ArraySize = CubeFaces;
-	desc.Format = GFXD3D11TextureFormat[mFaceFormat];
-	desc.SampleDesc.Count = 1;
-	desc.SampleDesc.Quality = 0;
-	desc.Usage = D3D11_USAGE_IMMUTABLE;
-	desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
-	desc.CPUAccessFlags = 0;
-	desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
-
-	D3D11_SUBRESOURCE_DATA* pData = new D3D11_SUBRESOURCE_DATA[CubeFaces * mMipMapLevels];
-   for (U32 currentFace = 0; currentFace < CubeFaces; currentFace++)
-	{
-		if (!dds->mSurfaces[currentFace])
-			continue;
-
-      // convert to Z up
-      const U32 faceIndex = zUpFaceIndex(currentFace);
-
-		for(U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++)
-		{
-         const U32 dataIndex = faceIndex * mMipMapLevels + currentMip;
-			pData[dataIndex].pSysMem = dds->mSurfaces[currentFace]->mMips[currentMip];
-			pData[dataIndex].SysMemPitch = dds->getSurfacePitch(currentMip);
-         pData[dataIndex].SysMemSlicePitch = 0;
-		}
-
-	}
-
-   HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, pData, &mTexture);
-   if (FAILED(hr))
-   {
-      AssertFatal(false, "GFXD3D11Cubemap::initStatic(DDSFile *dds) - CreateTexture2D failure");
-   }
-
-	delete [] pData;
-
-	D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
-	SMViewDesc.Format = GFXD3D11TextureFormat[mFaceFormat];
-	SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
-	SMViewDesc.TextureCube.MipLevels = mMipMapLevels;
-	SMViewDesc.TextureCube.MostDetailedMip = 0;
-
-	hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
-
-	if(FAILED(hr)) 
-	{
-		AssertFatal(false, "GFXD3D11Cubemap::initStatic(DDSFile *dds) - CreateTexture2D call failure");
-	}
-}
-
-void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat, U32 mipLevels)
-{
-   if (!mDynamic)
-      GFXTextureManager::addEventDelegate(this, &GFXD3D11Cubemap::_onTextureEvent);
-
-   mDynamic = true;
-   mTexSize = texSize;
-   mFaceFormat = faceFormat;
-   if (!mipLevels)
-      mAutoGenMips = true;
+void GFXD3D11Cubemap::_init(U32 size, GFXFormat format, U32 mipLevels, bool isDynamic, DDSFile* dds, GFXTexHandle* faces) {
+   releaseSurfaces();
 
+   mTexSize = size;
+   mFaceFormat = format;
    mMipMapLevels = mipLevels;
-
+   mDynamic = isDynamic;
+   mAutoGenMips = (mipLevels == 0);
    bool compressed = ImageUtil::isCompressedFormat(mFaceFormat);
 
    UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
    UINT miscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
-   if (!compressed)
-   {
+   if (!compressed) {
       bindFlags |= D3D11_BIND_RENDER_TARGET;
       miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
    }
 
    D3D11_TEXTURE2D_DESC desc = {};
-
    desc.Width = mTexSize;
    desc.Height = mTexSize;
-   desc.MipLevels = mMipMapLevels;
-   desc.ArraySize = 6;
+   desc.MipLevels = mAutoGenMips ? 0 : mMipMapLevels;
+   desc.ArraySize = CubeFaces;
    desc.Format = GFXD3D11TextureFormat[mFaceFormat];
    desc.SampleDesc.Count = 1;
-   desc.SampleDesc.Quality = 0;
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.BindFlags = bindFlags;
    desc.CPUAccessFlags = 0;
    desc.MiscFlags = miscFlags;
 
+   D3D11_SUBRESOURCE_DATA* pData = nullptr;
+   if (dds) {
+      pData = new D3D11_SUBRESOURCE_DATA[CubeFaces * mMipMapLevels];
+      for (U32 i = 0; i < CubeFaces; i++) {
+         U32 faceIndex = zUpFaceIndex(i);
+         for (U32 mip = 0; mip < mMipMapLevels; mip++) {
+            U32 index = faceIndex * mMipMapLevels + mip;
+            pData[index].pSysMem = dds->mSurfaces[i]->mMips[mip];
+            pData[index].SysMemPitch = dds->getSurfacePitch(mip);
+            pData[index].SysMemSlicePitch = 0;
+         }
+      }
+   }
 
-   HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &mTexture);
+   HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, pData, &mTexture);
+   delete[] pData;
+   AssertFatal(SUCCEEDED(hr), "GFXD3D11Cubemap::_init - CreateTexture2D failed");
 
-   D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc = {};
-   SMViewDesc.Format = GFXD3D11TextureFormat[mFaceFormat];
-   SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
-   SMViewDesc.TextureCube.MipLevels = -1;
-   SMViewDesc.TextureCube.MostDetailedMip = 0;
+   D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc = {};
+   viewDesc.Format = GFXD3D11TextureFormat[mFaceFormat];
+   viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+   viewDesc.TextureCube.MipLevels = mAutoGenMips ? -1 : mMipMapLevels;
 
-   hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
+   hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &viewDesc, &mSRView);
+   AssertFatal(SUCCEEDED(hr), "GFXD3D11Cubemap::_init - CreateShaderResourceView failed");
 
-   //Generate mips
-   if (mAutoGenMips && !compressed)
-   {
+   if (mAutoGenMips && !compressed) {
       D3D11DEVICECONTEXT->GenerateMips(mSRView);
       //get mip level count
       D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
@@ -266,29 +128,44 @@ void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat, U32 mipLeve
       mMipMapLevels = viewDesc.TextureCube.MipLevels;
    }
 
-
-   if (FAILED(hr))
-   {
-      AssertFatal(false, "GFXD3D11Cubemap::initDynamic - CreateTexture2D call failure");
-   }
-
-   for (U32 i = 0; i < CubeFaces; i++)
-   {
-      D3D11_RENDER_TARGET_VIEW_DESC viewDesc = {};
-      viewDesc.Format = desc.Format;
-      viewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
-      viewDesc.Texture2DArray.ArraySize = 1;
-      viewDesc.Texture2DArray.MipSlice = 0;
-      viewDesc.Texture2DArray.FirstArraySlice = i;
-      hr = D3D11DEVICE->CreateRenderTargetView(mTexture, &viewDesc, &mRTView[i]);
-
-      if (FAILED(hr))
-      {
-         AssertFatal(false, "GFXD3D11Cubemap::initDynamic - CreateRenderTargetView call failure");
+   if (isDynamic) {
+      for (U32 i = 0; i < CubeFaces; i++) {
+         D3D11_RENDER_TARGET_VIEW_DESC rtViewDesc = {};
+         rtViewDesc.Format = desc.Format;
+         rtViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+         rtViewDesc.Texture2DArray.MipSlice = 0;
+         rtViewDesc.Texture2DArray.FirstArraySlice = i;
+         rtViewDesc.Texture2DArray.ArraySize = 1;
+         hr = D3D11DEVICE->CreateRenderTargetView(mTexture, &rtViewDesc, &mRTView[i]);
+         AssertFatal(SUCCEEDED(hr), "GFXD3D11Cubemap::_init - CreateRenderTargetView failed");
       }
    }
 }
 
+
+void GFXD3D11Cubemap::initStatic(GFXTexHandle *faces)
+{
+   AssertFatal( faces, "GFXD3D11Cubemap::initStatic - Got null GFXTexHandle!" );
+	AssertFatal( *faces, "empty texture passed to CubeMap::create" );
+  
+   _init(faces->getWidth(), faces->getFormat(), faces->getPointer()->getMipLevels(), false, nullptr, faces);
+
+}
+
+void GFXD3D11Cubemap::initStatic(DDSFile *dds)
+{
+   AssertFatal(dds, "GFXD3D11Cubemap::initStatic - Got null DDS file!");
+   AssertFatal(dds->isCubemap(), "GFXD3D11Cubemap::initStatic - Got non-cubemap DDS file!");
+   AssertFatal(dds->mSurfaces.size() == 6, "GFXD3D11Cubemap::initStatic - DDS has less than 6 surfaces!");  
+   
+   _init(dds->getWidth(), dds->getFormat(), dds->getMipLevels(), false, dds, nullptr);
+}
+
+void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat, U32 mipLevels)
+{
+   _init(texSize, faceFormat, mipLevels, true);
+}
+
 void GFXD3D11Cubemap::generateMipMaps()
 {
    //Generate mips
@@ -357,97 +234,24 @@ GFXD3D11CubemapArray::~GFXD3D11CubemapArray()
    SAFE_RELEASE(mTexture);
 }
 
-//TODO: really need a common private 'init' function to avoid code double up with these init* functions
-void GFXD3D11CubemapArray::init(GFXCubemapHandle *cubemaps, const U32 cubemapCount)
-{
-   AssertFatal(cubemaps, "GFXD3D11CubemapArray::initStatic - Got null GFXCubemapHandle!");
-   AssertFatal(*cubemaps, "GFXD3D11CubemapArray::initStatic - Got empty cubemap!");
-
-   setCubeTexSize(cubemaps);
-   mFormat = cubemaps[0]->getFormat();
-   mNumCubemaps = cubemapCount;
-
-   //create texture object
-   UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
-   UINT miscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
-
-   D3D11_TEXTURE2D_DESC desc;
-   ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
-   desc.Width = mSize;
-   desc.Height = mSize;
-   desc.MipLevels = mMipMapLevels;
-   desc.ArraySize = CubeFaces * cubemapCount;
-   desc.Format = GFXD3D11TextureFormat[mFormat];
-   desc.SampleDesc.Count = 1;
-   desc.SampleDesc.Quality = 0;
-   desc.Usage = D3D11_USAGE_DEFAULT;
-   desc.BindFlags = bindFlags;
-   desc.MiscFlags = miscFlags;
-   desc.CPUAccessFlags = 0;
-
-   HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &mTexture);
-
-   if (FAILED(hr))
-      AssertFatal(false, "GFXD3D11CubemapArray::initStatic - CreateTexture2D failure");
-
-   for (U32 i = 0; i < cubemapCount; i++)
-   {
-      GFXD3D11Cubemap *cubeObj = static_cast<GFXD3D11Cubemap*>((GFXCubemap*)cubemaps[i]);
-      //yes checking the first one(cubemap at index 0) is pointless but saves a further if statement
-      if (cubemaps[i]->getSize() != mSize || cubemaps[i]->getFormat() != mFormat || cubemaps[i]->getMipMapLevels() != mMipMapLevels)
-      {
-         Con::printf("Trying to add an invalid Cubemap to a CubemapArray");
-         //destroy array here first
-         AssertFatal(false, "GFXD3D11CubemapArray::initStatic - invalid cubemap");
-      }
-
-      for (U32 face = 0; face < CubeFaces; face++)
-      {
-         const U32 arraySlice = face + CubeFaces * i;
-         for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++)
-         {
-            const U32 srcSubResource = D3D11CalcSubresource(currentMip, face, mMipMapLevels);
-            const U32 dstSubResource = D3D11CalcSubresource(currentMip, arraySlice, mMipMapLevels);
-            D3D11DEVICECONTEXT->CopySubresourceRegion(mTexture, dstSubResource, 0, 0, 0, cubeObj->get2DTex(), srcSubResource, NULL);
-         }
-      }
-   }
-
-   //create shader resource view
-   D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
-   SMViewDesc.Format = GFXD3D11TextureFormat[mFormat];
-   SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
-   SMViewDesc.TextureCubeArray.MipLevels = mMipMapLevels;
-   SMViewDesc.TextureCubeArray.MostDetailedMip = 0;
-   SMViewDesc.TextureCubeArray.NumCubes = mNumCubemaps;
-   SMViewDesc.TextureCubeArray.First2DArrayFace = 0;
-
-   hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
-   if (FAILED(hr))
-      AssertFatal(false, "GFXD3D11CubemapArray::initStatic - shader resource view  creation failure");
-
-}
+void GFXD3D11CubemapArray::_init(U32 cubemapCount, U32 size, GFXFormat format) {
+   SAFE_RELEASE(mSRView);
+   SAFE_RELEASE(mTexture);
 
-//Just allocate the cubemap array but we don't upload any data
-void GFXD3D11CubemapArray::init(const U32 cubemapCount, const U32 cubemapFaceSize, const GFXFormat format)
-{
-   setCubeTexSize(cubemapFaceSize);
    mNumCubemaps = cubemapCount;
+   mSize = size;
    mFormat = format;
 
-   //create texture object
    UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
    UINT miscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
 
-   D3D11_TEXTURE2D_DESC desc;
-   ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
+   D3D11_TEXTURE2D_DESC desc = {};
    desc.Width = mSize;
    desc.Height = mSize;
    desc.MipLevels = mMipMapLevels;
    desc.ArraySize = CubeFaces * cubemapCount;
    desc.Format = GFXD3D11TextureFormat[mFormat];
    desc.SampleDesc.Count = 1;
-   desc.SampleDesc.Quality = 0;
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.BindFlags = bindFlags;
    desc.MiscFlags = miscFlags;
@@ -460,39 +264,54 @@ void GFXD3D11CubemapArray::init(const U32 cubemapCount, const U32 cubemapFaceSiz
    }
 
    HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &mTexture);
+   AssertFatal(SUCCEEDED(hr), "GFXD3D11CubemapArray::_init - CreateTexture2D failed");
+
+   D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc = {};
+   viewDesc.Format = GFXD3D11TextureFormat[mFormat];
+   viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
+   viewDesc.TextureCubeArray.MipLevels = mMipMapLevels;
+   viewDesc.TextureCubeArray.MostDetailedMip = 0;
+   viewDesc.TextureCubeArray.NumCubes = mNumCubemaps;
+   viewDesc.TextureCubeArray.First2DArrayFace = 0;
+
+   hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &viewDesc, &mSRView);
+   AssertFatal(SUCCEEDED(hr), "GFXD3D11CubemapArray::_init - CreateShaderResourceView failed");
+}
 
-   if (FAILED(hr))
-      AssertFatal(false, "GFXD3D11CubemapArray::initStatic - CreateTexture2D failure");
+//TODO: really need a common private 'init' function to avoid code double up with these init* functions
+void GFXD3D11CubemapArray::init(GFXCubemapHandle *cubemaps, const U32 cubemapCount)
+{
+   AssertFatal(cubemaps, "GFXD3D11CubemapArray::initStatic - Got null GFXCubemapHandle!");
+   AssertFatal(*cubemaps, "GFXD3D11CubemapArray::initStatic - Got empty cubemap!");
+   setCubeTexSize(cubemaps);
 
-   //create shader resource view
-   D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
-   SMViewDesc.Format = GFXD3D11TextureFormat[mFormat];
-   SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
-   SMViewDesc.TextureCubeArray.MipLevels = mMipMapLevels;
-   SMViewDesc.TextureCubeArray.MostDetailedMip = 0;
-   SMViewDesc.TextureCubeArray.NumCubes = mNumCubemaps;
-   SMViewDesc.TextureCubeArray.First2DArrayFace = 0;
+   _init(cubemapCount, cubemaps[0]->getSize(), cubemaps[0]->getFormat());
 
-   hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
-   if (FAILED(hr))
-      AssertFatal(false, "GFXD3D11CubemapArray::initStatic - shader resource view  creation failure");
+}
 
+//Just allocate the cubemap array but we don't upload any data
+void GFXD3D11CubemapArray::init(const U32 cubemapCount, const U32 cubemapFaceSize, const GFXFormat format)
+{
+   setCubeTexSize(cubemapFaceSize);
+
+   _init(cubemapCount, cubemapFaceSize, format);
 }
 
 void GFXD3D11CubemapArray::updateTexture(const GFXCubemapHandle &cubemap, const U32 slot)
 {
    AssertFatal(slot <= mNumCubemaps, "GFXD3D11CubemapArray::updateTexture - trying to update a cubemap texture that is out of bounds!");
    AssertFatal(mFormat == cubemap->getFormat(), "GFXD3D11CubemapArray::updateTexture - Destination format doesn't match");
-   AssertFatal(mSize == cubemap->getSize(), "GFXD3D11CubemapArray::updateTexture - Destination size doesn't match");
    AssertFatal(mMipMapLevels == cubemap->getMipMapLevels(), "GFXD3D11CubemapArray::updateTexture - Destination mip levels doesn't match");
 
-   GFXD3D11Cubemap *pCubeObj = static_cast<GFXD3D11Cubemap*>((GFXCubemap*)cubemap);
-   ID3D11Resource *pDstRes = pCubeObj->get2DTex();
-   for (U32 face = 0; face < CubeFaces; face++)
-   {
+   if (mSize != cubemap->getSize() || mFormat != cubemap->getFormat() || mMipMapLevels != cubemap->getMipMapLevels()) {
+      _init(mNumCubemaps, cubemap->getSize(), cubemap->getFormat());
+   }
+
+   GFXD3D11Cubemap* pCubeObj = static_cast<GFXD3D11Cubemap*>((GFXCubemap*)cubemap);
+   ID3D11Resource* pDstRes = pCubeObj->get2DTex();
+   for (U32 face = 0; face < CubeFaces; face++) {
       const U32 arraySlice = face + CubeFaces * slot;
-      for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++)
-      {
+      for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++) {
          const U32 srcSubResource = D3D11CalcSubresource(currentMip, face, mMipMapLevels);
          const U32 dstSubResource = D3D11CalcSubresource(currentMip, arraySlice, mMipMapLevels);
          D3D11DEVICECONTEXT->CopySubresourceRegion(mTexture, dstSubResource, 0, 0, 0, pDstRes, srcSubResource, NULL);
@@ -500,23 +319,19 @@ void GFXD3D11CubemapArray::updateTexture(const GFXCubemapHandle &cubemap, const
    }
 }
 
-void GFXD3D11CubemapArray::copyTo(GFXCubemapArray *pDstCubemap)
-{
+void GFXD3D11CubemapArray::copyTo(GFXCubemapArray* pDstCubemap) {
    AssertFatal(pDstCubemap, "GFXD3D11CubemapArray::copyTo - Got null GFXCubemapArray");
-   AssertFatal(pDstCubemap->getNumCubemaps() > mNumCubemaps, "GFXD3D11CubemapArray::copyTo - Destination too small");
-   AssertFatal(pDstCubemap->getFormat() == mFormat, "GFXD3D11CubemapArray::copyTo - Destination format doesn't match");
-   AssertFatal(pDstCubemap->getSize() == mSize, "GFXD3D11CubemapArray::copyTo - Destination size doesn't match");
-   AssertFatal(pDstCubemap->getMipMapLevels() == mMipMapLevels, "GFXD3D11CubemapArray::copyTo - Destination mip levels doesn't match");
-
-   GFXD3D11CubemapArray *pDstCube = static_cast<GFXD3D11CubemapArray*>(pDstCubemap);
-   ID3D11Resource *pDstRes = pDstCube->get2DTex();
-   for (U32 cubeMap = 0; cubeMap < mNumCubemaps; cubeMap++)
-   {
-      for (U32 face = 0; face < CubeFaces; face++)
-      {
+
+   if (pDstCubemap->getSize() != mSize || pDstCubemap->getFormat() != mFormat || pDstCubemap->getMipMapLevels() != mMipMapLevels) {
+      pDstCubemap->init(mNumCubemaps, mSize, mFormat);
+   }
+
+   GFXD3D11CubemapArray* pDstCube = static_cast<GFXD3D11CubemapArray*>(pDstCubemap);
+   ID3D11Resource* pDstRes = pDstCube->get2DTex();
+   for (U32 cubeMap = 0; cubeMap < mNumCubemaps; cubeMap++) {
+      for (U32 face = 0; face < CubeFaces; face++) {
          const U32 arraySlice = face + CubeFaces * cubeMap;
-         for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++)
-         {
+         for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++) {
             const U32 subResource = D3D11CalcSubresource(currentMip, arraySlice, mMipMapLevels);
             D3D11DEVICECONTEXT->CopySubresourceRegion(pDstRes, subResource, 0, 0, 0, mTexture, subResource, NULL);
          }

+ 3 - 0
Engine/source/gfx/D3D11/gfxD3D11Cubemap.h

@@ -77,6 +77,7 @@ private:
    /// The callback used to get texture events.
    /// @see GFXTextureManager::addEventDelegate
    void _onTextureEvent(GFXTexCallbackCode code);
+   void _init(U32 size, GFXFormat format, U32 mipLevels, bool isDynamic, DDSFile* dds = nullptr, GFXTexHandle* faces = nullptr);
 };
 
 class GFXD3D11CubemapArray : public GFXCubemapArray
@@ -84,6 +85,7 @@ class GFXD3D11CubemapArray : public GFXCubemapArray
 public:
    GFXD3D11CubemapArray();
    virtual ~GFXD3D11CubemapArray();
+   
    void init(GFXCubemapHandle *cubemaps, const U32 cubemapCount) override;
    void init(const U32 cubemapCount, const U32 cubemapFaceSize, const GFXFormat format) override;
    void updateTexture(const GFXCubemapHandle &cubemap, const U32 slot) override;
@@ -100,6 +102,7 @@ public:
 private:
    friend class GFXD3D11TextureTarget;
    friend class GFXD3D11Device;
+   void _init(U32 cubemapCount, U32 size, GFXFormat format);
 
    ID3D11Texture2D *mTexture;
    ID3D11ShaderResourceView* mSRView; // for shader resource input