Browse Source

Add cubemap arrays, as well as control for generation of MIPs on texture targets.

Areloch 7 years ago
parent
commit
1f7cf55204

+ 129 - 24
Engine/source/gfx/D3D11/gfxD3D11Cubemap.cpp

@@ -34,7 +34,8 @@ GFXD3D11Cubemap::GFXD3D11Cubemap() : mTexture(NULL), mSRView(NULL), mDSView(NULL
 
    for (U32 i = 0; i < CubeFaces; i++)
 	{
-      mRTView[i] = NULL;
+      for(U32 j=0; j < MaxMipMaps; j++)
+         mRTView[i][j] = NULL;
 	}
 }
 
@@ -50,7 +51,8 @@ void GFXD3D11Cubemap::releaseSurfaces()
 
    for (U32 i = 0; i < CubeFaces; i++)
 	{
-      SAFE_RELEASE(mRTView[i]);
+      for (U32 j = 0; j < MaxMipMaps; j++)
+         SAFE_RELEASE(mRTView[i][j]);
 	}
 
    SAFE_RELEASE(mDSView);
@@ -93,7 +95,7 @@ void GFXD3D11Cubemap::initStatic(GFXTexHandle *faces)
 	desc.Width = mTexSize;
 	desc.Height = mTexSize;
    desc.MipLevels = mAutoGenMips ? 0 : mMipMapLevels;
-	desc.ArraySize = 6;
+	desc.ArraySize = CubeFaces;
 	desc.Format = GFXD3D11TextureFormat[mFaceFormat];
 	desc.SampleDesc.Count = 1;
 	desc.SampleDesc.Quality = 0;
@@ -209,16 +211,20 @@ void GFXD3D11Cubemap::initStatic(DDSFile *dds)
 	}
 }
 
-void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
+void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat, U32 mipLevels)
 {
 	if(!mDynamic)
 		GFXTextureManager::addEventDelegate(this, &GFXD3D11Cubemap::_onTextureEvent);
 
 	mDynamic = true;
-   mAutoGenMips = true;
 	mTexSize = texSize;
 	mFaceFormat = faceFormat;
-   mMipMapLevels = 0;
+    if (!mipLevels)
+       mAutoGenMips = true;
+
+    mMipMapLevels = mipLevels;
+
+
    bool compressed = ImageUtil::isCompressedFormat(mFaceFormat);
 
    UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
@@ -233,7 +239,7 @@ void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
 
 	desc.Width = mTexSize;
 	desc.Height = mTexSize;
-	desc.MipLevels = 0;
+	desc.MipLevels = mMipMapLevels;
 	desc.ArraySize = 6;
 	desc.Format = GFXD3D11TextureFormat[mFaceFormat];
 	desc.SampleDesc.Count = 1;
@@ -249,7 +255,7 @@ void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
 	D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
 	SMViewDesc.Format = GFXD3D11TextureFormat[mFaceFormat];
 	SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
-   SMViewDesc.TextureCube.MipLevels = -1;
+   SMViewDesc.TextureCube.MipLevels = mAutoGenMips ? -1 : mMipMapLevels;
 	SMViewDesc.TextureCube.MostDetailedMip = 0;
 
 	hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
@@ -274,18 +280,21 @@ void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
 	viewDesc.Format = desc.Format;
 	viewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
 	viewDesc.Texture2DArray.ArraySize = 1;
-	viewDesc.Texture2DArray.MipSlice = 0;
 
    for (U32 i = 0; i < CubeFaces; i++)
-	{
-		viewDesc.Texture2DArray.FirstArraySlice = i;
-      hr = D3D11DEVICE->CreateRenderTargetView(mTexture, &viewDesc, &mRTView[i]);
+   {
+	  viewDesc.Texture2DArray.FirstArraySlice = i;
+      for (U32 j = 0; j < mMipMapLevels; j++)
+      {
+         viewDesc.Texture2DArray.MipSlice = j;
+         hr = D3D11DEVICE->CreateRenderTargetView(mTexture, &viewDesc, &mRTView[i][j]);
 
-		if(FAILED(hr)) 
-		{
-			AssertFatal(false, "GFXD3D11Cubemap::initDynamic - CreateRenderTargetView call failure");
-		}
-	}
+         if (FAILED(hr))
+         {
+            AssertFatal(false, "GFXD3D11Cubemap::initDynamic - CreateRenderTargetView call failure");
+         }
+      }
+   }
 
    D3D11_TEXTURE2D_DESC depthTexDesc;
    depthTexDesc.Width = mTexSize;
@@ -352,16 +361,11 @@ ID3D11ShaderResourceView* GFXD3D11Cubemap::getSRView()
    return mSRView;
 }
 
-ID3D11RenderTargetView* GFXD3D11Cubemap::getRTView(U32 faceIdx)
+ID3D11RenderTargetView* GFXD3D11Cubemap::getRTView(U32 faceIdx, U32 mipIndex)
 {
    AssertFatal(faceIdx < CubeFaces, "GFXD3D11Cubemap::getRTView - face index out of bounds");
 
-   return mRTView[faceIdx];
-}
-
-ID3D11RenderTargetView** GFXD3D11Cubemap::getRTViewArray()
-{
-   return mRTView;
+   return mRTView[faceIdx][mipIndex];
 }
 
 ID3D11DepthStencilView* GFXD3D11Cubemap::getDSView()
@@ -372,4 +376,105 @@ ID3D11DepthStencilView* GFXD3D11Cubemap::getDSView()
 ID3D11Texture2D* GFXD3D11Cubemap::get2DTex()
 {
    return mTexture;
+}
+
+//-----------------------------------------------------------------------------
+// Cubemap Array
+//-----------------------------------------------------------------------------
+
+GFXD3D11CubemapArray::GFXD3D11CubemapArray() : mTexture(NULL), mSRView(NULL)
+{
+}
+
+GFXD3D11CubemapArray::~GFXD3D11CubemapArray()
+{
+   SAFE_RELEASE(mSRView);
+   SAFE_RELEASE(mTexture);
+}
+
+void GFXD3D11CubemapArray::initStatic(GFXCubemapHandle *cubemaps, const U32 cubemapCount)
+{
+   AssertFatal(cubemaps, "GFXD3D11CubemapArray - Got null GFXCubemapHandle!");
+   AssertFatal(*cubemaps, "GFXD3D11CubemapArray - Got empty cubemap!");
+
+   //all cubemaps must be the same size,format and number of mipmaps. Grab the details from the first cubemap
+   mSize = cubemaps[0]->getSize();
+   mFormat = cubemaps[0]->getFormat();
+   mMipMapLevels = cubemaps[0]->getMipMapLevels();
+   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(GFXCubemap *cubemaps,const U32 cubemapCount) - 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(GFXCubemap *cubemaps,const U32 cubemapCount) - 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(GFXCubemap *cubemaps,const U32 cubemapCount) - shader resource view  creation failure");
+
+}
+
+void GFXD3D11CubemapArray::setToTexUnit(U32 tuNum)
+{
+   D3D11DEVICECONTEXT->PSSetShaderResources(tuNum, 1, &mSRView);
+}
+
+void GFXD3D11CubemapArray::zombify()
+{
+   // Static cubemaps are handled by D3D
+}
+
+void GFXD3D11CubemapArray::resurrect()
+{
+   // Static cubemaps are handled by D3D
 }

+ 27 - 4
Engine/source/gfx/D3D11/gfxD3D11Cubemap.h

@@ -29,13 +29,14 @@
 #include "gfx/gfxTarget.h"
 
 const U32 CubeFaces = 6;
+const U32 MaxMipMaps = 13; //todo this needs a proper static value somewhere to sync up with other classes like GBitmap
 
 class GFXD3D11Cubemap : public GFXCubemap
 {
 public:
    virtual void initStatic( GFXTexHandle *faces );
    virtual void initStatic( DDSFile *dds );
-   virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8 );
+   virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8, U32 mipLevels = 0);
    virtual void setToTexUnit( U32 tuNum );
    virtual U32 getSize() const { return mTexSize; }
    virtual GFXFormat getFormat() const { return mFaceFormat; }
@@ -49,8 +50,7 @@ public:
 
    // Get functions
    ID3D11ShaderResourceView* getSRView();
-   ID3D11RenderTargetView* getRTView(U32 faceIdx);
-   ID3D11RenderTargetView** getRTViewArray();
+   ID3D11RenderTargetView* getRTView(U32 faceIdx, U32 mipIndex=0);
    ID3D11DepthStencilView* getDSView();
    ID3D11Texture2D* get2DTex();
 
@@ -61,7 +61,7 @@ private:
 
    ID3D11Texture2D* mTexture;
    ID3D11ShaderResourceView* mSRView; // for shader resource input
-   ID3D11RenderTargetView* mRTView[CubeFaces]; // for render targets, 6 faces of the cubemap
+   ID3D11RenderTargetView* mRTView[CubeFaces][MaxMipMaps]; // for render targets, 6 faces of the cubemap
    ID3D11DepthStencilView* mDSView; //render target view for depth stencil
 
    bool mAutoGenMips;
@@ -76,4 +76,27 @@ private:
    void _onTextureEvent(GFXTexCallbackCode code);
 };
 
+class GFXD3D11CubemapArray : public GFXCubemapArray
+{
+public:
+   GFXD3D11CubemapArray();
+   virtual ~GFXD3D11CubemapArray();
+   virtual void initStatic(GFXCubemapHandle *cubemaps, const U32 cubemapCount);
+   virtual void setToTexUnit(U32 tuNum);
+
+   ID3D11ShaderResourceView* getSRView() { return mSRView; }
+   ID3D11Texture2D* get2DTex() { return mTexture; }
+
+   // GFXResource interface
+   virtual void zombify();
+   virtual void resurrect();
+
+private:
+   friend class GFXD3D11TextureTarget;
+   friend class GFXD3D11Device;
+
+   ID3D11Texture2D *mTexture;
+   ID3D11ShaderResourceView* mSRView; // for shader resource input
+};
+
 #endif

+ 29 - 3
Engine/source/gfx/D3D11/gfxD3D11Device.cpp

@@ -449,7 +449,7 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window)
    DXGI_SWAP_CHAIN_DESC d3dpp = setupPresentParams(mode, winHwnd);
 
    // TODO support at least feature level 10 to match GL
-   D3D_FEATURE_LEVEL pFeatureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 };
+   D3D_FEATURE_LEVEL pFeatureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 };
    U32 nFeatureCount = ARRAYSIZE(pFeatureLevels);
    D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE;// use D3D_DRIVER_TYPE_REFERENCE for reference device
    // create a device, device context and swap chain using the information in the d3dpp struct
@@ -689,9 +689,9 @@ GFXWindowTarget * GFXD3D11Device::allocWindowTarget(PlatformWindow *window)
    return gdwt;
 }
 
-GFXTextureTarget* GFXD3D11Device::allocRenderToTextureTarget()
+GFXTextureTarget* GFXD3D11Device::allocRenderToTextureTarget(bool genMips)
 {
-   GFXD3D11TextureTarget *targ = new GFXD3D11TextureTarget();
+   GFXD3D11TextureTarget *targ = new GFXD3D11TextureTarget(genMips);
    targ->registerResourceWithDevice(this);
 
    return targ;
@@ -963,6 +963,25 @@ void GFXD3D11Device::clear(U32 flags, const LinearColorF& color, F32 z, U32 sten
    SAFE_RELEASE(dsView);
 }
 
+void GFXD3D11Device::clearColorAttachment(const U32 attachment, const LinearColorF& color)
+{
+   GFXD3D11TextureTarget *pTarget = static_cast<GFXD3D11TextureTarget*>(mCurrentRT.getPointer());
+   ID3D11RenderTargetView* rtView = NULL;
+
+   if (!pTarget)
+   {
+      rtView = mDeviceBackBufferView;// we are using the default backbuffer
+   }
+   else
+   {
+      //attachment + 1 to skip past DepthStencil which is first in the list
+      rtView = static_cast<ID3D11RenderTargetView*>(pTarget->mTargetViews[attachment + 1]);
+   }
+
+   const FLOAT clearColor[4] = { color.red, color.green, color.blue, color.alpha };
+   mD3DDeviceContext->ClearRenderTargetView(rtView, clearColor);
+}
+
 void GFXD3D11Device::endSceneInternal() 
 {
    mCanCurrentlyRender = false;
@@ -1837,6 +1856,13 @@ GFXCubemap * GFXD3D11Device::createCubemap()
    return cube;
 }
 
+GFXCubemapArray * GFXD3D11Device::createCubemapArray()
+{
+   GFXD3D11CubemapArray* cubeArray = new GFXD3D11CubemapArray();
+   cubeArray->registerResourceWithDevice(this);
+   return cubeArray;
+}
+
 // Debug events
 //------------------------------------------------------------------------------
 void GFXD3D11Device::enterDebugEvent(ColorI color, const char *name)

+ 5 - 2
Engine/source/gfx/D3D11/gfxD3D11Device.h

@@ -71,7 +71,7 @@ private:
    virtual void enumerateVideoModes();
 
    virtual GFXWindowTarget *allocWindowTarget(PlatformWindow *window);
-   virtual GFXTextureTarget *allocRenderToTextureTarget();
+   virtual GFXTextureTarget *allocRenderToTextureTarget(bool genMips = true);
 
    virtual void enterDebugEvent(ColorI color, const char *name);
    virtual void leaveDebugEvent();
@@ -237,6 +237,7 @@ public:
    U32 getAdaterIndex() const { return mAdapterIndex; }
 
    virtual GFXCubemap *createCubemap();
+   virtual GFXCubemapArray *createCubemapArray();
 
    virtual F32  getPixelShaderVersion() const { return mPixVersion; }
    virtual void setPixelShaderVersion( F32 version ){ mPixVersion = version;} 
@@ -249,6 +250,8 @@ public:
    // Misc rendering control
    // {
    virtual void clear( U32 flags, const LinearColorF& color, F32 z, U32 stencil );
+   virtual void clearColorAttachment(const U32 attachment, const LinearColorF& color);
+
    virtual bool beginSceneInternal();
    virtual void endSceneInternal();
 
@@ -325,7 +328,7 @@ public:
 
    // grab the sampler map
    const SamplerMap &getSamplersMap() const { return mSamplersMap; }
-   SamplerMap &getSamplersMap() { return mSamplersMap; }
+   SamplerMap &getSamplersMap(){ return mSamplersMap; }
 };
 
 #endif

+ 1 - 0
Engine/source/gfx/D3D11/gfxD3D11EnumTranslate.cpp

@@ -67,6 +67,7 @@ void GFXD3D11EnumTranslate::init()
    GFXD3D11TextureFormat[GFXFormatR16F] = DXGI_FORMAT_R16_FLOAT;
    GFXD3D11TextureFormat[GFXFormatR16G16F] = DXGI_FORMAT_R16G16_FLOAT;
    GFXD3D11TextureFormat[GFXFormatR10G10B10A2] = DXGI_FORMAT_R10G10B10A2_UNORM;
+   GFXD3D11TextureFormat[GFXFormatR11G11B10] = DXGI_FORMAT_R11G11B10_FLOAT;
    GFXD3D11TextureFormat[GFXFormatD32] = DXGI_FORMAT_UNKNOWN;
    GFXD3D11TextureFormat[GFXFormatD24X8] = DXGI_FORMAT_UNKNOWN;
    GFXD3D11TextureFormat[GFXFormatD24S8] = DXGI_FORMAT_D24_UNORM_S8_UINT;

+ 2 - 1
Engine/source/gfx/D3D11/gfxD3D11Shader.cpp

@@ -1384,7 +1384,8 @@ void GFXD3D11Shader::_buildSamplerShaderConstantHandles( Vector<GFXShaderConstDe
       const GFXShaderConstDesc &desc = *iter;
 
       AssertFatal(   desc.constType == GFXSCT_Sampler || 
-                     desc.constType == GFXSCT_SamplerCube, 
+                     desc.constType == GFXSCT_SamplerCube || 
+                     desc.constType == GFXSCT_SamplerCubeArray,
                      "GFXD3D11Shader::_buildSamplerShaderConstantHandles - Invalid samplerDescription type!" );
 
       GFXD3D11ShaderConstHandle *handle;

+ 24 - 4
Engine/source/gfx/D3D11/gfxD3D11Target.cpp

@@ -28,7 +28,7 @@
 #include "gfx/gfxStringEnumTranslate.h"
 #include "windowManager/win32/win32Window.h"
 
-GFXD3D11TextureTarget::GFXD3D11TextureTarget() 
+GFXD3D11TextureTarget::GFXD3D11TextureTarget(bool genMips) 
    :  mTargetSize( Point2I::Zero ),
       mTargetFormat( GFXFormatR8G8B8A8 )
 {
@@ -39,6 +39,8 @@ GFXD3D11TextureTarget::GFXD3D11TextureTarget()
       mTargetViews[i] = NULL;
       mTargetSRViews[i] = NULL;
    }
+
+   mGenMips = genMips;
 }
 
 GFXD3D11TextureTarget::~GFXD3D11TextureTarget()
@@ -215,7 +217,7 @@ void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXCubemap *tex, U32
 
    mTargets[slot] = cube->get2DTex();
    mTargets[slot]->AddRef();
-   mTargetViews[slot] = cube->getRTView(face);
+   mTargetViews[slot] = cube->getRTView(face, mipLevel);
    mTargetViews[slot]->AddRef();
    mTargetSRViews[slot] = cube->getSRView();
    mTargetSRViews[slot]->AddRef();
@@ -262,6 +264,9 @@ void GFXD3D11TextureTarget::activate()
 
 void GFXD3D11TextureTarget::deactivate()
 {
+   if (!mGenMips)
+      return;
+
    //re-gen mip maps
    for (U32 i = 0; i < 6; i++)
    {
@@ -347,7 +352,23 @@ GFXFormat GFXD3D11WindowTarget::getFormat()
 
 bool GFXD3D11WindowTarget::present()
 {
-   return (D3D11->getSwapChain()->Present(!D3D11->smDisableVSync, 0) == S_OK);
+   HRESULT hr = D3D11->getSwapChain()->Present(!D3D11->smDisableVSync, 0);
+   if (hr == DXGI_ERROR_DEVICE_REMOVED)
+   {
+      HRESULT result = D3D11->getDevice()->GetDeviceRemovedReason();
+      if (result == DXGI_ERROR_DEVICE_HUNG)
+         AssertFatal(false,"DXGI_ERROR_DEVICE_HUNG");
+      else if (result == DXGI_ERROR_DEVICE_REMOVED)
+         AssertFatal(false, "DXGI_ERROR_DEVICE_REMOVED");
+      else if (result == DXGI_ERROR_DEVICE_RESET)
+         AssertFatal(false, "DXGI_ERROR_DEVICE_RESET");
+      else if (result == DXGI_ERROR_DRIVER_INTERNAL_ERROR)
+         AssertFatal(false, "DXGI_ERROR_DRIVER_INTERNAL_ERROR");
+      else if (result == DXGI_ERROR_INVALID_CALL)
+         AssertFatal(false, "DXGI_ERROR_INVALID_CALL");
+   }
+
+   return (hr == S_OK);
 }
 
 void GFXD3D11WindowTarget::setImplicitSwapChain()
@@ -370,7 +391,6 @@ void GFXD3D11WindowTarget::resetMode()
    mSize = Point2I(mPresentationParams.BufferDesc.Width, mPresentationParams.BufferDesc.Height);
 
    mWindow->setSuppressReset(false);
-   GFX->beginReset();
 }
 
 void GFXD3D11WindowTarget::zombify()

+ 1 - 1
Engine/source/gfx/D3D11/gfxD3D11Target.h

@@ -51,7 +51,7 @@ class GFXD3D11TextureTarget : public GFXTextureTarget
 
 public:
 
-   GFXD3D11TextureTarget();
+   GFXD3D11TextureTarget(bool genMips);
    ~GFXD3D11TextureTarget();
 
    // Public interface.

+ 21 - 1
Engine/source/gfx/Null/gfxNullDevice.cpp

@@ -151,7 +151,7 @@ private:
 public:
    virtual void initStatic( GFXTexHandle *faces ) { };
    virtual void initStatic( DDSFile *dds ) { };
-   virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8 ) { };
+   virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8, U32 mipLevels = 0) { };
    virtual U32 getSize() const { return 0; }
    virtual GFXFormat getFormat() const { return GFXFormatR8G8B8A8; }
 
@@ -161,6 +161,21 @@ public:
    virtual void resurrect() {}
 };
 
+class GFXNullCubemapArray : public GFXCubemapArray
+{
+   friend class GFXDevice;
+private:
+   // should only be called by GFXDevice
+   virtual void setToTexUnit(U32 tuNum) { };
+
+public:
+   virtual void initStatic(GFXCubemapHandle *cubemaps, const U32 cubemapCount) { };
+
+   virtual ~GFXNullCubemapArray() {};
+   virtual void zombify() {}
+   virtual void resurrect() {}
+};
+
 class GFXNullVertexBuffer : public GFXVertexBuffer 
 {
    unsigned char* tempBuf;
@@ -295,6 +310,11 @@ GFXCubemap* GFXNullDevice::createCubemap()
    return new GFXNullCubemap(); 
 };
 
+GFXCubemapArray* GFXNullDevice::createCubemapArray()
+{
+   return new GFXNullCubemapArray();
+};
+
 void GFXNullDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
 {
    // Add the NULL renderer

+ 3 - 1
Engine/source/gfx/Null/gfxNullDevice.h

@@ -129,12 +129,13 @@ protected:
 
 public:
    virtual GFXCubemap * createCubemap();
+   virtual GFXCubemapArray *createCubemapArray();
 
    virtual F32 getFillConventionOffset() const { return 0.0f; };
 
    ///@}
 
-   virtual GFXTextureTarget *allocRenderToTextureTarget(){return NULL;};
+   virtual GFXTextureTarget *allocRenderToTextureTarget(bool genMips=true){return NULL;};
    virtual GFXWindowTarget *allocWindowTarget(PlatformWindow *window)
    {
       return new GFXNullWindowTarget();
@@ -151,6 +152,7 @@ public:
 
 
    virtual void clear( U32 flags, const LinearColorF& color, F32 z, U32 stencil ) { };
+   virtual void clearColorAttachment(const U32 attachment, const LinearColorF& color) { };
    virtual bool beginSceneInternal() { return true; };
    virtual void endSceneInternal() { };
 

+ 7 - 0
Engine/source/gfx/gfxCubemap.cpp

@@ -124,3 +124,10 @@ bool GFXCubemapHandle::set( const String &cubemapDDS )
 
    return isValid();
 }
+
+const String GFXCubemapArray::describeSelf() const
+{
+   // We've got nothing
+   return String();
+}
+

+ 44 - 2
Engine/source/gfx/gfxCubemap.h

@@ -59,8 +59,8 @@ public:
    /// Create a static cubemap from a DDS cubemap file.
    virtual void initStatic( DDSFile *dds ) = 0;
 
-   ///
-   virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8 ) = 0;
+   ///create dynamic cubemap. mipLevels 0 is auto create mips, otherwise the value is how many mip levels you wish the cubemap to have
+   virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8, U32 mipLevels = 0 ) = 0;
 
    void initNormalize(U32 size);
       
@@ -99,5 +99,47 @@ public:
    void free() { StrongObjectRef::set( NULL ); }
 };
 
+/// Cubemap array
+class GFXCubemapArray : public StrongRefBase, public GFXResource
+{
+   friend class GFXDevice;
+   friend class GFXTextureManager;
+
+protected:
+   // should only be called by GFXDevice
+   virtual void setToTexUnit( U32 tuNum ) = 0;
+   /// number of cubemaps in the array
+   U32 mNumCubemaps;
+   U32 mSize;
+   U32 mMipMapLevels;
+   GFXFormat mFormat;
+
+public:
+
+   virtual ~GFXCubemapArray() {};
+
+   virtual void initStatic(GFXCubemapHandle *cubemaps, const U32 cubemapCount) = 0;
+   /// Return number of textures in the array
+   const U32 getNumCubemaps() const { return mNumCubemaps; }
+   /// Get the number of mip maps
+   const U32 getMipMapLevels() const { return mMipMapLevels; }
+   /// Returns the size of the faces.
+   const U32 getSize() const { return mSize; }
+
+   virtual const String describeSelf() const;
+};
+
+/// A reference counted handle to a cubemap array resource.
+class GFXCubemapArrayHandle : public StrongRefPtr<GFXCubemapArray>
+{
+public:
+   GFXCubemapArrayHandle() {}
+   GFXCubemapArrayHandle(GFXCubemapArray *cubemapArray) { StrongRefPtr<GFXCubemapArray>::set(cubemapArray); }
+
+   /// Releases the texture handle.
+   void free() { StrongObjectRef::set(NULL); }
+};
+
+
 
 #endif // GFXCUBEMAP

+ 57 - 5
Engine/source/gfx/gfxDevice.cpp

@@ -131,6 +131,8 @@ GFXDevice::GFXDevice()
       mNewTexture[i] = NULL;
       mCurrentCubemap[i] = NULL;
       mNewCubemap[i] = NULL;
+      mCurrentCubemapArray[i] = NULL;
+      mNewCubemapArray[i] = NULL;
       mTexType[i] = GFXTDT_Normal;
 
       mTextureMatrix[i].identity();
@@ -262,6 +264,8 @@ GFXDevice::~GFXDevice()
       mNewTexture[i] = NULL;
       mCurrentCubemap[i] = NULL;
       mNewCubemap[i] = NULL;
+      mCurrentCubemapArray[i] = NULL;
+      mNewCubemapArray[i] = NULL;
    }
 
    mCurrentRT = NULL;
@@ -398,6 +402,15 @@ void GFXDevice::updateStates(bool forceSetAll /*=false*/)
                      setTextureInternal(i, NULL);
                }
                break;
+            case GFXTDT_CubeArray:
+            {
+               mCurrentCubemapArray[i] = mNewCubemapArray[i];
+               if (mCurrentCubemapArray[i])
+                  mCurrentCubemapArray[i]->setToTexUnit(i);
+               else
+                  setTextureInternal(i, NULL);
+            }
+            break;
             default:
                AssertFatal(false, "Unknown texture type!");
                break;
@@ -537,6 +550,15 @@ void GFXDevice::updateStates(bool forceSetAll /*=false*/)
                   setTextureInternal(i, NULL);
             }
             break;
+         case GFXTDT_CubeArray:
+         {
+            mCurrentCubemapArray[i] = mNewCubemapArray[i];
+            if (mCurrentCubemapArray[i])
+               mCurrentCubemapArray[i]->setToTexUnit(i);
+            else
+               setTextureInternal(i, NULL);
+         }
+         break;
          default:
             AssertFatal(false, "Unknown texture type!");
             break;
@@ -777,30 +799,60 @@ void GFXDevice::setTexture( U32 stage, GFXTextureObject *texture )
    // Clear out the cubemaps
    mNewCubemap[stage] = NULL;
    mCurrentCubemap[stage] = NULL;
+   mNewCubemapArray[stage] = NULL;
+   mCurrentCubemapArray[stage] = NULL;
 }
 
 //-----------------------------------------------------------------------------
 // Set cube texture
 //-----------------------------------------------------------------------------
-void GFXDevice::setCubeTexture( U32 stage, GFXCubemap *texture )
+void GFXDevice::setCubeTexture( U32 stage, GFXCubemap *cubemap )
 {
    AssertFatal(stage < getNumSamplers(), "GFXDevice::setTexture - out of range stage!");
 
    if (  mTexType[stage] == GFXTDT_Cube &&
-         (  ( mTextureDirty[stage] && mNewCubemap[stage].getPointer() == texture ) ||
-            ( !mTextureDirty[stage] && mCurrentCubemap[stage].getPointer() == texture ) ) )
+         (  ( mTextureDirty[stage] && mNewCubemap[stage].getPointer() == cubemap) ||
+            ( !mTextureDirty[stage] && mCurrentCubemap[stage].getPointer() == cubemap) ) )
       return;
 
    mStateDirty = true;
    mTexturesDirty = true;
    mTextureDirty[stage] = true;
 
-   mNewCubemap[stage] = texture;
+   mNewCubemap[stage] = cubemap;
    mTexType[stage] = GFXTDT_Cube;
 
-   // Clear out the normal textures
+   // Clear out textures
    mNewTexture[stage] = NULL;
    mCurrentTexture[stage] = NULL;
+   mNewCubemapArray[stage] = NULL;
+   mCurrentCubemapArray[stage] = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Set cube texture array
+//-----------------------------------------------------------------------------
+void GFXDevice::setCubeArrayTexture(U32 stage, GFXCubemapArray *cubemapArray)
+{
+   AssertFatal(stage < getNumSamplers(), "GFXDevice::setTexture - out of range stage!");
+
+   if (mTexType[stage] == GFXTDT_CubeArray &&
+      ((mTextureDirty[stage] && mNewCubemapArray[stage].getPointer() == cubemapArray) ||
+      (!mTextureDirty[stage] && mCurrentCubemapArray[stage].getPointer() == cubemapArray)))
+      return;
+
+   mStateDirty = true;
+   mTexturesDirty = true;
+   mTextureDirty[stage] = true;
+
+   mNewCubemapArray[stage] = cubemapArray;
+   mTexType[stage] = GFXTDT_CubeArray;
+
+   // Clear out textures
+   mNewTexture[stage] = NULL;
+   mCurrentTexture[stage] = NULL;
+   mNewCubemap[stage] = NULL;
+   mCurrentCubemap[stage] = NULL;
 }
 
 //------------------------------------------------------------------------------

+ 9 - 3
Engine/source/gfx/gfxDevice.h

@@ -497,13 +497,16 @@ protected:
    enum TexDirtyType
    {
       GFXTDT_Normal,
-      GFXTDT_Cube
+      GFXTDT_Cube,
+      GFXTDT_CubeArray
    };
    
    GFXTexHandle mCurrentTexture[TEXTURE_STAGE_COUNT];
    GFXTexHandle mNewTexture[TEXTURE_STAGE_COUNT];
    GFXCubemapHandle mCurrentCubemap[TEXTURE_STAGE_COUNT];
    GFXCubemapHandle mNewCubemap[TEXTURE_STAGE_COUNT];
+   GFXCubemapArrayHandle mCurrentCubemapArray[TEXTURE_STAGE_COUNT];
+   GFXCubemapArrayHandle mNewCubemapArray[TEXTURE_STAGE_COUNT];
 
    TexDirtyType   mTexType[TEXTURE_STAGE_COUNT];
    bool           mTextureDirty[TEXTURE_STAGE_COUNT];
@@ -753,6 +756,7 @@ protected:
 
 public:   
    virtual GFXCubemap * createCubemap() = 0;
+   virtual GFXCubemapArray *createCubemapArray() = 0;
 
    inline GFXTextureManager *getTextureManager()
    {
@@ -778,7 +782,7 @@ public:
 
    /// Allocate a target for doing render to texture operations, with no
    /// depth/stencil buffer.
-   virtual GFXTextureTarget *allocRenderToTextureTarget()=0;
+   virtual GFXTextureTarget *allocRenderToTextureTarget(bool genMips = true) = 0;
 
    /// Allocate a target for a given window.
    virtual GFXWindowTarget *allocWindowTarget(PlatformWindow *window)=0;
@@ -827,6 +831,7 @@ public:
 
    ///
    virtual void clear( U32 flags, const LinearColorF& color, F32 z, U32 stencil ) = 0;
+   virtual void clearColorAttachment(const U32 attachment, const LinearColorF& color) = 0;
    virtual bool beginScene();
    virtual void endScene();
    virtual void beginField();
@@ -937,8 +942,9 @@ public:
    /// @{
 
    ///
-   void setTexture(U32 stage, GFXTextureObject*texture);
+   void setTexture(U32 stage, GFXTextureObject *texture);
    void setCubeTexture( U32 stage, GFXCubemap *cubemap );
+   void setCubeArrayTexture( U32 stage, GFXCubemapArray *cubemapArray);
    inline GFXTextureObject* getCurrentTexture( U32 stage ) { return mCurrentTexture[stage]; }
 
    /// @}

+ 4 - 1
Engine/source/gfx/gfxEnums.h

@@ -188,6 +188,7 @@ enum GFXFormat
    GFXFormatR16G16,
    GFXFormatR16G16F,
    GFXFormatR10G10B10A2,
+   GFXFormatR11G11B10,
    GFXFormatD32,
    GFXFormatD24X8,
    GFXFormatD24S8,   
@@ -495,6 +496,7 @@ enum GFXTextureTransformFlags
 
 // CodeReview: This number is used for the declaration of variables, but it
 // should *not* be used for any run-time purposes [7/2/2007 Pat]
+#define TEXTURE_STAGE_COUNT 32
 #define TEXTURE_STAGE_COUNT 16
 
 enum GFXSamplerState 
@@ -597,7 +599,8 @@ enum GFXShaderConstType
    GFXSCT_Int4, 
    // Samplers
    GFXSCT_Sampler,
-   GFXSCT_SamplerCube
+   GFXSCT_SamplerCube,
+   GFXSCT_SamplerCubeArray
 };
 
 

+ 6 - 0
Engine/source/gfx/gfxTarget.h

@@ -196,6 +196,12 @@ public:
    /// 
    /// By default, this method will resolve all color targets.
    virtual void resolve()=0;
+
+   /// Returns true if the automatic generation of mip maps is enabled
+   inline bool isGenMipsEnabled() const { return mGenMips; }
+
+protected:
+   bool mGenMips;
 };
 
 typedef StrongRefPtr<GFXTarget> GFXTargetRef;

+ 1 - 1
Engine/source/gfx/gl/gfxGLCubemap.cpp

@@ -181,7 +181,7 @@ void GFXGLCubemap::initStatic( DDSFile *dds )
    }
 }
 
-void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
+void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat, U32 mipLevels)
 {
    mDynamicTexSize = texSize;
    mFaceFormat = faceFormat;

+ 1 - 1
Engine/source/gfx/gl/gfxGLCubemap.h

@@ -39,7 +39,7 @@ public:
 
    virtual void initStatic( GFXTexHandle *faces );
    virtual void initStatic( DDSFile *dds );
-   virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8 );
+   virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8, U32 mipLevels = 0);
    virtual U32 getSize() const { return mWidth; }
    virtual GFXFormat getFormat() const { return mFaceFormat; }
 

+ 8 - 2
Engine/source/gfx/gl/gfxGLDevice.cpp

@@ -495,6 +495,12 @@ void GFXGLDevice::clear(U32 flags, const LinearColorF& color, F32 z, U32 stencil
       glStencilMask(desc->stencilWriteMask);
 }
 
+void GFXGLDevice::clearColorAttachment(const U32 attachment, const LinearColorF& color)
+{
+   const GLfloat clearColor[4] = { color.red, color.green, color.blue, color.alpha };
+   glClearBufferfv(GL_COLOR, attachment, clearColor);
+}
+
 // Given a primitive type and a number of primitives, return the number of indexes/vertexes used.
 inline GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32 primitiveCount)
 {
@@ -749,9 +755,9 @@ void GFXGLDevice::setStateBlockInternal(GFXStateBlock* block, bool force)
 
 //------------------------------------------------------------------------------
 
-GFXTextureTarget * GFXGLDevice::allocRenderToTextureTarget()
+GFXTextureTarget * GFXGLDevice::allocRenderToTextureTarget(bool genMips)
 {
-   GFXGLTextureTarget *targ = new GFXGLTextureTarget();
+   GFXGLTextureTarget *targ = new GFXGLTextureTarget(genMips);
    targ->registerResourceWithDevice(this);
    return targ;
 }

+ 3 - 1
Engine/source/gfx/gl/gfxGLDevice.h

@@ -81,6 +81,7 @@ public:
    virtual U32 getTotalVideoMemory();
 
    virtual GFXCubemap * createCubemap();
+   virtual GFXCubemapArray *createCubemapArray() { return NULL; } //TODO: implement
 
    virtual F32 getFillConventionOffset() const { return 0.0f; }
 
@@ -91,7 +92,7 @@ public:
    /// @{
 
    ///
-   virtual GFXTextureTarget *allocRenderToTextureTarget();
+   virtual GFXTextureTarget *allocRenderToTextureTarget(bool genMips = true);
    virtual GFXWindowTarget *allocWindowTarget(PlatformWindow *window);
    virtual void _updateRenderTargets();
 
@@ -117,6 +118,7 @@ public:
    virtual GFXShader* createShader();
       
    virtual void clear( U32 flags, const LinearColorF& color, F32 z, U32 stencil );
+   virtual void clearColorAttachment(const U32 attachment, const LinearColorF& color);
    virtual bool beginSceneInternal();
    virtual void endSceneInternal();
 

+ 3 - 0
Engine/source/gfx/gl/gfxGLEnumTranslate.cpp

@@ -138,6 +138,7 @@ void GFXGLEnumTranslate::init()
    GFXGLTextureInternalFormat[GFXFormatR8G8B8X8] = GL_RGBA8;
    GFXGLTextureInternalFormat[GFXFormatB8G8R8A8] = GL_RGBA8;
    GFXGLTextureInternalFormat[GFXFormatR10G10B10A2] = GL_RGB10_A2;
+   GFXGLTextureInternalFormat[GFXFormatR11G11B10] = GL_R11F_G11F_B10F;   
    GFXGLTextureInternalFormat[GFXFormatD32] = GL_DEPTH_COMPONENT32;
    GFXGLTextureInternalFormat[GFXFormatD24X8] = GL_DEPTH24_STENCIL8;
    GFXGLTextureInternalFormat[GFXFormatD24S8] = GL_DEPTH24_STENCIL8;
@@ -165,6 +166,7 @@ void GFXGLEnumTranslate::init()
    GFXGLTextureFormat[GFXFormatR8G8B8X8] = GL_RGBA;
    GFXGLTextureFormat[GFXFormatB8G8R8A8] = GL_BGRA;
    GFXGLTextureFormat[GFXFormatR10G10B10A2] = GL_RGBA;
+   GFXGLTextureFormat[GFXFormatR11G11B10] = GL_RGB;
    GFXGLTextureFormat[GFXFormatD32] = GL_DEPTH_COMPONENT;
    GFXGLTextureFormat[GFXFormatD24X8] = GL_DEPTH_STENCIL;
    GFXGLTextureFormat[GFXFormatD24S8] = GL_DEPTH_STENCIL;
@@ -192,6 +194,7 @@ void GFXGLEnumTranslate::init()
    GFXGLTextureType[GFXFormatR8G8B8X8] = GL_UNSIGNED_BYTE;
    GFXGLTextureType[GFXFormatB8G8R8A8] = GL_UNSIGNED_BYTE;;
    GFXGLTextureType[GFXFormatR10G10B10A2] = GL_UNSIGNED_INT_10_10_10_2;
+   GFXGLTextureType[GFXFormatR11G11B10] = GL_UNSIGNED_INT_10F_11F_11F_REV;
    GFXGLTextureType[GFXFormatD32] = GL_UNSIGNED_INT;
    GFXGLTextureType[GFXFormatD24X8] = GL_UNSIGNED_INT_24_8;
    GFXGLTextureType[GFXFormatD24S8] = GL_UNSIGNED_INT_24_8;

+ 7 - 1
Engine/source/gfx/gl/gfxGLTextureTarget.cpp

@@ -136,6 +136,7 @@ class _GFXGLTextureTargetFBOImpl : public _GFXGLTextureTargetImpl
 {
 public:
    GLuint mFramebuffer;
+   bool mGenMips;
    
    _GFXGLTextureTargetFBOImpl(GFXGLTextureTarget* target);
    virtual ~_GFXGLTextureTargetFBOImpl();
@@ -147,6 +148,7 @@ public:
 
 _GFXGLTextureTargetFBOImpl::_GFXGLTextureTargetFBOImpl(GFXGLTextureTarget* target)
 {
+   mGenMips = target->isGenMipsEnabled();
    mTarget = target;
    glGenFramebuffers(1, &mFramebuffer);
 }
@@ -245,6 +247,9 @@ void _GFXGLTextureTargetFBOImpl::finish()
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, 0);
 
+   if (!mGenMips)
+      return;
+
    for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
    {   
       _GFXGLTargetDesc* color = mTarget->getTargetDesc( static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0+i ) );
@@ -263,8 +268,9 @@ void _GFXGLTextureTargetFBOImpl::finish()
 }
 
 // Actual GFXGLTextureTarget interface
-GFXGLTextureTarget::GFXGLTextureTarget() : mCopyFboSrc(0), mCopyFboDst(0)
+GFXGLTextureTarget::GFXGLTextureTarget(bool genMips) : mCopyFboSrc(0), mCopyFboDst(0)
 {
+   mGenMips = genMips;
    for(U32 i=0; i<MaxRenderSlotId; i++)
       mTargets[i] = NULL;
    

+ 1 - 1
Engine/source/gfx/gl/gfxGLTextureTarget.h

@@ -45,7 +45,7 @@ class _GFXGLTextureTargetImpl;
 class GFXGLTextureTarget : public GFXTextureTarget
 {
 public:
-   GFXGLTextureTarget();
+   GFXGLTextureTarget(bool genMips);
    virtual ~GFXGLTextureTarget();
 
    virtual const Point2I getSize();

+ 14 - 1
Engine/source/gfx/sim/cubemapData.cpp

@@ -112,7 +112,7 @@ void CubemapData::createMap()
           {
              if (!mCubeFaceFile[i].isEmpty())
              {
-                if (!mCubeFace[i].set(mCubeFaceFile[i], &GFXStaticTextureProfile, avar("%s() - mCubeFace[%d] (line %d)", __FUNCTION__, i, __LINE__)))
+                if (!mCubeFace[i].set(mCubeFaceFile[i], &GFXStaticTextureSRGBProfile, avar("%s() - mCubeFace[%d] (line %d)", __FUNCTION__, i, __LINE__)))
                 {
                    Con::errorf("CubemapData::createMap - Failed to load texture '%s'", mCubeFaceFile[i].c_str());
                    initSuccess = false;
@@ -164,6 +164,11 @@ void CubemapData::updateFaces()
 	}
 }
 
+void CubemapData::setCubemapFile(FileName newCubemapFile)
+{
+   mCubeMapFile = newCubemapFile;
+}
+
 void CubemapData::setCubeFaceFile(U32 index, FileName newFaceFile)
 {
    if (index >= 6)
@@ -172,6 +177,14 @@ void CubemapData::setCubeFaceFile(U32 index, FileName newFaceFile)
    mCubeFaceFile[index] = newFaceFile;
 }
 
+void CubemapData::setCubeFaceTexture(U32 index, GFXTexHandle newFaceTexture)
+{
+   if (index >= 6)
+      return;
+
+   mCubeFace[index] = newFaceTexture;
+}
+
 DefineEngineMethod( CubemapData, updateFaces, void, (),,
    "Update the assigned cubemaps faces." )
 {

+ 5 - 0
Engine/source/gfx/sim/cubemapData.h

@@ -63,7 +63,12 @@ public:
    // Update a static cubemap @ pos
 	void updateFaces();
 
+   void setCubemapFile(FileName newCubemapFile);
+
    void setCubeFaceFile(U32 index, FileName newFaceFile);
+
+   void setCubeFaceTexture(U32 index, GFXTexHandle newFaceTexture);
+
    GFXTexHandle* getCubeMapFace(U32 faceIdx) { return &mCubeFace[faceIdx]; }
 
 protected: