Torque3D Documentation / _generateds / gfxD3D11TextureObject.cpp

gfxD3D11TextureObject.cpp

Engine/source/gfx/D3D11/gfxD3D11TextureObject.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2015 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "gfx/D3D11/gfxD3D11Device.h"
 25#include "gfx/D3D11/gfxD3D11TextureObject.h"
 26#include "platform/profiler.h"
 27#include "console/console.h"
 28
 29#ifdef TORQUE_DEBUG
 30U32 GFXD3D11TextureObject::mTexCount = 0;
 31#endif
 32
 33
 34// GFXFormatR8G8B8 has now the same behaviour as GFXFormatR8G8B8X8. 
 35// This is because 24 bit format are now deprecated by microsoft, for data alignment reason there's no changes beetween 24 and 32 bit formats.
 36// DirectX 10-11 both have 24 bit format no longer.
 37
 38
 39GFXD3D11TextureObject::GFXD3D11TextureObject( GFXDevice * d, GFXTextureProfile *profile) : GFXTextureObject( d, profile )
 40{
 41#ifdef D3D11_DEBUG_SPEW
 42   mTexCount++;
 43   Con::printf("+ texMake %d %x", mTexCount, this);
 44#endif
 45
 46   mD3DTexture = NULL;
 47   mLocked = false;
 48
 49   mD3DSurface = NULL;
 50   dMemset(&mLockRect, 0, sizeof(mLockRect));
 51   dMemset(&mLockBox, 0, sizeof(mLockBox));
 52   mLockedSubresource = 0;
 53   mDSView = NULL;
 54   mRTView = NULL;
 55   mSRView = NULL;
 56   isManaged = false;
 57}
 58
 59GFXD3D11TextureObject::~GFXD3D11TextureObject()
 60{
 61   kill();
 62#ifdef D3D11_DEBUG_SPEW
 63   mTexCount--;
 64   Con::printf("+ texkill %d %x", mTexCount, this);
 65#endif
 66}
 67
 68GFXLockedRect *GFXD3D11TextureObject::lock(U32 mipLevel /*= 0*/, RectI *inRect /*= NULL*/)
 69{
 70   AssertFatal( !mLocked, "GFXD3D11TextureObject::lock - The texture is already locked!" );
 71
 72   if( !mStagingTex ||
 73      mStagingTex->getWidth() != getWidth() ||
 74      mStagingTex->getHeight() != getHeight() ||
 75      mStagingTex->getDepth() != getDepth())
 76   {
 77      if (getDepth() != 0)
 78      {
 79         mStagingTex.set(getWidth(), getHeight(), getDepth(), mFormat, &GFXSystemMemTextureProfile, avar("%s() - mLockTex (line %d)", __FUNCTION__, __LINE__, 0));
 80      }
 81      else
 82      {
 83         mStagingTex.set(getWidth(), getHeight(), mFormat, &GFXSystemMemTextureProfile, avar("%s() - mLockTex (line %d)", __FUNCTION__, __LINE__));
 84      }
 85   }
 86
 87   ID3D11DeviceContext* pContext = D3D11DEVICECONTEXT;
 88   D3D11_MAPPED_SUBRESOURCE mapInfo;
 89   U32 offset = 0;
 90   mLockedSubresource = D3D11CalcSubresource(mipLevel, 0, getMipLevels());
 91   GFXD3D11TextureObject* pD3DStagingTex = (GFXD3D11TextureObject*)&(*mStagingTex);
 92
 93   //map staging texture
 94   HRESULT hr = pContext->Map(pD3DStagingTex->getResource(), mLockedSubresource, D3D11_MAP_WRITE, 0, &mapInfo);      
 95
 96   if (FAILED(hr))
 97      AssertFatal(false, "GFXD3D11TextureObject:lock - failed to map render target resource!");
 98
 99
100   const bool is3D = mStagingTex->getDepth() != 0;
101   const U32 width = mTextureSize.x >> mipLevel;
102   const U32 height = mTextureSize.y >> mipLevel;
103   const U32 depth = is3D ? mTextureSize.z >> mipLevel : 1;
104
105   //calculate locked box region and offset
106   if (inRect)
107   {
108      if ((inRect->point.x + inRect->extent.x > width) || (inRect->point.y + inRect->extent.y > height))
109         AssertFatal(false, "GFXD3D11TextureObject::lock - Rectangle too big!");
110
111      mLockBox.top = inRect->point.y;
112      mLockBox.left = inRect->point.x;
113      mLockBox.bottom = inRect->point.y + inRect->extent.y;
114      mLockBox.right = inRect->point.x + inRect->extent.x;
115      mLockBox.back = depth;
116      mLockBox.front = 0;
117
118      //calculate offset
119      offset = inRect->point.x * getFormatByteSize() + inRect->point.y * mapInfo.RowPitch;
120   }
121   else
122   {
123      mLockBox.top = 0;
124      mLockBox.left = 0;
125      mLockBox.bottom = height;
126      mLockBox.right = width;
127      mLockBox.back = depth;
128      mLockBox.front = 0;
129   }
130
131   mLocked = true;
132   mLockRect.pBits = static_cast<U8*>(mapInfo.pData) + offset;
133   mLockRect.Pitch = mapInfo.RowPitch;
134
135   return (GFXLockedRect*)&mLockRect;
136}
137
138void GFXD3D11TextureObject::unlock(U32 mipLevel)
139{
140   AssertFatal( mLocked, "GFXD3D11TextureObject::unlock - Attempting to unlock a surface that has not been locked" );
141
142   //profile in the unlock function because all the heavy lifting is done here
143   PROFILE_START(GFXD3D11TextureObject_lockRT);
144
145   ID3D11DeviceContext* pContext = D3D11DEVICECONTEXT;
146   GFXD3D11TextureObject* pD3DStagingTex = (GFXD3D11TextureObject*)&(*mStagingTex);
147   ID3D11Resource* pStagingResource = pD3DStagingTex->getResource();
148   const bool is3D = mStagingTex->getDepth() != 0;
149
150   //unmap staging texture
151   pContext->Unmap(pStagingResource, mLockedSubresource);
152   //copy lock box region from the staging texture to our regular texture
153   pContext->CopySubresourceRegion(mD3DTexture, mLockedSubresource, mLockBox.left, mLockBox.top, is3D ? mLockBox.back : 0, pStagingResource, mLockedSubresource, &mLockBox);
154
155   PROFILE_END();
156
157   mLockedSubresource = 0;
158   mLocked = false;
159}
160
161void GFXD3D11TextureObject::release()
162{
163   SAFE_RELEASE(mSRView);
164   SAFE_RELEASE(mRTView);
165   SAFE_RELEASE(mDSView);
166   SAFE_RELEASE(mD3DTexture);
167   SAFE_RELEASE(mD3DSurface);
168}
169
170void GFXD3D11TextureObject::zombify()
171{
172   // Managed textures are managed by D3D
173   AssertFatal(!mLocked, "GFXD3D11TextureObject::zombify - Cannot zombify a locked texture!");
174   if(isManaged)
175      return;
176   release();
177}
178
179void GFXD3D11TextureObject::resurrect()
180{
181   // Managed textures are managed by D3D
182   if(isManaged)
183      return;
184
185   static_cast<GFXD3D11TextureManager*>(TEXMGR)->refreshTexture(this);
186}
187
188bool GFXD3D11TextureObject::copyToBmp(GBitmap* bmp)
189{
190   if (!bmp)
191      return false;
192
193   // check format limitations
194   // at the moment we only support RGBA for the source (other 4 byte formats should
195   // be easy to add though)
196   AssertFatal(mFormat == GFXFormatR16G16B16A16F || mFormat == GFXFormatR8G8B8A8 || mFormat == GFXFormatR8G8B8A8_LINEAR_FORCE || mFormat == GFXFormatR8G8B8A8_SRGB || mFormat == GFXFormatR8G8B8, "copyToBmp: invalid format");
197   if (mFormat != GFXFormatR16G16B16A16F && mFormat != GFXFormatR8G8B8A8 && mFormat != GFXFormatR8G8B8A8_LINEAR_FORCE && mFormat != GFXFormatR8G8B8A8_SRGB && mFormat != GFXFormatR8G8B8)
198      return false;
199
200   PROFILE_START(GFXD3D11TextureObject_copyToBmp);
201
202   AssertFatal(bmp->getWidth() == getWidth(), "GFXD3D11TextureObject::copyToBmp - source/dest width does not match");
203   AssertFatal(bmp->getHeight() == getHeight(), "GFXD3D11TextureObject::copyToBmp - source/dest height does not match");
204   const U32 mipLevels = getMipLevels();
205
206   bmp->setHasTransparency(mHasTransparency);
207
208   // set some constants
209   U32 sourceBytesPerPixel = 4;
210   U32 destBytesPerPixel = 0;
211
212   const GFXFormat fmt = bmp->getFormat();
213   bool fp16 = false;//is rgba16f format?
214   if (fmt == GFXFormatR16G16B16A16F)
215   {
216      destBytesPerPixel = 8;
217      sourceBytesPerPixel = 8;
218      fp16 = true;
219   }
220   else if (fmt == GFXFormatR8G8B8A8 || fmt == GFXFormatR8G8B8A8_LINEAR_FORCE || fmt == GFXFormatR8G8B8A8_SRGB)
221      destBytesPerPixel = 4;
222   else if(bmp->getFormat() == GFXFormatR8G8B8)
223      destBytesPerPixel = 3;
224   else
225      // unsupported
226      AssertFatal(false, "GFXD3D11TextureObject::copyToBmp - unsupported bitmap format");
227   
228   //create temp staging texture
229   D3D11_TEXTURE2D_DESC desc;
230   static_cast<ID3D11Texture2D*>(mD3DTexture)->GetDesc(&desc);
231   desc.BindFlags = 0;
232   desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
233   desc.Usage = D3D11_USAGE_STAGING;
234   desc.MiscFlags = 0;
235
236   ID3D11Texture2D* pStagingTexture = NULL;
237   HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &pStagingTexture);
238   if (FAILED(hr))
239   {
240      Con::errorf("GFXD3D11TextureObject::copyToBmp - Failed to create staging texture"); 
241      return false;
242   }
243
244   //copy the classes texture to the staging texture
245   D3D11DEVICECONTEXT->CopyResource(pStagingTexture, mD3DTexture);
246
247   for (U32 mip = 0; mip < mipLevels; mip++)
248   {
249      const U32 width = bmp->getWidth(mip);
250      const U32 height = bmp->getHeight(mip);
251      //map the staging resource
252      D3D11_MAPPED_SUBRESOURCE mappedRes;
253      const U32 subResource = D3D11CalcSubresource(mip, 0, mipLevels);
254      hr = D3D11DEVICECONTEXT->Map(pStagingTexture, subResource, D3D11_MAP_READ, 0, &mappedRes);
255      if (FAILED(hr))
256      {
257         //cleanup
258         SAFE_RELEASE(pStagingTexture);
259         Con::errorf("GFXD3D11TextureObject::copyToBmp - Failed to map staging texture");
260         return false;
261      }
262
263      // set pointers
264      const U8* srcPtr = (U8*)mappedRes.pData;
265      U8* destPtr = bmp->getWritableBits(mip);
266
267      // we will want to skip over any D3D cache data in the source texture
268      const S32 sourceCacheSize = mappedRes.RowPitch - width * sourceBytesPerPixel;
269      AssertFatal(sourceCacheSize >= 0, "GFXD3D11TextureObject::copyToBmp - cache size is less than zero?");
270
271      // copy data into bitmap
272      for (U32 row = 0; row < height; ++row)
273      {
274         for (U32 col = 0; col < width; ++col)
275         {
276            //we can just copy data straight in with RGBA16F format
277            if (fp16)
278            {
279               dMemcpy(destPtr, srcPtr, sizeof(U16) * 4);
280            }
281            else
282            {            
283               destPtr[0] = srcPtr[2]; // red
284               destPtr[1] = srcPtr[1]; // green
285               destPtr[2] = srcPtr[0]; // blue 
286               if (destBytesPerPixel == 4)
287                  destPtr[3] = srcPtr[3]; // alpha
288            }
289
290            // go to next pixel in src
291            srcPtr += sourceBytesPerPixel;
292
293            // go to next pixel in dest
294            destPtr += destBytesPerPixel;
295         }
296         // skip past the cache data for this row (if any)
297         srcPtr += sourceCacheSize;
298      }
299
300      // assert if we stomped or underran memory
301      AssertFatal(U32(destPtr - bmp->getWritableBits(mip)) == width * height * destBytesPerPixel, "GFXD3D11TextureObject::copyToBmp - memory error");
302      AssertFatal(U32(srcPtr - (U8*)mappedRes.pData) == height * mappedRes.RowPitch, "GFXD3D11TextureObject::copyToBmp - memory error");
303
304      D3D11DEVICECONTEXT->Unmap(pStagingTexture, subResource);
305   }
306
307   SAFE_RELEASE(pStagingTexture);
308   PROFILE_END();
309
310   return true;
311}
312
313ID3D11ShaderResourceView* GFXD3D11TextureObject::getSRView()
314{
315   return mSRView;
316}
317ID3D11RenderTargetView* GFXD3D11TextureObject::getRTView()
318{
319   return mRTView;
320}
321ID3D11DepthStencilView* GFXD3D11TextureObject::getDSView()
322{
323   return mDSView;
324}
325
326ID3D11ShaderResourceView** GFXD3D11TextureObject::getSRViewPtr()
327{
328   return &mSRView;
329}
330ID3D11RenderTargetView** GFXD3D11TextureObject::getRTViewPtr()
331{
332   return &mRTView;
333}
334
335ID3D11DepthStencilView** GFXD3D11TextureObject::getDSViewPtr()
336{
337   return &mDSView;
338}
339