mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-25 14:25:38 +00:00
Update GFXTextureManager and GBitmap
GBitmap Changes: Added all other formats to gbitmap that we support gbitmap now supports cubemaps added converters for all these other formats added stb_image_resize for extrudemips so we can extrude mipmaps for all other formats GFXTextureManager Can now directly make cubemaps and texture arrays based on the GFXTextureProfile API implementations for all functions that cubemaps and arrays needed
This commit is contained in:
parent
975fc924cc
commit
3aef90a6bc
66 changed files with 4235 additions and 2590 deletions
|
|
@ -38,6 +38,7 @@ GFXD3D11TextureTarget::GFXD3D11TextureTarget(bool genMips)
|
|||
mResolveTargets[i] = NULL;
|
||||
mTargetViews[i] = NULL;
|
||||
mTargetSRViews[i] = NULL;
|
||||
mTargetArrayIdx[i] = 0;
|
||||
}
|
||||
|
||||
mGenMips = genMips;
|
||||
|
|
@ -57,9 +58,9 @@ GFXD3D11TextureTarget::~GFXD3D11TextureTarget()
|
|||
zombify();
|
||||
}
|
||||
|
||||
void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *tex, U32 mipLevel/*=0*/, U32 zOffset /*= 0*/ )
|
||||
void GFXD3D11TextureTarget::attachTexture(RenderSlot slot, GFXTextureObject* tex, U32 mipLevel /*= 0*/, U32 zOffset /*= 0*/, U32 faceIndex /*= 0*/)
|
||||
{
|
||||
GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_attachTexture, ColorI::RED );
|
||||
GFXDEBUGEVENT_SCOPE(GFXPCD3D11TextureTarget_attachTexture, ColorI::RED);
|
||||
|
||||
AssertFatal(slot < MaxRenderSlotId, "GFXD3D11TextureTarget::attachTexture - out of range slot.");
|
||||
|
||||
|
|
@ -76,17 +77,17 @@ void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *te
|
|||
SAFE_RELEASE(mTargetViews[slot]);
|
||||
SAFE_RELEASE(mTargets[slot]);
|
||||
SAFE_RELEASE(mTargetSRViews[slot]);
|
||||
|
||||
mResolveTargets[slot] = NULL;
|
||||
mTargetArrayIdx[slot] = 0;
|
||||
|
||||
if(slot == Color0)
|
||||
if (slot == Color0)
|
||||
{
|
||||
mTargetSize = Point2I::Zero;
|
||||
mTargetFormat = GFXFormatR8G8B8A8;
|
||||
}
|
||||
|
||||
// Are we clearing?
|
||||
if(!tex)
|
||||
if (!tex)
|
||||
{
|
||||
// Yup - just exit, it'll stay NULL.
|
||||
return;
|
||||
|
|
@ -96,7 +97,7 @@ void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *te
|
|||
mTargetSRViews[slot] = NULL;
|
||||
|
||||
// Take care of default targets
|
||||
if( tex == GFXTextureTarget::sDefaultDepthStencil )
|
||||
if (tex == GFXTextureTarget::sDefaultDepthStencil)
|
||||
{
|
||||
mTargets[slot] = D3D11->mDeviceDepthStencil;
|
||||
mTargetViews[slot] = D3D11->mDeviceDepthStencilView;
|
||||
|
|
@ -108,81 +109,100 @@ void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *te
|
|||
// Cast the texture object to D3D...
|
||||
AssertFatal(dynamic_cast<GFXD3D11TextureObject*>(tex), "GFXD3D11TextureTarget::attachTexture - invalid texture object.");
|
||||
|
||||
GFXD3D11TextureObject *d3dto = dynamic_cast<GFXD3D11TextureObject*>(tex);
|
||||
GFXD3D11TextureObject* d3dto = dynamic_cast<GFXD3D11TextureObject*>(tex);
|
||||
bool isCube = d3dto->isCubeMap();
|
||||
|
||||
// Grab the surface level.
|
||||
if( slot == DepthStencil )
|
||||
{
|
||||
if (slot == DepthStencil)
|
||||
{
|
||||
mTargets[slot] = d3dto->getSurface();
|
||||
if ( mTargets[slot] )
|
||||
if (mTargets[slot])
|
||||
mTargets[slot]->AddRef();
|
||||
|
||||
mTargetViews[slot] = d3dto->getDSView();
|
||||
if( mTargetViews[slot])
|
||||
mTargetViews[slot]->AddRef();
|
||||
if (mTargetViews[slot])
|
||||
mTargetViews[slot]->AddRef();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// getSurface will almost always return NULL. It will only return non-NULL
|
||||
// if the surface that it needs to render to is different than the mip level
|
||||
// in the actual texture. This will happen with MSAA.
|
||||
if( d3dto->getSurface() == NULL )
|
||||
{
|
||||
if (!isCube)
|
||||
{
|
||||
|
||||
mTargets[slot] = d3dto->get2DTex();
|
||||
mTargets[slot]->AddRef();
|
||||
mTargetViews[slot] = d3dto->getRTView();
|
||||
mTargetViews[slot]->AddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
mTargets[slot] = d3dto->getSurface();
|
||||
mTargets[slot]->AddRef();
|
||||
mTargetViews[slot]->AddRef();
|
||||
mResolveTargets[slot] = d3dto;
|
||||
|
||||
if ( tex && slot == Color0 )
|
||||
if (d3dto->getSurface() == NULL)
|
||||
{
|
||||
mTargetSize.set( tex->getSize().x, tex->getSize().y );
|
||||
mTargetFormat = tex->getFormat();
|
||||
mTargets[slot] = d3dto->get2DTex();
|
||||
mTargets[slot]->AddRef();
|
||||
mTargetViews[slot] = d3dto->getRTView();
|
||||
mTargetViews[slot]->AddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
mTargets[slot] = d3dto->getSurface();
|
||||
mTargets[slot]->AddRef();
|
||||
mTargetViews[slot] = d3dto->getRTView();
|
||||
mTargetViews[slot]->AddRef();
|
||||
mResolveTargets[slot] = d3dto;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cubemap render target face
|
||||
mGenMips = false;
|
||||
AssertFatal(faceIndex < 6, "Invalid cubemap face index!");
|
||||
ID3D11RenderTargetView* faceRTV = d3dto->getCubeFaceRTView(faceIndex);
|
||||
AssertFatal(faceRTV, "Cubemap face RTV is null!");
|
||||
|
||||
mTargetArrayIdx[slot] = faceIndex;
|
||||
|
||||
if (d3dto->getSurface() == NULL)
|
||||
{
|
||||
mTargets[slot] = d3dto->get2DTex();
|
||||
mTargets[slot]->AddRef();
|
||||
mTargetViews[slot] = faceRTV;
|
||||
mTargetViews[slot]->AddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
mTargets[slot] = d3dto->getSurface();
|
||||
mTargets[slot]->AddRef();
|
||||
mTargetViews[slot] = faceRTV;
|
||||
mTargetViews[slot]->AddRef();
|
||||
mResolveTargets[slot] = d3dto;
|
||||
}
|
||||
}
|
||||
|
||||
// For mip generation
|
||||
if (mGenMips)
|
||||
{
|
||||
mTargetSRViews[slot] = d3dto->getSRView();
|
||||
mTargetSRViews[slot]->AddRef();
|
||||
if (mTargetSRViews[slot])
|
||||
mTargetSRViews[slot]->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
// Update surface size
|
||||
if(slot == Color0)
|
||||
// Update color target info
|
||||
if (slot == Color0)
|
||||
{
|
||||
ID3D11Texture2D *surface = mTargets[Color0];
|
||||
if ( surface )
|
||||
ID3D11Texture2D* surface = mTargets[Color0];
|
||||
if (surface)
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC sd;
|
||||
surface->GetDesc(&sd);
|
||||
mTargetSize = Point2I(sd.Width, sd.Height);
|
||||
|
||||
S32 format = sd.Format;
|
||||
|
||||
if (format == DXGI_FORMAT_R8G8B8A8_TYPELESS || format == DXGI_FORMAT_B8G8R8A8_TYPELESS)
|
||||
{
|
||||
mTargetFormat = GFXFormatR8G8B8A8;
|
||||
return;
|
||||
else
|
||||
{
|
||||
GFXREVERSE_LOOKUP(GFXD3D11TextureFormat, GFXFormat, format);
|
||||
mTargetFormat = (GFXFormat)format;
|
||||
}
|
||||
|
||||
GFXREVERSE_LOOKUP( GFXD3D11TextureFormat, GFXFormat, format );
|
||||
mTargetFormat = (GFXFormat)format;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel/*=0*/ )
|
||||
{
|
||||
GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_attachTexture_Cubemap, ColorI::RED );
|
||||
|
|
@ -316,7 +336,9 @@ void GFXD3D11TextureTarget::resolveTo( GFXTextureObject *tex )
|
|||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
mTargets[Color0]->GetDesc(&desc);
|
||||
D3D11DEVICECONTEXT->CopySubresourceRegion(((GFXD3D11TextureObject*)(tex))->get2DTex(), 0, 0, 0, 0, mTargets[Color0], 0, NULL);
|
||||
UINT mipLevels = desc.MipLevels ? desc.MipLevels : 1;
|
||||
UINT subResource = D3D11CalcSubresource(0, mTargetArrayIdx[Color0], mipLevels);
|
||||
D3D11DEVICECONTEXT->CopySubresourceRegion(((GFXD3D11TextureObject*)(tex))->get2DTex(), 0, 0, 0, 0, mTargets[Color0], subResource, NULL);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ class GFXD3D11TextureTarget : public GFXTextureTarget
|
|||
|
||||
GFXFormat mTargetFormat;
|
||||
|
||||
U32 mTargetArrayIdx[MaxRenderSlotId];
|
||||
|
||||
public:
|
||||
|
||||
GFXD3D11TextureTarget(bool genMips);
|
||||
|
|
@ -57,7 +59,7 @@ public:
|
|||
// Public interface.
|
||||
const Point2I getSize() override { return mTargetSize; }
|
||||
GFXFormat getFormat() override { return mTargetFormat; }
|
||||
void attachTexture(RenderSlot slot, GFXTextureObject *tex, U32 mipLevel=0, U32 zOffset = 0) override;
|
||||
void attachTexture(RenderSlot slot, GFXTextureObject* tex, U32 mipLevel = 0, U32 zOffset = 0, U32 faceIndex = 0) override;
|
||||
void attachTexture(RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel=0) override;
|
||||
void resolve() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ void GFXD3D11TextureManager::_innerCreateTexture( GFXD3D11TextureObject *retTex,
|
|||
GFXTextureProfile *profile,
|
||||
U32 numMipLevels,
|
||||
bool forceMips,
|
||||
S32 antialiasLevel)
|
||||
S32 antialiasLevel,
|
||||
U32 arraySize)
|
||||
{
|
||||
U32 usage = 0;
|
||||
U32 bindFlags = 0;
|
||||
|
|
@ -67,6 +68,9 @@ void GFXD3D11TextureManager::_innerCreateTexture( GFXD3D11TextureObject *retTex,
|
|||
retTex->isManaged = false;
|
||||
DXGI_FORMAT d3dTextureFormat = GFXD3D11TextureFormat[format];
|
||||
|
||||
if (retTex->isCubeMap())
|
||||
miscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
|
||||
|
||||
if( retTex->mProfile->isDynamic() )
|
||||
{
|
||||
usage = D3D11_USAGE_DYNAMIC;
|
||||
|
|
@ -199,7 +203,7 @@ void GFXD3D11TextureManager::_innerCreateTexture( GFXD3D11TextureObject *retTex,
|
|||
D3D11_TEXTURE2D_DESC desc;
|
||||
|
||||
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
|
||||
desc.ArraySize = 1;
|
||||
desc.ArraySize = arraySize * (retTex->isCubeMap() ? 6 : 1);
|
||||
desc.BindFlags = bindFlags;
|
||||
desc.CPUAccessFlags = cpuFlags;
|
||||
desc.Format = d3dTextureFormat;
|
||||
|
|
@ -219,6 +223,7 @@ void GFXD3D11TextureManager::_innerCreateTexture( GFXD3D11TextureObject *retTex,
|
|||
|
||||
retTex->get2DTex()->GetDesc(&desc);
|
||||
retTex->mMipLevels = desc.MipLevels;
|
||||
retTex->mArraySize = arraySize;
|
||||
}
|
||||
|
||||
// start creating the resource views...
|
||||
|
|
@ -267,6 +272,7 @@ GFXTextureObject *GFXD3D11TextureManager::_createTextureObject( U32 height,
|
|||
U32 numMipLevels,
|
||||
bool forceMips,
|
||||
S32 antialiasLevel,
|
||||
U32 arraySize,
|
||||
GFXTextureObject *inTex )
|
||||
{
|
||||
GFXD3D11TextureObject *retTex;
|
||||
|
|
@ -278,11 +284,11 @@ GFXTextureObject *GFXD3D11TextureManager::_createTextureObject( U32 height,
|
|||
}
|
||||
else
|
||||
{
|
||||
retTex = new GFXD3D11TextureObject(GFX, profile);
|
||||
retTex = new GFXD3D11TextureObject(GFX, profile, arraySize);
|
||||
retTex->registerResourceWithDevice(GFX);
|
||||
}
|
||||
|
||||
_innerCreateTexture(retTex, height, width, depth, format, profile, numMipLevels, forceMips, antialiasLevel);
|
||||
_innerCreateTexture(retTex, height, width, depth, format, profile, numMipLevels, forceMips, antialiasLevel, arraySize);
|
||||
|
||||
return retTex;
|
||||
}
|
||||
|
|
@ -295,7 +301,9 @@ bool GFXD3D11TextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *p
|
|||
|
||||
// Check with profiler to see if we can do automatic mipmap generation.
|
||||
const bool supportsAutoMips = GFX->getCardProfiler()->queryProfile("autoMipMapLevel", true);
|
||||
|
||||
|
||||
const bool isCube = texture->isCubeMap() && pDL->getNumFaces() > 1;
|
||||
const U32 numFaces = isCube ? 6 : 1;
|
||||
// Helper bool
|
||||
const bool isCompressedTexFmt = ImageUtil::isCompressedFormat(aTexture->mFormat);
|
||||
|
||||
|
|
@ -312,98 +320,101 @@ bool GFXD3D11TextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *p
|
|||
|
||||
bool isDynamic = texture->mProfile->isDynamic();
|
||||
// Fill the texture...
|
||||
for( U32 i = 0; i < maxDownloadMip; i++ )
|
||||
for (U32 face = 0; face < numFaces; ++face)
|
||||
{
|
||||
U32 subResource = D3D11CalcSubresource(i, 0, aTexture->mMipLevels);
|
||||
for (U32 i = 0; i < maxDownloadMip; i++)
|
||||
{
|
||||
U32 subResource = D3D11CalcSubresource(i, face, aTexture->mMipLevels);
|
||||
|
||||
if(!isDynamic)
|
||||
{
|
||||
U8* copyBuffer = NULL;
|
||||
if (!isDynamic)
|
||||
{
|
||||
U8* copyBuffer = NULL;
|
||||
|
||||
switch(texture->mFormat)
|
||||
{
|
||||
switch (texture->mFormat)
|
||||
{
|
||||
case GFXFormatR8G8B8:
|
||||
case GFXFormatR8G8B8_SRGB:
|
||||
{
|
||||
PROFILE_SCOPE(Swizzle24_Upload);
|
||||
{
|
||||
PROFILE_SCOPE(Swizzle24_Upload);
|
||||
|
||||
U8* Bits = new U8[pDL->getWidth(i) * pDL->getHeight(i) * 4];
|
||||
dMemcpy(Bits, pDL->getBits(i), pDL->getWidth(i) * pDL->getHeight(i) * 3);
|
||||
bitmapConvertRGB_to_RGBX(&Bits, pDL->getWidth(i) * pDL->getHeight(i));
|
||||
copyBuffer = new U8[pDL->getWidth(i) * pDL->getHeight(i) * 4];
|
||||
|
||||
dev->getDeviceSwizzle32()->ToBuffer(copyBuffer, Bits, pDL->getWidth(i) * pDL->getHeight(i) * 4);
|
||||
dev->getDeviceContext()->UpdateSubresource(texture->get2DTex(), subResource, NULL, copyBuffer, pDL->getWidth() * 4, pDL->getHeight() *4);
|
||||
U8* Bits = new U8[pDL->getWidth(i) * pDL->getHeight(i) * 4];
|
||||
dMemcpy(Bits, pDL->getBits(i, face), pDL->getWidth(i) * pDL->getHeight(i) * 3);
|
||||
bitmapConvertRGB_to_RGBX(&Bits, pDL->getWidth(i) * pDL->getHeight(i));
|
||||
copyBuffer = new U8[pDL->getWidth(i) * pDL->getHeight(i) * 4];
|
||||
|
||||
dev->getDeviceSwizzle32()->ToBuffer(copyBuffer, Bits, pDL->getWidth(i) * pDL->getHeight(i) * 4);
|
||||
dev->getDeviceContext()->UpdateSubresource(texture->get2DTex(), subResource, NULL, copyBuffer, pDL->getWidth() * 4, pDL->getHeight() * 4);
|
||||
SAFE_DELETE_ARRAY(Bits);
|
||||
break;
|
||||
}
|
||||
|
||||
case GFXFormatR8G8B8A8:
|
||||
case GFXFormatR8G8B8X8:
|
||||
case GFXFormatR8G8B8A8_SRGB:
|
||||
{
|
||||
PROFILE_SCOPE(Swizzle32_Upload);
|
||||
copyBuffer = new U8[pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel()];
|
||||
dev->getDeviceSwizzle32()->ToBuffer(copyBuffer, pDL->getBits(i), pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel());
|
||||
dev->getDeviceContext()->UpdateSubresource(texture->get2DTex(), subResource, NULL, copyBuffer, pDL->getWidth() * pDL->getBytesPerPixel(), pDL->getHeight() *pDL->getBytesPerPixel());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// Just copy the bits in no swizzle or padding
|
||||
PROFILE_SCOPE(SwizzleNull_Upload);
|
||||
AssertFatal( pDL->getFormat() == texture->mFormat, "Format mismatch");
|
||||
dev->getDeviceContext()->UpdateSubresource(texture->get2DTex(), subResource, NULL, pDL->getBits(i), pDL->getWidth() *pDL->getBytesPerPixel(), pDL->getHeight() *pDL->getBytesPerPixel());
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY(copyBuffer);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapping;
|
||||
HRESULT res = dev->getDeviceContext()->Map(texture->get2DTex(), subResource, D3D11_MAP_WRITE, 0, &mapping);
|
||||
|
||||
AssertFatal(res, "tex2d map call failure");
|
||||
|
||||
switch( texture->mFormat )
|
||||
{
|
||||
case GFXFormatR8G8B8:
|
||||
case GFXFormatR8G8B8_SRGB:
|
||||
{
|
||||
PROFILE_SCOPE(Swizzle24_Upload);
|
||||
|
||||
U8* Bits = new U8[pDL->getWidth(i) * pDL->getHeight(i) * 4];
|
||||
dMemcpy(Bits, pDL->getBits(i), pDL->getWidth(i) * pDL->getHeight(i) * 3);
|
||||
bitmapConvertRGB_to_RGBX(&Bits, pDL->getWidth(i) * pDL->getHeight(i));
|
||||
|
||||
dev->getDeviceSwizzle32()->ToBuffer(mapping.pData, Bits, pDL->getWidth(i) * pDL->getHeight(i) * 4);
|
||||
SAFE_DELETE_ARRAY(Bits);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
case GFXFormatR8G8B8A8:
|
||||
case GFXFormatR8G8B8X8:
|
||||
case GFXFormatR8G8B8A8_SRGB:
|
||||
{
|
||||
PROFILE_SCOPE(Swizzle32_Upload);
|
||||
dev->getDeviceSwizzle32()->ToBuffer(mapping.pData, pDL->getBits(i), pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel());
|
||||
copyBuffer = new U8[pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel()];
|
||||
dev->getDeviceSwizzle32()->ToBuffer(copyBuffer, pDL->getBits(i, face), pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel());
|
||||
dev->getDeviceContext()->UpdateSubresource(texture->get2DTex(), subResource, NULL, copyBuffer, pDL->getWidth() * pDL->getBytesPerPixel(), pDL->getHeight() * pDL->getBytesPerPixel());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
default:
|
||||
{
|
||||
// Just copy the bits in no swizzle or padding
|
||||
PROFILE_SCOPE(SwizzleNull_Upload);
|
||||
AssertFatal( pDL->getFormat() == texture->mFormat, "Format mismatch");
|
||||
dMemcpy(mapping.pData, pDL->getBits(i), pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel());
|
||||
}
|
||||
}
|
||||
AssertFatal(pDL->getFormat() == texture->mFormat, "Format mismatch");
|
||||
dev->getDeviceContext()->UpdateSubresource(texture->get2DTex(), subResource, NULL, pDL->getBits(i, face), pDL->getWidth() * pDL->getBytesPerPixel(), pDL->getHeight() * pDL->getBytesPerPixel());
|
||||
}
|
||||
}
|
||||
|
||||
dev->getDeviceContext()->Unmap(texture->get2DTex(), subResource);
|
||||
}
|
||||
SAFE_DELETE_ARRAY(copyBuffer);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapping;
|
||||
HRESULT res = dev->getDeviceContext()->Map(texture->get2DTex(), subResource, D3D11_MAP_WRITE, 0, &mapping);
|
||||
|
||||
AssertFatal(res, "tex2d map call failure");
|
||||
|
||||
switch (texture->mFormat)
|
||||
{
|
||||
case GFXFormatR8G8B8:
|
||||
case GFXFormatR8G8B8_SRGB:
|
||||
{
|
||||
PROFILE_SCOPE(Swizzle24_Upload);
|
||||
|
||||
U8* Bits = new U8[pDL->getWidth(i) * pDL->getHeight(i) * 4];
|
||||
dMemcpy(Bits, pDL->getBits(i, face), pDL->getWidth(i) * pDL->getHeight(i) * 3);
|
||||
bitmapConvertRGB_to_RGBX(&Bits, pDL->getWidth(i) * pDL->getHeight(i));
|
||||
|
||||
dev->getDeviceSwizzle32()->ToBuffer(mapping.pData, Bits, pDL->getWidth(i) * pDL->getHeight(i) * 4);
|
||||
SAFE_DELETE_ARRAY(Bits);
|
||||
}
|
||||
break;
|
||||
|
||||
case GFXFormatR8G8B8A8:
|
||||
case GFXFormatR8G8B8X8:
|
||||
case GFXFormatR8G8B8A8_SRGB:
|
||||
{
|
||||
PROFILE_SCOPE(Swizzle32_Upload);
|
||||
dev->getDeviceSwizzle32()->ToBuffer(mapping.pData, pDL->getBits(i, face), pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// Just copy the bits in no swizzle or padding
|
||||
PROFILE_SCOPE(SwizzleNull_Upload);
|
||||
AssertFatal(pDL->getFormat() == texture->mFormat, "Format mismatch");
|
||||
dMemcpy(mapping.pData, pDL->getBits(i, face), pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel());
|
||||
}
|
||||
}
|
||||
|
||||
dev->getDeviceContext()->Unmap(texture->get2DTex(), subResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
|
|
@ -487,7 +498,7 @@ bool GFXD3D11TextureManager::_refreshTexture(GFXTextureObject *texture)
|
|||
if(texture->mProfile->isRenderTarget() || texture->mProfile->isDynamic() || texture->mProfile->isZTarget())
|
||||
{
|
||||
realTex->release();
|
||||
_innerCreateTexture(realTex, texture->getHeight(), texture->getWidth(), texture->getDepth(), texture->mFormat, texture->mProfile, texture->mMipLevels, false, texture->mAntialiasLevel);
|
||||
_innerCreateTexture(realTex, texture->getHeight(), texture->getWidth(), texture->getDepth(), texture->mFormat, texture->mProfile, texture->mMipLevels, false, texture->mAntialiasLevel, texture->mArraySize);
|
||||
usedStrategies++;
|
||||
}
|
||||
|
||||
|
|
@ -519,14 +530,31 @@ bool GFXD3D11TextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *d
|
|||
GFXD3D11TextureObject *texture = static_cast<GFXD3D11TextureObject*>(aTexture);
|
||||
GFXD3D11Device* dev = static_cast<GFXD3D11Device *>(GFX);
|
||||
// Fill the texture...
|
||||
for( U32 i = 0; i < aTexture->mMipLevels; i++ )
|
||||
const bool isCube = texture->isCubeMap() && dds->isCubemap();
|
||||
const U32 numFaces = isCube ? 6 : 1;
|
||||
|
||||
// Loop over faces and mips
|
||||
for (U32 face = 0; face < numFaces; ++face)
|
||||
{
|
||||
PROFILE_SCOPE(GFXD3DTexMan_loadSurface);
|
||||
for (U32 mip = 0; mip < aTexture->mMipLevels; ++mip)
|
||||
{
|
||||
PROFILE_SCOPE(GFXD3DTexMan_loadSurface);
|
||||
|
||||
AssertFatal( dds->mSurfaces.size() > 0, "Assumption failed. DDSFile has no surfaces." );
|
||||
// DDSFile must have data for each face
|
||||
AssertFatal(dds->mSurfaces.size() > face, "DDSFile missing cubemap face data.");
|
||||
AssertFatal(dds->mSurfaces[face]->mMips.size() > mip, "DDSFile missing mip level.");
|
||||
|
||||
U32 subresource = D3D11CalcSubresource(i, 0, aTexture->mMipLevels);
|
||||
dev->getDeviceContext()->UpdateSubresource(texture->get2DTex(), subresource, 0, dds->mSurfaces[0]->mMips[i], dds->getSurfacePitch(i), 0);
|
||||
const U32 subresource = D3D11CalcSubresource(mip, face, aTexture->mMipLevels);
|
||||
|
||||
dev->getDeviceContext()->UpdateSubresource(
|
||||
texture->get2DTex(), // resource
|
||||
subresource, // subresource index
|
||||
nullptr, // box (nullptr for full subresource)
|
||||
dds->mSurfaces[face]->mMips[mip], // source data pointer
|
||||
dds->getSurfacePitch(mip), // row pitch
|
||||
0 // depth pitch
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
|
|
@ -541,14 +569,14 @@ bool GFXD3D11TextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *d
|
|||
void GFXD3D11TextureManager::createResourceView(U32 height, U32 width, U32 depth, DXGI_FORMAT format, U32 numMipLevels,U32 usageFlags, GFXTextureObject *inTex)
|
||||
{
|
||||
GFXD3D11TextureObject *tex = static_cast<GFXD3D11TextureObject*>(inTex);
|
||||
ID3D11Resource* resource = NULL;
|
||||
|
||||
if(tex->get2DTex())
|
||||
resource = tex->get2DTex();
|
||||
else if(tex->getSurface())
|
||||
resource = tex->getSurface();
|
||||
else
|
||||
resource = tex->get3DTex();
|
||||
ID3D11Resource* resource;
|
||||
|
||||
if (tex->get2DTex())
|
||||
resource = tex->get2DTex();
|
||||
else if (tex->getSurface())
|
||||
resource = tex->getSurface();
|
||||
else
|
||||
resource = tex->get3DTex();
|
||||
|
||||
HRESULT hr;
|
||||
//TODO: add MSAA support later.
|
||||
|
|
@ -567,11 +595,40 @@ void GFXD3D11TextureManager::createResourceView(U32 height, U32 width, U32 depth
|
|||
desc.Texture3D.MipLevels = -1;
|
||||
desc.Texture3D.MostDetailedMip = 0;
|
||||
}
|
||||
else
|
||||
else if (tex->isCubeMap())
|
||||
{
|
||||
if (tex->getArraySize() == 1)
|
||||
{
|
||||
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
desc.TextureCube.MipLevels = -1;
|
||||
desc.TextureCube.MostDetailedMip = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
|
||||
desc.TextureCubeArray.MostDetailedMip = 0;
|
||||
desc.TextureCubeArray.MipLevels = -1;
|
||||
desc.TextureCubeArray.First2DArrayFace = 0;
|
||||
desc.TextureCubeArray.NumCubes = tex->getArraySize();
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
desc.Texture2D.MipLevels = -1;
|
||||
desc.Texture2D.MostDetailedMip = 0;
|
||||
if (tex->getArraySize() == 1)
|
||||
{
|
||||
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
desc.Texture2D.MipLevels = -1;
|
||||
desc.Texture2D.MostDetailedMip = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
||||
desc.Texture2DArray.MipLevels = -1;
|
||||
desc.Texture2DArray.MostDetailedMip = 0;
|
||||
desc.Texture2DArray.FirstArraySlice = 0;
|
||||
desc.Texture2DArray.ArraySize = tex->getArraySize();
|
||||
}
|
||||
}
|
||||
|
||||
hr = D3D11DEVICE->CreateShaderResourceView(resource,&desc, tex->getSRViewPtr());
|
||||
|
|
@ -580,12 +637,29 @@ void GFXD3D11TextureManager::createResourceView(U32 height, U32 width, U32 depth
|
|||
|
||||
if(usageFlags & D3D11_BIND_RENDER_TARGET)
|
||||
{
|
||||
D3D11_RENDER_TARGET_VIEW_DESC desc;
|
||||
desc.Format = format;
|
||||
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
desc.Texture2D.MipSlice = 0;
|
||||
hr = D3D11DEVICE->CreateRenderTargetView(resource, &desc, tex->getRTViewPtr());
|
||||
AssertFatal(SUCCEEDED(hr), "CreateRenderTargetView:: failed to create view!");
|
||||
if (tex->isCubeMap())
|
||||
{
|
||||
for (U32 face = 0; face < 6; face++)
|
||||
{
|
||||
D3D11_RENDER_TARGET_VIEW_DESC desc;
|
||||
desc.Format = format;
|
||||
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
desc.Texture2DArray.ArraySize = 1;
|
||||
desc.Texture2DArray.FirstArraySlice = face;
|
||||
desc.Texture2DArray.MipSlice = 0;
|
||||
hr = D3D11DEVICE->CreateRenderTargetView(resource, &desc, tex->getCubeFaceRTViewPtr(face));
|
||||
AssertFatal(SUCCEEDED(hr), "CreateRenderTargetView:: failed to create view!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D11_RENDER_TARGET_VIEW_DESC desc;
|
||||
desc.Format = format;
|
||||
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
desc.Texture2D.MipSlice = 0;
|
||||
hr = D3D11DEVICE->CreateRenderTargetView(resource, &desc, tex->getRTViewPtr());
|
||||
AssertFatal(SUCCEEDED(hr), "CreateRenderTargetView:: failed to create view!");
|
||||
}
|
||||
}
|
||||
|
||||
if(usageFlags & D3D11_BIND_DEPTH_STENCIL)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ protected:
|
|||
U32 numMipLevels,
|
||||
bool forceMips = false,
|
||||
S32 antialiasLevel = 0,
|
||||
U32 arraySize = 1,
|
||||
GFXTextureObject *inTex = NULL ) override;
|
||||
|
||||
bool _loadTexture(GFXTextureObject *texture, DDSFile *dds) override;
|
||||
|
|
@ -56,7 +57,7 @@ protected:
|
|||
private:
|
||||
U32 mCurTexSet[GFX_TEXTURE_STAGE_COUNT];
|
||||
|
||||
void _innerCreateTexture(GFXD3D11TextureObject *obj, U32 height, U32 width, U32 depth, GFXFormat format, GFXTextureProfile *profile, U32 numMipLevels, bool forceMips = false, S32 antialiasLevel = 0);
|
||||
void _innerCreateTexture(GFXD3D11TextureObject *obj, U32 height, U32 width, U32 depth, GFXFormat format, GFXTextureProfile *profile, U32 numMipLevels, bool forceMips = false, S32 antialiasLevel = 0, U32 arraySize = 1);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,26 +33,16 @@ U32 GFXD3D11TextureObject::mTexCount = 0;
|
|||
// GFXFormatR8G8B8 has now the same behaviour as GFXFormatR8G8B8X8.
|
||||
// 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.
|
||||
// DirectX 10-11 both have 24 bit format no longer.
|
||||
|
||||
|
||||
GFXD3D11TextureObject::GFXD3D11TextureObject( GFXDevice * d, GFXTextureProfile *profile) : GFXTextureObject( d, profile )
|
||||
GFXD3D11TextureObject::GFXD3D11TextureObject( GFXDevice * d, GFXTextureProfile *profile, const U32 arraySize) : GFXTextureObject( d, profile )
|
||||
{
|
||||
#ifdef D3D11_DEBUG_SPEW
|
||||
mTexCount++;
|
||||
Con::printf("+ texMake %d %x", mTexCount, this);
|
||||
#endif
|
||||
|
||||
mD3DTexture = NULL;
|
||||
mLocked = false;
|
||||
|
||||
mD3DSurface = NULL;
|
||||
isManaged = false;
|
||||
dMemset(&mLockRect, 0, sizeof(mLockRect));
|
||||
dMemset(&mLockBox, 0, sizeof(mLockBox));
|
||||
mLockedSubresource = 0;
|
||||
mDSView = NULL;
|
||||
mRTView = NULL;
|
||||
mSRView = NULL;
|
||||
isManaged = false;
|
||||
mArraySize = arraySize;
|
||||
}
|
||||
|
||||
GFXD3D11TextureObject::~GFXD3D11TextureObject()
|
||||
|
|
@ -64,53 +54,76 @@ GFXD3D11TextureObject::~GFXD3D11TextureObject()
|
|||
#endif
|
||||
}
|
||||
|
||||
GFXLockedRect *GFXD3D11TextureObject::lock(U32 mipLevel /*= 0*/, RectI *inRect /*= NULL*/)
|
||||
ID3D11Texture2D* GFXD3D11TextureObject::get2DTex() const
|
||||
{
|
||||
AssertFatal( !mLocked, "GFXD3D11TextureObject::lock - The texture is already locked!" );
|
||||
ComPtr<ID3D11Texture2D> tex2D;
|
||||
if (mD3DTexture) mD3DTexture.As(&tex2D);
|
||||
return tex2D.Get();
|
||||
}
|
||||
|
||||
if( !mStagingTex ||
|
||||
ID3D11Texture3D* GFXD3D11TextureObject::get3DTex() const
|
||||
{
|
||||
ComPtr<ID3D11Texture3D> tex3D;
|
||||
if (mD3DTexture) mD3DTexture.As(&tex3D);
|
||||
return tex3D.Get();
|
||||
}
|
||||
|
||||
ID3D11Texture2D** GFXD3D11TextureObject::get2DTexPtr()
|
||||
{
|
||||
return reinterpret_cast<ID3D11Texture2D**>(mD3DTexture.GetAddressOf());
|
||||
}
|
||||
|
||||
ID3D11Texture3D** GFXD3D11TextureObject::get3DTexPtr()
|
||||
{
|
||||
return reinterpret_cast<ID3D11Texture3D**>(mD3DTexture.GetAddressOf());
|
||||
}
|
||||
|
||||
ID3D11RenderTargetView** GFXD3D11TextureObject::getCubeFaceRTViewPtr(U32 face)
|
||||
{
|
||||
AssertFatal(isCubeMap(), "Not a cubemap texture!");
|
||||
AssertFatal(face < 6, "Invalid cubemap face index!");
|
||||
return mCubeRTV[face].GetAddressOf();
|
||||
}
|
||||
|
||||
GFXLockedRect* GFXD3D11TextureObject::lock(U32 mipLevel /*= 0*/, RectI* inRect /*= NULL*/, U32 faceIndex /*= 0*/)
|
||||
{
|
||||
AssertFatal(!mLocked, "GFXD3D11TextureObject::lock - Texture is already locked!");
|
||||
AssertFatal(faceIndex < 6 || !isCubeMap(), "Invalid cubemap face index!");
|
||||
|
||||
// Ensure staging texture exists and matches size
|
||||
if (!mStagingTex.isValid() ||
|
||||
mStagingTex->getWidth() != getWidth() ||
|
||||
mStagingTex->getHeight() != getHeight() ||
|
||||
mStagingTex->getDepth() != getDepth())
|
||||
{
|
||||
if (getDepth() != 0)
|
||||
{
|
||||
mStagingTex.set(getWidth(), getHeight(), getDepth(), mFormat, &GFXSystemMemTextureProfile, avar("%s() - mLockTex (line %d)", __FUNCTION__, __LINE__, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
mStagingTex.set(getWidth(), getHeight(), mFormat, &GFXSystemMemTextureProfile, avar("%s() - mLockTex (line %d)", __FUNCTION__, __LINE__));
|
||||
}
|
||||
mStagingTex.set(getWidth(), getHeight(), mFormat, &GFXSystemMemTextureProfile,
|
||||
avar("%s() - stagingTex", __FUNCTION__));
|
||||
}
|
||||
|
||||
ID3D11DeviceContext* pContext = D3D11DEVICECONTEXT;
|
||||
D3D11_MAPPED_SUBRESOURCE mapInfo;
|
||||
U32 offset = 0;
|
||||
mLockedSubresource = D3D11CalcSubresource(mipLevel, 0, getMipLevels());
|
||||
GFXD3D11TextureObject* pD3DStagingTex = (GFXD3D11TextureObject*)&(*mStagingTex);
|
||||
|
||||
//map staging texture
|
||||
HRESULT hr = pContext->Map(pD3DStagingTex->getResource(), mLockedSubresource, D3D11_MAP_WRITE, 0, &mapInfo);
|
||||
mLockedSubresource = D3D11CalcSubresource(mipLevel, faceIndex, getMipLevels());
|
||||
GFXD3D11TextureObject* staging = (GFXD3D11TextureObject*)&(*mStagingTex);
|
||||
|
||||
HRESULT hr = D3D11DEVICECONTEXT->Map(staging->getResource(), mLockedSubresource, D3D11_MAP_WRITE, 0, &mapInfo);
|
||||
if (FAILED(hr))
|
||||
AssertFatal(false, "GFXD3D11TextureObject:lock - failed to map render target resource!");
|
||||
|
||||
|
||||
const bool is3D = mStagingTex->getDepth() != 0;
|
||||
const U32 width = mTextureSize.x >> mipLevel;
|
||||
const U32 height = mTextureSize.y >> mipLevel;
|
||||
const U32 depth = is3D ? mTextureSize.z >> mipLevel : 1;
|
||||
U32 offset = 0;
|
||||
|
||||
//calculate locked box region and offset
|
||||
if (inRect)
|
||||
{
|
||||
if ((inRect->point.x + inRect->extent.x > width) || (inRect->point.y + inRect->extent.y > height))
|
||||
AssertFatal(false, "GFXD3D11TextureObject::lock - Rectangle too big!");
|
||||
AssertFatal(inRect->point.x + inRect->extent.x <= width, "GFXD3D11TextureObject::lock - Invalid lock rect width!");
|
||||
AssertFatal(inRect->point.y + inRect->extent.y <= height, "GFXD3D11TextureObject::lock - Invalid lock rect height!");
|
||||
|
||||
mLockBox.top = inRect->point.y;
|
||||
mLockBox.left = inRect->point.x;
|
||||
mLockBox.bottom = inRect->point.y + inRect->extent.y;
|
||||
mLockBox.right = inRect->point.x + inRect->extent.x;
|
||||
mLockBox.bottom = inRect->point.y + inRect->extent.y;
|
||||
mLockBox.back = depth;
|
||||
mLockBox.front = 0;
|
||||
|
||||
|
|
@ -121,49 +134,57 @@ GFXLockedRect *GFXD3D11TextureObject::lock(U32 mipLevel /*= 0*/, RectI *inRect /
|
|||
{
|
||||
mLockBox.top = 0;
|
||||
mLockBox.left = 0;
|
||||
mLockBox.bottom = height;
|
||||
mLockBox.right = width;
|
||||
mLockBox.bottom = height;
|
||||
mLockBox.back = depth;
|
||||
mLockBox.front = 0;
|
||||
|
||||
}
|
||||
|
||||
mLocked = true;
|
||||
mLockRect.pBits = static_cast<U8*>(mapInfo.pData) + offset;
|
||||
mLockRect.Pitch = mapInfo.RowPitch;
|
||||
|
||||
return (GFXLockedRect*)&mLockRect;
|
||||
return reinterpret_cast<GFXLockedRect*>(&mLockRect);
|
||||
}
|
||||
|
||||
void GFXD3D11TextureObject::unlock(U32 mipLevel)
|
||||
void GFXD3D11TextureObject::unlock(U32 mipLevel /*= 0*/, U32 faceIndex /*= 0*/)
|
||||
{
|
||||
AssertFatal( mLocked, "GFXD3D11TextureObject::unlock - Attempting to unlock a surface that has not been locked" );
|
||||
AssertFatal(mLocked, "GFXD3D11TextureObject::unlock - Texture is not locked!");
|
||||
AssertFatal(faceIndex < 6 || !isCubeMap(), "Invalid cubemap face index!");
|
||||
|
||||
//profile in the unlock function because all the heavy lifting is done here
|
||||
PROFILE_START(GFXD3D11TextureObject_lockRT);
|
||||
PROFILE_START(GFXD3D11TextureObject_unlock);
|
||||
|
||||
ID3D11DeviceContext* pContext = D3D11DEVICECONTEXT;
|
||||
GFXD3D11TextureObject* pD3DStagingTex = (GFXD3D11TextureObject*)&(*mStagingTex);
|
||||
ID3D11Resource* pStagingResource = pD3DStagingTex->getResource();
|
||||
const bool is3D = mStagingTex->getDepth() != 0;
|
||||
GFXD3D11TextureObject* staging = (GFXD3D11TextureObject*)&(*mStagingTex);
|
||||
|
||||
//unmap staging texture
|
||||
pContext->Unmap(pStagingResource, mLockedSubresource);
|
||||
//copy lock box region from the staging texture to our regular texture
|
||||
pContext->CopySubresourceRegion(mD3DTexture, mLockedSubresource, mLockBox.left, mLockBox.top, is3D ? mLockBox.back : 0, pStagingResource, mLockedSubresource, &mLockBox);
|
||||
D3D11DEVICECONTEXT->Unmap(staging->getResource(), mLockedSubresource);
|
||||
|
||||
PROFILE_END();
|
||||
// Copy from staging back to GPU texture
|
||||
D3D11DEVICECONTEXT->CopySubresourceRegion(
|
||||
mD3DTexture.Get(),
|
||||
mLockedSubresource,
|
||||
0, 0, 0,
|
||||
staging->getResource(),
|
||||
mLockedSubresource,
|
||||
&mLockBox
|
||||
);
|
||||
|
||||
mLockedSubresource = 0;
|
||||
mLocked = false;
|
||||
|
||||
PROFILE_END();
|
||||
}
|
||||
|
||||
void GFXD3D11TextureObject::release()
|
||||
{
|
||||
SAFE_RELEASE(mSRView);
|
||||
SAFE_RELEASE(mRTView);
|
||||
SAFE_RELEASE(mDSView);
|
||||
SAFE_RELEASE(mD3DTexture);
|
||||
SAFE_RELEASE(mD3DSurface);
|
||||
mSRView.Reset();
|
||||
mRTView.Reset();
|
||||
mDSView.Reset();
|
||||
mD3DTexture.Reset();
|
||||
mD3DSurface.Reset();
|
||||
|
||||
for (auto& faceRTV : mCubeRTV)
|
||||
faceRTV.Reset();
|
||||
}
|
||||
|
||||
void GFXD3D11TextureObject::zombify()
|
||||
|
|
@ -189,149 +210,206 @@ bool GFXD3D11TextureObject::copyToBmp(GBitmap* bmp)
|
|||
if (!bmp)
|
||||
return false;
|
||||
|
||||
// check format limitations
|
||||
// at the moment we only support RGBA for the source (other 4 byte formats should
|
||||
// be easy to add though)
|
||||
AssertFatal(mFormat == GFXFormatR16G16B16A16F || mFormat == GFXFormatR8G8B8A8 || mFormat == GFXFormatR8G8B8A8_LINEAR_FORCE || mFormat == GFXFormatR8G8B8A8_SRGB || mFormat == GFXFormatR8G8B8, "copyToBmp: invalid format");
|
||||
if (mFormat != GFXFormatR16G16B16A16F && mFormat != GFXFormatR8G8B8A8 && mFormat != GFXFormatR8G8B8A8_LINEAR_FORCE && mFormat != GFXFormatR8G8B8A8_SRGB && mFormat != GFXFormatR8G8B8)
|
||||
return false;
|
||||
AssertFatal(mFormat == GFXFormatR16G16B16A16F || mFormat == GFXFormatR8G8B8A8 ||
|
||||
mFormat == GFXFormatR8G8B8A8_LINEAR_FORCE || mFormat == GFXFormatR8G8B8A8_SRGB ||
|
||||
mFormat == GFXFormatR8G8B8,
|
||||
"GFXD3D11TextureObject::copyToBmp - Unsupported source format.");
|
||||
|
||||
PROFILE_START(GFXD3D11TextureObject_copyToBmp);
|
||||
|
||||
AssertFatal(bmp->getWidth() == getWidth(), avar("GFXGLTextureObject::copyToBmp - Width mismatch: %i vs %i", bmp->getWidth(), getWidth()));
|
||||
AssertFatal(bmp->getHeight() == getHeight(), avar("GFXGLTextureObject::copyToBmp - Height mismatch: %i vs %i", bmp->getHeight(), getHeight()));
|
||||
const U32 mipLevels = getMipLevels();
|
||||
AssertFatal(bmp->getWidth() == getWidth(), "Width mismatch between texture and bitmap.");
|
||||
AssertFatal(bmp->getHeight() == getHeight(), "Height mismatch between texture and bitmap.");
|
||||
|
||||
const U32 mipLevels = getMipLevels();
|
||||
bmp->setHasTransparency(mHasTransparency);
|
||||
|
||||
// set some constants
|
||||
U32 sourceBytesPerPixel = 4;
|
||||
U32 destBytesPerPixel = 0;
|
||||
// Figure out bytes per pixel
|
||||
const bool isFP16 = (bmp->getFormat() == GFXFormatR16G16B16A16F);
|
||||
const U32 destBpp = (bmp->getFormat() == GFXFormatR8G8B8 ? 3 :
|
||||
bmp->getFormat() == GFXFormatR16G16B16A16F ? 8 : 4);
|
||||
const U32 srcBpp = (mFormat == GFXFormatR16G16B16A16F ? 8 : 4);
|
||||
|
||||
const GFXFormat fmt = bmp->getFormat();
|
||||
bool fp16 = false;//is rgba16f format?
|
||||
if (fmt == GFXFormatR16G16B16A16F)
|
||||
{
|
||||
destBytesPerPixel = 8;
|
||||
sourceBytesPerPixel = 8;
|
||||
fp16 = true;
|
||||
}
|
||||
else if (fmt == GFXFormatR8G8B8A8 || fmt == GFXFormatR8G8B8A8_LINEAR_FORCE || fmt == GFXFormatR8G8B8A8_SRGB)
|
||||
destBytesPerPixel = 4;
|
||||
else if(bmp->getFormat() == GFXFormatR8G8B8)
|
||||
destBytesPerPixel = 3;
|
||||
else
|
||||
// unsupported
|
||||
AssertFatal(false, "GFXD3D11TextureObject::copyToBmp - unsupported bitmap format");
|
||||
|
||||
//create temp staging texture
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
static_cast<ID3D11Texture2D*>(mD3DTexture)->GetDesc(&desc);
|
||||
// --- Create staging texture ---
|
||||
D3D11_TEXTURE2D_DESC desc = {};
|
||||
reinterpret_cast<ID3D11Texture2D*>(mD3DTexture.Get())->GetDesc(&desc);
|
||||
desc.BindFlags = 0;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
ID3D11Texture2D* pStagingTexture = NULL;
|
||||
HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &pStagingTexture);
|
||||
ComPtr<ID3D11Texture2D> stagingTex;
|
||||
HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, nullptr, stagingTex.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Con::errorf("GFXD3D11TextureObject::copyToBmp - Failed to create staging texture");
|
||||
Con::errorf("GFXD3D11TextureObject::copyToBmp - Failed to create staging texture (0x%X)", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
//copy the classes texture to the staging texture
|
||||
D3D11DEVICECONTEXT->CopyResource(pStagingTexture, mD3DTexture);
|
||||
// --- Copy texture (handle cubemap or 2D) ---
|
||||
const U32 faceCount = isCubeMap() && bmp->getNumFaces() == 6 ? 6 : 1;
|
||||
|
||||
for (U32 mip = 0; mip < mipLevels; mip++)
|
||||
for (U32 face = 0; face < faceCount; ++face)
|
||||
{
|
||||
const U32 width = bmp->getWidth(mip);
|
||||
const U32 height = bmp->getHeight(mip);
|
||||
//map the staging resource
|
||||
D3D11_MAPPED_SUBRESOURCE mappedRes;
|
||||
const U32 subResource = D3D11CalcSubresource(mip, 0, mipLevels);
|
||||
hr = D3D11DEVICECONTEXT->Map(pStagingTexture, subResource, D3D11_MAP_READ, 0, &mappedRes);
|
||||
if (FAILED(hr))
|
||||
for (U32 mip = 0; mip < mipLevels; ++mip)
|
||||
{
|
||||
//cleanup
|
||||
SAFE_RELEASE(pStagingTexture);
|
||||
Con::errorf("GFXD3D11TextureObject::copyToBmp - Failed to map staging texture");
|
||||
return false;
|
||||
}
|
||||
const U32 srcSubRes = D3D11CalcSubresource(mip, face, mipLevels);
|
||||
// Always map mip-level 0..mipLevels-1 on *slice 0* of the staging texture
|
||||
const U32 dstSubRes = D3D11CalcSubresource(mip, face, mipLevels);
|
||||
|
||||
// set pointers
|
||||
const U8* srcPtr = (U8*)mappedRes.pData;
|
||||
U8* destPtr = bmp->getWritableBits(mip);
|
||||
D3D11DEVICECONTEXT->CopySubresourceRegion(
|
||||
stagingTex.Get(), dstSubRes, 0, 0, 0,
|
||||
mD3DTexture.Get(), srcSubRes, nullptr);
|
||||
|
||||
// we will want to skip over any D3D cache data in the source texture
|
||||
const S32 sourceCacheSize = mappedRes.RowPitch - width * sourceBytesPerPixel;
|
||||
AssertFatal(sourceCacheSize >= 0, "GFXD3D11TextureObject::copyToBmp - cache size is less than zero?");
|
||||
|
||||
// copy data into bitmap
|
||||
for (U32 row = 0; row < height; ++row)
|
||||
{
|
||||
for (U32 col = 0; col < width; ++col)
|
||||
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
||||
hr = D3D11DEVICECONTEXT->Map(stagingTex.Get(), dstSubRes, D3D11_MAP_READ, 0, &mapped);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
//we can just copy data straight in with RGBA16F format
|
||||
if (fp16)
|
||||
{
|
||||
dMemcpy(destPtr, srcPtr, sizeof(U16) * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
destPtr[0] = srcPtr[2]; // red
|
||||
destPtr[1] = srcPtr[1]; // green
|
||||
destPtr[2] = srcPtr[0]; // blue
|
||||
if (destBytesPerPixel == 4)
|
||||
destPtr[3] = srcPtr[3]; // alpha
|
||||
}
|
||||
|
||||
// go to next pixel in src
|
||||
srcPtr += sourceBytesPerPixel;
|
||||
|
||||
// go to next pixel in dest
|
||||
destPtr += destBytesPerPixel;
|
||||
Con::errorf("GFXD3D11TextureObject::copyToBmp - Failed to map staging texture (0x%X)", hr);
|
||||
return false;
|
||||
}
|
||||
// skip past the cache data for this row (if any)
|
||||
srcPtr += sourceCacheSize;
|
||||
|
||||
const U8* src = static_cast<const U8*>(mapped.pData);
|
||||
U8* dst = bmp->getWritableBits(mip, face);
|
||||
|
||||
const U32 width = bmp->getWidth(mip);
|
||||
const U32 height = bmp->getHeight(mip);
|
||||
|
||||
for (U32 y = 0; y < height; ++y)
|
||||
{
|
||||
const U8* srcRow = src;
|
||||
U8* dstRow = dst;
|
||||
|
||||
for (U32 x = 0; x < width; ++x)
|
||||
{
|
||||
if (isFP16)
|
||||
{
|
||||
dMemcpy(dstRow, srcRow, sizeof(U16) * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert BGRA → RGB(A)
|
||||
dstRow[0] = srcRow[2];
|
||||
dstRow[1] = srcRow[1];
|
||||
dstRow[2] = srcRow[0];
|
||||
if (destBpp == 4)
|
||||
dstRow[3] = srcRow[3];
|
||||
}
|
||||
srcRow += srcBpp;
|
||||
dstRow += destBpp;
|
||||
}
|
||||
|
||||
src += mapped.RowPitch;
|
||||
dst += width * destBpp;
|
||||
}
|
||||
|
||||
D3D11DEVICECONTEXT->Unmap(stagingTex.Get(), dstSubRes);
|
||||
}
|
||||
|
||||
// assert if we stomped or underran memory
|
||||
AssertFatal(U32(destPtr - bmp->getWritableBits(mip)) == width * height * destBytesPerPixel, "GFXD3D11TextureObject::copyToBmp - memory error");
|
||||
AssertFatal(U32(srcPtr - (U8*)mappedRes.pData) == height * mappedRes.RowPitch, "GFXD3D11TextureObject::copyToBmp - memory error");
|
||||
|
||||
D3D11DEVICECONTEXT->Unmap(pStagingTexture, subResource);
|
||||
}
|
||||
|
||||
SAFE_RELEASE(pStagingTexture);
|
||||
PROFILE_END();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ID3D11ShaderResourceView* GFXD3D11TextureObject::getSRView()
|
||||
void GFXD3D11TextureObject::generateMipMaps()
|
||||
{
|
||||
return mSRView;
|
||||
}
|
||||
ID3D11RenderTargetView* GFXD3D11TextureObject::getRTView()
|
||||
{
|
||||
return mRTView;
|
||||
}
|
||||
ID3D11DepthStencilView* GFXD3D11TextureObject::getDSView()
|
||||
{
|
||||
return mDSView;
|
||||
//Generate mips
|
||||
D3D11DEVICECONTEXT->GenerateMips(mSRView.Get());
|
||||
//get mip level count
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
|
||||
mSRView->GetDesc(&viewDesc);
|
||||
mMipLevels = viewDesc.TextureCube.MipLevels;
|
||||
}
|
||||
|
||||
ID3D11ShaderResourceView** GFXD3D11TextureObject::getSRViewPtr()
|
||||
void GFXD3D11TextureObject::updateTextureSlot(const GFXTexHandle& texHandle, const U32 slot, const S32 faceIdx /*=-1*/)
|
||||
{
|
||||
return &mSRView;
|
||||
}
|
||||
ID3D11RenderTargetView** GFXD3D11TextureObject::getRTViewPtr()
|
||||
{
|
||||
return &mRTView;
|
||||
AssertFatal(slot < getArraySize(), "updateTextureSlot - destination slot out of bounds");
|
||||
AssertFatal(mFormat == texHandle->getFormat(), "updateTextureSlot - format mismatch");
|
||||
AssertFatal(getMipLevels() == texHandle->getMipLevels(), "updateTextureSlot - mip level mismatch");
|
||||
|
||||
GFXD3D11TextureObject* srcTex = static_cast<GFXD3D11TextureObject*>(texHandle.getPointer());
|
||||
|
||||
ID3D11Resource* dstRes = get2DTex();
|
||||
ID3D11Resource* srcRes = srcTex->get2DTex();
|
||||
|
||||
const UINT mipLevels = getMipLevels();
|
||||
|
||||
const bool dstIsCube = isCubeMap();
|
||||
const bool srcIsCube = srcTex->isCubeMap();
|
||||
|
||||
const UINT dstArraySize = getArraySize();
|
||||
const UINT srcArraySize = srcTex->getArraySize();
|
||||
|
||||
// Determine number of faces to copy
|
||||
const UINT faceCount = srcIsCube ? 6 : 1;
|
||||
const UINT startFace = (faceIdx >= 0) ? faceIdx : 0;
|
||||
const UINT endFace = (faceIdx >= 0) ? faceIdx + 1 : faceCount;
|
||||
|
||||
for (UINT face = startFace; face < endFace; ++face)
|
||||
{
|
||||
// Compute source slice
|
||||
const UINT srcSlice = srcIsCube
|
||||
? (srcArraySize > 1 ? face + slot * 6 : face) // only add slot*6 if it's a cubemap array
|
||||
: (srcArraySize > 1 ? face + slot : 0); // otherwise, single 2D texture or 2D array
|
||||
|
||||
const UINT dstSlice = dstIsCube
|
||||
? (dstArraySize > 1 ? face + slot * 6 : face) // only add slot*6 if it's a cubemap array
|
||||
: (dstArraySize > 1 ? face + slot : 0); // otherwise, single 2D texture or 2D array
|
||||
|
||||
for (UINT mip = 0; mip < mipLevels; ++mip)
|
||||
{
|
||||
const UINT srcSubresource = D3D11CalcSubresource(mip, srcSlice, mipLevels);
|
||||
const UINT dstSubresource = D3D11CalcSubresource(mip, dstSlice, mipLevels);
|
||||
|
||||
D3D11DEVICECONTEXT->CopySubresourceRegion(dstRes, dstSubresource, 0, 0, 0, srcRes, srcSubresource, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11DepthStencilView** GFXD3D11TextureObject::getDSViewPtr()
|
||||
void GFXD3D11TextureObject::copyTo(GFXTextureObject* dstTex)
|
||||
{
|
||||
return &mDSView;
|
||||
AssertFatal(dstTex, "GFXD3D11TextureObject::copyTo - destination is null");
|
||||
|
||||
GFXD3D11TextureObject* pDstTex = static_cast<GFXD3D11TextureObject*>(dstTex);
|
||||
|
||||
ID3D11Texture2D* srcTex = (ID3D11Texture2D*)mD3DTexture.Get();
|
||||
ID3D11Texture2D* dstTex2D = pDstTex->get2DTex();
|
||||
|
||||
D3D11_TEXTURE2D_DESC srcDesc, dstDesc;
|
||||
srcTex->GetDesc(&srcDesc);
|
||||
dstTex2D->GetDesc(&dstDesc);
|
||||
|
||||
// Sanity check – sizes and formats must match for a full copy.
|
||||
AssertFatal(srcDesc.Width == dstDesc.Width && srcDesc.Height == dstDesc.Height,
|
||||
"GFXD3D11TextureObject::copyTo - Mismatched texture dimensions");
|
||||
AssertFatal(srcDesc.Format == dstDesc.Format,
|
||||
"GFXD3D11TextureObject::copyTo - Mismatched formats");
|
||||
|
||||
UINT srcMipLevels = srcDesc.MipLevels ? srcDesc.MipLevels : 1;
|
||||
UINT dstMipLevels = dstDesc.MipLevels ? dstDesc.MipLevels : 1;
|
||||
UINT mipLevels = getMin(srcMipLevels, dstMipLevels);
|
||||
|
||||
UINT srcArraySize = srcDesc.ArraySize;
|
||||
UINT dstArraySize = dstDesc.ArraySize;
|
||||
UINT arraySize = getMin(srcArraySize, dstArraySize);
|
||||
|
||||
// Handle cube maps and cube map arrays
|
||||
bool isCubeSrc = (srcDesc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) != 0;
|
||||
|
||||
// In cubemaps, ArraySize is always 6 * numCubes
|
||||
if (isCubeSrc) arraySize = srcArraySize; // 6 or 6*nCubes
|
||||
|
||||
for (UINT arraySlice = 0; arraySlice < arraySize; ++arraySlice)
|
||||
{
|
||||
for (UINT mip = 0; mip < mipLevels; ++mip)
|
||||
{
|
||||
UINT srcSubresource = D3D11CalcSubresource(mip, arraySlice, srcMipLevels);
|
||||
UINT dstSubresource = D3D11CalcSubresource(mip, arraySlice, dstMipLevels);
|
||||
|
||||
D3D11DEVICECONTEXT->CopySubresourceRegion(
|
||||
dstTex2D, dstSubresource,
|
||||
0, 0, 0,
|
||||
srcTex, srcSubresource,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,55 +27,77 @@
|
|||
#include "gfx/gfxTextureHandle.h"
|
||||
#include "gfx/gfxTextureManager.h"
|
||||
|
||||
#include <wrl/client.h>
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
class GFXD3D11TextureObject : public GFXTextureObject
|
||||
{
|
||||
protected:
|
||||
static U32 mTexCount;
|
||||
|
||||
GFXTexHandle mStagingTex;
|
||||
DXGI_MAPPED_RECT mLockRect;
|
||||
D3D11_BOX mLockBox;
|
||||
bool mLocked;
|
||||
bool mLocked = false;
|
||||
|
||||
U32 mLockedSubresource;
|
||||
ID3D11Resource *mD3DTexture;
|
||||
U32 mLockedSubresource = 0;
|
||||
|
||||
// used for z buffers...
|
||||
ID3D11Texture2D *mD3DSurface;
|
||||
// Main GPU texture resource (2D / 3D / Cubemap)
|
||||
ComPtr<ID3D11Resource> mD3DTexture;
|
||||
|
||||
ID3D11ShaderResourceView* mSRView; // for shader resource input
|
||||
ID3D11RenderTargetView* mRTView; // for render targets
|
||||
ID3D11DepthStencilView* mDSView; //render target view for depth stencil
|
||||
// Used for Z-targets
|
||||
ComPtr<ID3D11Texture2D> mD3DSurface;
|
||||
|
||||
// Views
|
||||
ComPtr<ID3D11ShaderResourceView> mSRView; // Shader resource
|
||||
ComPtr<ID3D11RenderTargetView> mRTView; // Render target
|
||||
ComPtr<ID3D11DepthStencilView> mDSView; // Depth stencil
|
||||
|
||||
// Cubemap face render target views (optional)
|
||||
ComPtr<ID3D11RenderTargetView> mCubeRTV[6];
|
||||
public:
|
||||
|
||||
GFXD3D11TextureObject( GFXDevice * d, GFXTextureProfile *profile);
|
||||
GFXD3D11TextureObject( GFXDevice * d, GFXTextureProfile *profile, const U32 arraySize = 1);
|
||||
~GFXD3D11TextureObject();
|
||||
|
||||
ID3D11Resource* getResource(){ return mD3DTexture; }
|
||||
ID3D11Texture2D* get2DTex(){ return (ID3D11Texture2D*) mD3DTexture; }
|
||||
ID3D11Texture2D** get2DTexPtr(){ return (ID3D11Texture2D**) &mD3DTexture; }
|
||||
ID3D11Texture3D* get3DTex(){ return (ID3D11Texture3D*) mD3DTexture; }
|
||||
ID3D11Texture3D** get3DTexPtr(){ return (ID3D11Texture3D**) &mD3DTexture; }
|
||||
|
||||
ID3D11ShaderResourceView* getSRView();
|
||||
ID3D11RenderTargetView* getRTView();
|
||||
ID3D11DepthStencilView* getDSView();
|
||||
// Accessors
|
||||
ID3D11Resource* getResource() const { return mD3DTexture.Get(); }
|
||||
ID3D11Texture2D* get2DTex() const;
|
||||
ID3D11Texture3D* get3DTex() const;
|
||||
ID3D11Texture2D** get2DTexPtr();
|
||||
ID3D11Texture3D** get3DTexPtr();
|
||||
|
||||
ID3D11ShaderResourceView** getSRViewPtr();
|
||||
ID3D11RenderTargetView** getRTViewPtr();
|
||||
ID3D11DepthStencilView** getDSViewPtr();
|
||||
|
||||
ID3D11ShaderResourceView* getSRView() const { return mSRView.Get(); }
|
||||
ID3D11RenderTargetView* getRTView() const { return mRTView.Get(); }
|
||||
ID3D11DepthStencilView* getDSView() const { return mDSView.Get(); }
|
||||
|
||||
ID3D11ShaderResourceView** getSRViewPtr() { return mSRView.GetAddressOf(); }
|
||||
ID3D11RenderTargetView** getRTViewPtr() { return mRTView.GetAddressOf(); }
|
||||
ID3D11DepthStencilView** getDSViewPtr() { return mDSView.GetAddressOf(); }
|
||||
|
||||
// Cubemap face RTV access (for render-to-cubemap)
|
||||
ID3D11RenderTargetView* getCubeFaceRTView(U32 face) const
|
||||
{
|
||||
AssertFatal(isCubeMap(), "Not a cubemap texture!");
|
||||
AssertFatal(face < 6, "Invalid cubemap face index!");
|
||||
return mCubeRTV[face].Get();
|
||||
}
|
||||
|
||||
ID3D11RenderTargetView** getCubeFaceRTViewPtr(U32 face);
|
||||
|
||||
void release();
|
||||
|
||||
bool isManaged; //setting to true tells this texture not to be released from being zombify
|
||||
|
||||
GFXLockedRect * lock(U32 mipLevel = 0, RectI *inRect = NULL) override;
|
||||
void unlock(U32 mipLevel = 0 ) override;
|
||||
GFXLockedRect* lock(U32 mipLevel = 0, RectI* inRect = NULL, U32 faceIndex = 0) override;
|
||||
void unlock(U32 mipLevel = 0, U32 faceIndex = 0) override;
|
||||
|
||||
bool copyToBmp(GBitmap* bmp) override;
|
||||
ID3D11Texture2D* getSurface() {return mD3DSurface;}
|
||||
ID3D11Texture2D** getSurfacePtr() {return &mD3DSurface;}
|
||||
void generateMipMaps() override;
|
||||
void updateTextureSlot(const GFXTexHandle& texHandle, const U32 slot, const S32 face = -1) override;
|
||||
void copyTo(GFXTextureObject* dstTex) override;
|
||||
ID3D11Texture2D* getSurface() {return mD3DSurface.Get();}
|
||||
ID3D11Texture2D** getSurfacePtr() {return mD3DSurface.GetAddressOf();}
|
||||
|
||||
// GFXResource
|
||||
void zombify() override;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue