You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5433 lines
168 KiB
C++
5433 lines
168 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
|
|
// Description : Direct3D specific texture manager implementation.
|
|
|
|
|
|
#include "RenderDll_precompiled.h"
|
|
#include "DriverD3D.h"
|
|
#include "I3DEngine.h"
|
|
#include "StringUtils.h"
|
|
#include <ImageExtensionHelper.h>
|
|
#include "BitFiddling.h" // ConvertBlock3DcToDXT5()
|
|
#include "D3DStereo.h"
|
|
#include "../Common/PostProcess/PostProcessUtils.h"
|
|
#include "D3DPostProcess.h"
|
|
#include "../Common/Textures/TextureHelpers.h"
|
|
#include "../Common/Textures/TextureManager.h"
|
|
#include "../Common/RenderCapabilities.h"
|
|
#include <AzCore/Debug/AssetTracking.h>
|
|
#include <Common/Memory/VRAMDrillerBus.h>
|
|
|
|
#if AZ_RENDER_TO_TEXTURE_GEM_ENABLED
|
|
#include <RTTBus.h>
|
|
#endif // AZ_RENDER_TO_TEXTURE_GEM_ENABLED
|
|
|
|
#undef min
|
|
#undef max
|
|
//===============================================================================
|
|
namespace {
|
|
void SetShaderResourceViewDesc(const SResourceView& rv, uint32 texType, D3DFormat format, int arraySize, uint32 nSliceCount, D3D11_SHADER_RESOURCE_VIEW_DESC& desc)
|
|
{
|
|
const uint nMipCount = rv.m_Desc.nMipCount == SResourceView().m_Desc.nMipCount ? (uint) - 1 : (uint)rv.m_Desc.nMipCount;
|
|
ZeroStruct(desc);
|
|
desc.Format = CTexture::ConvertToShaderResourceFmt(format);
|
|
if (rv.m_Desc.bSrgbRead)
|
|
{
|
|
desc.Format = CTexture::ConvertToSRGBFmt(desc.Format);
|
|
}
|
|
switch (texType)
|
|
{
|
|
case eTT_1D:
|
|
if (arraySize > 1)
|
|
{
|
|
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
|
|
desc.Texture1DArray.MostDetailedMip = rv.m_Desc.nMostDetailedMip;
|
|
desc.Texture1DArray.MipLevels = nMipCount;
|
|
desc.Texture1DArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
desc.Texture1DArray.ArraySize = nSliceCount;
|
|
}
|
|
else
|
|
{
|
|
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
|
|
desc.Texture1D.MostDetailedMip = rv.m_Desc.nMostDetailedMip;
|
|
desc.Texture1D.MipLevels = nMipCount;
|
|
}
|
|
break;
|
|
case eTT_2D:
|
|
if (arraySize > 1)
|
|
{
|
|
if (rv.m_Desc.bMultisample)
|
|
{
|
|
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
|
|
desc.Texture2DMSArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
desc.Texture2DMSArray.ArraySize = nSliceCount;
|
|
}
|
|
else
|
|
{
|
|
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
|
desc.Texture2DArray.MostDetailedMip = rv.m_Desc.nMostDetailedMip;
|
|
desc.Texture2DArray.MipLevels = nMipCount;
|
|
desc.Texture2DArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
desc.Texture2DArray.ArraySize = nSliceCount;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (rv.m_Desc.bMultisample)
|
|
{
|
|
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
|
|
}
|
|
else
|
|
{
|
|
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
desc.Texture2D.MostDetailedMip = rv.m_Desc.nMostDetailedMip;
|
|
desc.Texture2D.MipLevels = nMipCount;
|
|
}
|
|
}
|
|
break;
|
|
case eTT_3D:
|
|
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
|
desc.Texture3D.MostDetailedMip = rv.m_Desc.nMostDetailedMip;
|
|
desc.Texture3D.MipLevels = nMipCount;
|
|
break;
|
|
case eTT_Cube:
|
|
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
|
desc.TextureCube.MostDetailedMip = rv.m_Desc.nMostDetailedMip;
|
|
desc.TextureCube.MipLevels = nMipCount;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SetRenderTargetViewDesc(const SResourceView& rv, uint32 texType, D3DFormat format, int arraySize, uint32 nSliceCount, D3D11_RENDER_TARGET_VIEW_DESC& rtvDesc)
|
|
{
|
|
ZeroStruct(rtvDesc);
|
|
rtvDesc.Format = format;
|
|
|
|
switch (texType)
|
|
{
|
|
case eTT_1D:
|
|
if (arraySize > 1)
|
|
{
|
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
|
|
rtvDesc.Texture1DArray.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
rtvDesc.Texture1DArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
rtvDesc.Texture1DArray.ArraySize = nSliceCount;
|
|
}
|
|
else
|
|
{
|
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
|
|
rtvDesc.Texture1D.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
}
|
|
break;
|
|
case eTT_2D:
|
|
if (arraySize > 1)
|
|
{
|
|
if (rv.m_Desc.bMultisample)
|
|
{
|
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
|
|
rtvDesc.Texture2DMSArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
rtvDesc.Texture2DMSArray.ArraySize = nSliceCount;
|
|
}
|
|
else
|
|
{
|
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
|
rtvDesc.Texture2DArray.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
rtvDesc.Texture2DArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
rtvDesc.Texture2DArray.ArraySize = nSliceCount;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (rv.m_Desc.bMultisample)
|
|
{
|
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
|
|
}
|
|
else
|
|
{
|
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
|
rtvDesc.Texture2D.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
}
|
|
}
|
|
break;
|
|
case eTT_3D:
|
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
|
|
rtvDesc.Texture3D.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
rtvDesc.Texture3D.FirstWSlice = rv.m_Desc.nFirstSlice;
|
|
rtvDesc.Texture3D.WSize = nSliceCount;
|
|
break;
|
|
case eTT_Cube:
|
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
|
rtvDesc.Texture2DArray.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
rtvDesc.Texture2DArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
rtvDesc.Texture2DArray.ArraySize = nSliceCount;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SetDepthStencilViewDesc(const SResourceView& rv, uint32 texType, D3DFormat format, int arraySize, uint32 nSliceCount, D3D11_DEPTH_STENCIL_VIEW_DESC& dsvDesc)
|
|
{
|
|
ZeroStruct(dsvDesc);
|
|
dsvDesc.Format = (DXGI_FORMAT)CTexture::ConvertToDepthStencilFmt(format);
|
|
|
|
switch (texType)
|
|
{
|
|
case eTT_1D:
|
|
if (arraySize > 1)
|
|
{
|
|
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY;
|
|
dsvDesc.Texture1DArray.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
dsvDesc.Texture1DArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
dsvDesc.Texture1DArray.ArraySize = nSliceCount;
|
|
}
|
|
else
|
|
{
|
|
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
|
|
dsvDesc.Texture1D.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
}
|
|
break;
|
|
case eTT_2D:
|
|
if (arraySize > 1)
|
|
{
|
|
if (rv.m_Desc.bMultisample)
|
|
{
|
|
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
|
|
dsvDesc.Texture2DMSArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
dsvDesc.Texture2DMSArray.ArraySize = nSliceCount;
|
|
}
|
|
else
|
|
{
|
|
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
|
dsvDesc.Texture2DArray.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
dsvDesc.Texture2DArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
dsvDesc.Texture2DArray.ArraySize = nSliceCount;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (rv.m_Desc.bMultisample)
|
|
{
|
|
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
|
|
}
|
|
else
|
|
{
|
|
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
|
dsvDesc.Texture2D.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
}
|
|
}
|
|
break;
|
|
case eTT_Cube:
|
|
{
|
|
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
|
dsvDesc.Texture2DArray.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
dsvDesc.Texture2DArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
dsvDesc.Texture2DArray.ArraySize = nSliceCount;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SetUnorderedAccessViewDesc(const SResourceView& rv, uint32 texType, D3DFormat format, int arraySize, uint32 nSliceCount, D3D11_UNORDERED_ACCESS_VIEW_DESC& desc)
|
|
{
|
|
ZeroStruct(desc);
|
|
desc.Format = format;
|
|
|
|
switch (texType)
|
|
{
|
|
case eTT_1D:
|
|
if (arraySize > 1)
|
|
{
|
|
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1DARRAY;
|
|
desc.Texture1DArray.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
desc.Texture1DArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
desc.Texture1DArray.ArraySize = nSliceCount;
|
|
}
|
|
else
|
|
{
|
|
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D;
|
|
desc.Texture1D.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
}
|
|
break;
|
|
case eTT_2D:
|
|
if (arraySize > 1)
|
|
{
|
|
AZ_Assert(rv.m_Desc.bMultisample == 0, "No MSAA in UAV Array");
|
|
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
|
|
desc.Texture2DArray.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
desc.Texture2DArray.FirstArraySlice = rv.m_Desc.nFirstSlice;
|
|
desc.Texture2DArray.ArraySize = nSliceCount;
|
|
}
|
|
else
|
|
{
|
|
AZ_Assert(rv.m_Desc.bMultisample == 0, "No MSAA in UAV");
|
|
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
|
|
desc.Texture2D.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
}
|
|
break;
|
|
case eTT_3D:
|
|
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
|
|
desc.Texture3D.MipSlice = rv.m_Desc.nMostDetailedMip;
|
|
desc.Texture3D.FirstWSlice = rv.m_Desc.nFirstSlice;
|
|
desc.Texture3D.WSize = nSliceCount;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
RenderTargetData::~RenderTargetData()
|
|
{
|
|
CDeviceTexture* pTexMSAA = (CDeviceTexture*)m_pDeviceTextureMSAA;
|
|
SAFE_RELEASE(pTexMSAA);
|
|
|
|
for (size_t i = 0; i < m_ResourceViews.size(); ++i)
|
|
{
|
|
const SResourceView& rv = m_ResourceViews[i];
|
|
switch (rv.m_Desc.eViewType)
|
|
{
|
|
case SResourceView::eShaderResourceView:
|
|
{
|
|
D3DShaderResourceView* pView = static_cast<D3DShaderResourceView*>(rv.m_pDeviceResourceView);
|
|
SAFE_RELEASE(pView);
|
|
break;
|
|
}
|
|
case SResourceView::eRenderTargetView:
|
|
{
|
|
D3DSurface* pView = static_cast<D3DSurface*>(rv.m_pDeviceResourceView);
|
|
SAFE_RELEASE(pView);
|
|
break;
|
|
}
|
|
case SResourceView::eDepthStencilView:
|
|
{
|
|
D3DDepthSurface* pView = static_cast<D3DDepthSurface*>(rv.m_pDeviceResourceView);
|
|
SAFE_RELEASE(pView);
|
|
break;
|
|
}
|
|
case SResourceView::eUnorderedAccessView:
|
|
{
|
|
D3DUnorderedAccessView* pView = static_cast<D3DUnorderedAccessView*>(rv.m_pDeviceResourceView);
|
|
SAFE_RELEASE(pView);
|
|
break;
|
|
}
|
|
default:
|
|
assert(false);
|
|
}
|
|
}
|
|
}
|
|
//===============================================================================
|
|
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#undef AZ_RESTRICTED_SECTION
|
|
#define D3DTEXTURE_CPP_SECTION_1 1
|
|
#define D3DTEXTURE_CPP_SECTION_2 2
|
|
#define D3DTEXTURE_CPP_SECTION_3 3
|
|
#define D3DTEXTURE_CPP_SECTION_4 4
|
|
#define D3DTEXTURE_CPP_SECTION_5 5
|
|
#define D3DTEXTURE_CPP_SECTION_6 6
|
|
#define D3DTEXTURE_CPP_SECTION_7 7
|
|
#define D3DTEXTURE_CPP_SECTION_8 8
|
|
#define D3DTEXTURE_CPP_SECTION_9 9
|
|
#define D3DTEXTURE_CPP_SECTION_10 10
|
|
#define D3DTEXTURE_CPP_SECTION_11 11
|
|
#define D3DTEXTURE_CPP_SECTION_12 12
|
|
#define D3DTEXTURE_CPP_SECTION_13 13
|
|
#define D3DTEXTURE_CPP_SECTION_14 14
|
|
#endif
|
|
|
|
#if defined(TEXTURE_GET_SYSTEM_COPY_SUPPORT)
|
|
byte* CTexture::Convert(const byte* sourceData, int nWidth, int nHeight, int sourceMipCount, ETEX_Format eTFSrc, ETEX_Format eTFDst, int& nOutSize, [[maybe_unused]] bool bLinear)
|
|
{
|
|
nOutSize = 0;
|
|
|
|
DXGI_FORMAT DeviceFormatSRC = (DXGI_FORMAT)DeviceFormatFromTexFormat(eTFSrc);
|
|
DXGI_FORMAT DeviceFormatDST = (DXGI_FORMAT)DeviceFormatFromTexFormat(eTFDst);
|
|
|
|
if (DeviceFormatSRC == DXGI_FORMAT_UNKNOWN || DeviceFormatDST == DXGI_FORMAT_UNKNOWN || nWidth <= 0 || nHeight <= 0)
|
|
{
|
|
AZ_Assert(false, "Invalid parameters to CTexture::Convert");
|
|
return nullptr;
|
|
}
|
|
|
|
if (sourceMipCount <= 0)
|
|
{
|
|
sourceMipCount = 1;
|
|
}
|
|
|
|
int outputSize = 0;
|
|
byte* outputData = nullptr;
|
|
|
|
if (eTFSrc == eTF_BC5U && eTFDst == eTF_BC3)
|
|
{
|
|
int w = nWidth;
|
|
int h = nHeight;
|
|
|
|
outputSize = CTexture::TextureDataSize(w, h, 1, sourceMipCount, 1, eTF_BC3);
|
|
outputData = new byte[outputSize];
|
|
|
|
int nOffsDST = 0;
|
|
int nOffsSRC = 0;
|
|
for (int mip = 0; mip < sourceMipCount; mip++)
|
|
{
|
|
if (w <= 0)
|
|
{
|
|
w = 1;
|
|
}
|
|
if (h <= 0)
|
|
{
|
|
h = 1;
|
|
}
|
|
|
|
const void* outSrc = &sourceData[nOffsSRC];
|
|
DWORD outSize = CTexture::TextureDataSize(w, h, 1, 1, 1, eTFDst);
|
|
|
|
nOffsSRC += CTexture::TextureDataSize(w, h, 1, 1, 1, eTFSrc);
|
|
|
|
{
|
|
const byte* src = (const byte*)outSrc;
|
|
|
|
for (uint32 n = 0; n < outSize / 16; n++) // for each block
|
|
{
|
|
const uint8* srcDataBlock = &src[n * 16];
|
|
uint8* outputDataBlock = &outputData[nOffsDST + n * 16];
|
|
ConvertBlock3DcToDXT5(outputDataBlock, srcDataBlock);
|
|
}
|
|
|
|
nOffsDST += outSize;
|
|
}
|
|
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
nOutSize = outputSize;
|
|
return outputData;
|
|
}
|
|
|
|
outputSize = CTexture::TextureDataSize(nWidth, nHeight, 1, sourceMipCount, 1, eTFSrc);
|
|
outputData = new byte[outputSize];
|
|
memcpy(outputData, sourceData, outputSize);
|
|
nOutSize = outputSize;
|
|
return outputData;
|
|
}
|
|
#endif //#if defined(WIN32) || defined(WIN64)
|
|
|
|
D3DSurface* CTexture::GetSurface(int nCMSide, int nLevel)
|
|
{
|
|
if (!m_pDevTexture)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (IsDeviceFormatTypeless(m_pPixelFormat->DeviceFormat))
|
|
{
|
|
iLog->Log("Error: CTexture::GetSurface: typeless formats can't be specified for RTVs, failed to create surface for the texture %s", GetSourceName());
|
|
return NULL;
|
|
}
|
|
|
|
SCOPED_RENDERER_ALLOCATION_NAME_HINT(GetSourceName());
|
|
|
|
HRESULT hr = S_OK;
|
|
D3DTexture* pID3DTexture = NULL;
|
|
D3DTexture* pID3DTexture3D = NULL;
|
|
D3DTexture* pID3DTextureCube = NULL;
|
|
D3DSurface* pTargSurf = m_pDeviceRTV;
|
|
const bool bUseMultisampledRTV = ((m_nFlags & FT_USAGE_MSAA) && m_bUseMultisampledRTV) != 0;
|
|
if (bUseMultisampledRTV)
|
|
{
|
|
pTargSurf = m_pDeviceRTVMS;
|
|
}
|
|
|
|
if (!pTargSurf)
|
|
{
|
|
int nMipLevel = 0;
|
|
int nSlice = 0;
|
|
int nSliceCount = -1;
|
|
|
|
if (m_eTT == eTT_Cube)
|
|
{
|
|
nMipLevel = (m_nFlags & FT_FORCE_MIPS) ? min((int)(m_nMips - 1), nLevel) : 0;
|
|
nSlice = nCMSide;
|
|
nSliceCount = 1;
|
|
}
|
|
pTargSurf = (D3DSurface*) CreateDeviceResourceView(SResourceView::RenderTargetView(m_eTFDst, nSlice, nSliceCount, nMipLevel, bUseMultisampledRTV));
|
|
|
|
if (bUseMultisampledRTV)
|
|
{
|
|
m_pDeviceRTVMS = pTargSurf;
|
|
}
|
|
else
|
|
{
|
|
m_pDeviceRTV = pTargSurf;
|
|
}
|
|
}
|
|
assert(hr == S_OK);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
pTargSurf = NULL;
|
|
}
|
|
|
|
return pTargSurf;
|
|
}
|
|
|
|
|
|
void CTexture::Readback(AZ::u32 subresourceIndex, StagingHook callback)
|
|
{
|
|
if (m_pDevTexture)
|
|
{
|
|
m_pDevTexture->DownloadToStagingResource(subresourceIndex, callback);
|
|
}
|
|
}
|
|
|
|
//===============================================================================
|
|
|
|
bool CTexture::IsDeviceFormatTypeless(D3DFormat nFormat)
|
|
{
|
|
switch (nFormat)
|
|
{
|
|
//128 bits
|
|
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
|
|
case DXGI_FORMAT_R32G32B32_TYPELESS:
|
|
|
|
//64 bits
|
|
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
|
|
case DXGI_FORMAT_R32G32_TYPELESS:
|
|
case DXGI_FORMAT_R32G8X24_TYPELESS:
|
|
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
|
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
|
|
|
|
//32 bits
|
|
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
|
|
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
|
|
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
|
|
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
|
|
case DXGI_FORMAT_R16G16_TYPELESS:
|
|
case DXGI_FORMAT_R32_TYPELESS:
|
|
case DXGI_FORMAT_R24G8_TYPELESS:
|
|
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
|
|
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
|
|
|
|
//16 bits
|
|
case DXGI_FORMAT_R8G8_TYPELESS:
|
|
case DXGI_FORMAT_R16_TYPELESS:
|
|
|
|
//8 bits
|
|
case DXGI_FORMAT_R8_TYPELESS:
|
|
|
|
//block formats
|
|
case DXGI_FORMAT_BC1_TYPELESS:
|
|
case DXGI_FORMAT_BC2_TYPELESS:
|
|
case DXGI_FORMAT_BC3_TYPELESS:
|
|
case DXGI_FORMAT_BC4_TYPELESS:
|
|
case DXGI_FORMAT_BC5_TYPELESS:
|
|
|
|
#if defined(OPENGL) || defined(CRY_USE_METAL)
|
|
case DXGI_FORMAT_ETC2_TYPELESS:
|
|
case DXGI_FORMAT_ETC2A_TYPELESS:
|
|
case DXGI_FORMAT_EAC_R11_TYPELESS:
|
|
case DXGI_FORMAT_EAC_RG11_TYPELESS:
|
|
#endif
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_1
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
|
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#else
|
|
case DXGI_FORMAT_BC6H_TYPELESS:
|
|
#endif
|
|
case DXGI_FORMAT_BC7_TYPELESS:
|
|
|
|
#ifdef CRY_USE_METAL
|
|
case DXGI_FORMAT_PVRTC2_TYPELESS:
|
|
case DXGI_FORMAT_PVRTC4_TYPELESS:
|
|
#endif
|
|
#if defined(ANDROID) || defined(CRY_USE_METAL)
|
|
case DXGI_FORMAT_ASTC_4x4_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_5x4_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_5x5_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_6x5_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_6x6_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_8x5_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_8x6_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_8x8_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_10x5_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_10x6_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_10x8_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_10x10_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_12x10_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_12x12_TYPELESS:
|
|
#endif
|
|
return true;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CTexture::IsDeviceFormatSRGBReadable(D3DFormat nFormat)
|
|
{
|
|
switch (nFormat)
|
|
{
|
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
|
return true;
|
|
|
|
case DXGI_FORMAT_BC1_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_BC2_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_BC3_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_BC7_UNORM:
|
|
return true;
|
|
|
|
#if defined(OPENGL) || defined(CRY_USE_METAL)
|
|
case DXGI_FORMAT_ETC2_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ETC2A_UNORM:
|
|
return true;
|
|
#endif //defined(OPENGL)
|
|
|
|
#ifdef CRY_USE_METAL
|
|
case DXGI_FORMAT_PVRTC2_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_PVRTC4_UNORM:
|
|
return true;
|
|
#endif
|
|
#if defined(ANDROID) || defined(CRY_USE_METAL)
|
|
case DXGI_FORMAT_ASTC_4x4_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_5x4_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_5x5_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_6x5_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_6x6_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_8x5_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_8x6_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_8x8_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_10x5_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_10x6_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_10x8_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_10x10_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_12x10_UNORM:
|
|
return true;
|
|
case DXGI_FORMAT_ASTC_12x12_UNORM:
|
|
return true;
|
|
#endif
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// this function is valid for FT_USAGE_DEPTHSTENCIL textures only
|
|
D3DFormat CTexture::DeviceFormatFromTexFormat(ETEX_Format eTF)
|
|
{
|
|
switch (eTF)
|
|
{
|
|
case eTF_R8G8B8A8:
|
|
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
case eTF_R8G8B8A8S:
|
|
return DXGI_FORMAT_R8G8B8A8_SNORM;
|
|
|
|
case eTF_A8:
|
|
return DXGI_FORMAT_A8_UNORM;
|
|
case eTF_R8:
|
|
return DXGI_FORMAT_R8_UNORM;
|
|
case eTF_R8S:
|
|
return DXGI_FORMAT_R8_SNORM;
|
|
case eTF_R16:
|
|
return DXGI_FORMAT_R16_UNORM;
|
|
case eTF_R16U:
|
|
return DXGI_FORMAT_R16_UINT;
|
|
case eTF_R16G16U:
|
|
return DXGI_FORMAT_R16G16_UINT;
|
|
case eTF_R10G10B10A2UI:
|
|
return DXGI_FORMAT_R10G10B10A2_UINT;
|
|
case eTF_R16F:
|
|
return DXGI_FORMAT_R16_FLOAT;
|
|
case eTF_R32F:
|
|
return DXGI_FORMAT_R32_FLOAT;
|
|
case eTF_R8G8:
|
|
return DXGI_FORMAT_R8G8_UNORM;
|
|
case eTF_R8G8S:
|
|
return DXGI_FORMAT_R8G8_SNORM;
|
|
case eTF_R16G16:
|
|
return DXGI_FORMAT_R16G16_UNORM;
|
|
case eTF_R16G16S:
|
|
return DXGI_FORMAT_R16G16_SNORM;
|
|
case eTF_R16G16F:
|
|
return DXGI_FORMAT_R16G16_FLOAT;
|
|
case eTF_R11G11B10F:
|
|
return DXGI_FORMAT_R11G11B10_FLOAT;
|
|
case eTF_R10G10B10A2:
|
|
return DXGI_FORMAT_R10G10B10A2_UNORM;
|
|
case eTF_R16G16B16A16:
|
|
return DXGI_FORMAT_R16G16B16A16_UNORM;
|
|
case eTF_R16G16B16A16S:
|
|
return DXGI_FORMAT_R16G16B16A16_SNORM;
|
|
case eTF_R16G16B16A16F:
|
|
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
|
case eTF_R32G32B32A32F:
|
|
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
|
|
|
case eTF_BC1:
|
|
return DXGI_FORMAT_BC1_UNORM;
|
|
case eTF_BC2:
|
|
return DXGI_FORMAT_BC2_UNORM;
|
|
case eTF_BC3:
|
|
return DXGI_FORMAT_BC3_UNORM;
|
|
case eTF_BC4U:
|
|
return DXGI_FORMAT_BC4_UNORM;
|
|
case eTF_BC4S:
|
|
return DXGI_FORMAT_BC4_SNORM;
|
|
case eTF_BC5U:
|
|
return DXGI_FORMAT_BC5_UNORM;
|
|
case eTF_BC5S:
|
|
return DXGI_FORMAT_BC5_SNORM;
|
|
case eTF_BC6UH:
|
|
return DXGI_FORMAT_BC6H_UF16;
|
|
case eTF_BC6SH:
|
|
return DXGI_FORMAT_BC6H_SF16;
|
|
case eTF_BC7:
|
|
return DXGI_FORMAT_BC7_UNORM;
|
|
case eTF_R9G9B9E5:
|
|
return DXGI_FORMAT_R9G9B9E5_SHAREDEXP;
|
|
|
|
// hardware depth buffers
|
|
case eTF_D16:
|
|
return DXGI_FORMAT_D16_UNORM;
|
|
case eTF_D24S8:
|
|
return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
|
case eTF_D32F:
|
|
return DXGI_FORMAT_D32_FLOAT;
|
|
case eTF_D32FS8:
|
|
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
|
|
|
// only available as hardware format under DX11.1 with DXGI 1.2
|
|
case eTF_B5G6R5:
|
|
return DXGI_FORMAT_B5G6R5_UNORM;
|
|
case eTF_B5G5R5:
|
|
return DXGI_FORMAT_B5G5R5A1_UNORM;
|
|
// case eTF_B4G4R4A4: return DXGI_FORMAT_B4G4R4A4_UNORM;
|
|
case eTF_B4G4R4A4:
|
|
return DXGI_FORMAT_UNKNOWN;
|
|
|
|
#if defined(OPENGL) || defined(CRY_USE_METAL)
|
|
// only available as hardware format under OpenGL
|
|
case eTF_EAC_R11:
|
|
return DXGI_FORMAT_EAC_R11_UNORM;
|
|
case eTF_EAC_RG11:
|
|
return DXGI_FORMAT_EAC_RG11_UNORM;
|
|
case eTF_ETC2:
|
|
return DXGI_FORMAT_ETC2_UNORM;
|
|
case eTF_ETC2A:
|
|
return DXGI_FORMAT_ETC2A_UNORM;
|
|
#endif //defined(OPENGL)
|
|
#ifdef CRY_USE_METAL
|
|
case eTF_PVRTC2:
|
|
return DXGI_FORMAT_PVRTC2_UNORM;
|
|
case eTF_PVRTC4:
|
|
return DXGI_FORMAT_PVRTC4_UNORM;
|
|
#endif
|
|
#if defined(ANDROID) || defined(CRY_USE_METAL)
|
|
case eTF_ASTC_4x4:
|
|
return DXGI_FORMAT_ASTC_4x4_UNORM;
|
|
case eTF_ASTC_5x4:
|
|
return DXGI_FORMAT_ASTC_5x4_UNORM;
|
|
case eTF_ASTC_5x5:
|
|
return DXGI_FORMAT_ASTC_5x5_UNORM;
|
|
case eTF_ASTC_6x5:
|
|
return DXGI_FORMAT_ASTC_6x5_UNORM;
|
|
case eTF_ASTC_6x6:
|
|
return DXGI_FORMAT_ASTC_6x6_UNORM;
|
|
case eTF_ASTC_8x5:
|
|
return DXGI_FORMAT_ASTC_8x5_UNORM;
|
|
case eTF_ASTC_8x6:
|
|
return DXGI_FORMAT_ASTC_8x6_UNORM;
|
|
case eTF_ASTC_8x8:
|
|
return DXGI_FORMAT_ASTC_8x8_UNORM;
|
|
case eTF_ASTC_10x5:
|
|
return DXGI_FORMAT_ASTC_10x5_UNORM;
|
|
case eTF_ASTC_10x6:
|
|
return DXGI_FORMAT_ASTC_10x6_UNORM;
|
|
case eTF_ASTC_10x8:
|
|
return DXGI_FORMAT_ASTC_10x8_UNORM;
|
|
case eTF_ASTC_10x10:
|
|
return DXGI_FORMAT_ASTC_10x10_UNORM;
|
|
case eTF_ASTC_12x10:
|
|
return DXGI_FORMAT_ASTC_12x10_UNORM;
|
|
case eTF_ASTC_12x12:
|
|
return DXGI_FORMAT_ASTC_12x12_UNORM;
|
|
#endif
|
|
|
|
// only available as hardware format under DX9
|
|
case eTF_A8L8:
|
|
return DXGI_FORMAT_UNKNOWN;
|
|
case eTF_L8:
|
|
return DXGI_FORMAT_UNKNOWN;
|
|
case eTF_L8V8U8:
|
|
return DXGI_FORMAT_UNKNOWN;
|
|
case eTF_B8G8R8:
|
|
return DXGI_FORMAT_UNKNOWN;
|
|
case eTF_L8V8U8X8:
|
|
return DXGI_FORMAT_UNKNOWN;
|
|
case eTF_B8G8R8X8:
|
|
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
|
case eTF_B8G8R8A8:
|
|
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
|
}
|
|
|
|
return DXGI_FORMAT_UNKNOWN;
|
|
}
|
|
|
|
D3DFormat CTexture::GetD3DLinFormat(D3DFormat nFormat)
|
|
{
|
|
return nFormat;
|
|
}
|
|
|
|
D3DFormat CTexture::ConvertToSRGBFmt(D3DFormat fmt)
|
|
{
|
|
switch (fmt)
|
|
{
|
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
|
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
|
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
|
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
|
|
|
case DXGI_FORMAT_BC1_UNORM:
|
|
return DXGI_FORMAT_BC1_UNORM_SRGB;
|
|
case DXGI_FORMAT_BC2_UNORM:
|
|
return DXGI_FORMAT_BC2_UNORM_SRGB;
|
|
case DXGI_FORMAT_BC3_UNORM:
|
|
return DXGI_FORMAT_BC3_UNORM_SRGB;
|
|
case DXGI_FORMAT_BC7_UNORM:
|
|
return DXGI_FORMAT_BC7_UNORM_SRGB;
|
|
|
|
#if defined(OPENGL) || defined(CRY_USE_METAL)
|
|
case DXGI_FORMAT_ETC2_UNORM:
|
|
return DXGI_FORMAT_ETC2_UNORM_SRGB;
|
|
case DXGI_FORMAT_ETC2A_UNORM:
|
|
return DXGI_FORMAT_ETC2A_UNORM_SRGB;
|
|
case DXGI_FORMAT_EAC_RG11_UNORM:
|
|
return DXGI_FORMAT_EAC_RG11_UNORM;
|
|
#endif //defined(OPENGL)
|
|
|
|
#ifdef CRY_USE_METAL
|
|
case DXGI_FORMAT_PVRTC2_UNORM:
|
|
return DXGI_FORMAT_PVRTC2_UNORM_SRGB;
|
|
case DXGI_FORMAT_PVRTC4_UNORM:
|
|
return DXGI_FORMAT_PVRTC4_UNORM_SRGB;
|
|
#endif
|
|
#if defined(ANDROID) || defined(CRY_USE_METAL)
|
|
case DXGI_FORMAT_ASTC_4x4_UNORM:
|
|
return DXGI_FORMAT_ASTC_4x4_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_5x4_UNORM:
|
|
return DXGI_FORMAT_ASTC_5x4_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_5x5_UNORM:
|
|
return DXGI_FORMAT_ASTC_5x5_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_6x5_UNORM:
|
|
return DXGI_FORMAT_ASTC_6x5_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_6x6_UNORM:
|
|
return DXGI_FORMAT_ASTC_6x6_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_8x5_UNORM:
|
|
return DXGI_FORMAT_ASTC_8x5_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_8x6_UNORM:
|
|
return DXGI_FORMAT_ASTC_8x6_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_8x8_UNORM:
|
|
return DXGI_FORMAT_ASTC_8x8_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_10x5_UNORM:
|
|
return DXGI_FORMAT_ASTC_10x5_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_10x6_UNORM:
|
|
return DXGI_FORMAT_ASTC_10x6_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_10x8_UNORM:
|
|
return DXGI_FORMAT_ASTC_10x8_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_10x10_UNORM:
|
|
return DXGI_FORMAT_ASTC_10x10_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_12x10_UNORM:
|
|
return DXGI_FORMAT_ASTC_12x10_UNORM_SRGB;
|
|
case DXGI_FORMAT_ASTC_12x12_UNORM:
|
|
return DXGI_FORMAT_ASTC_12x12_UNORM_SRGB;
|
|
case DXGI_FORMAT_R8_UNORM:
|
|
return DXGI_FORMAT_R8_UNORM;
|
|
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
|
|
return DXGI_FORMAT_R9G9B9E5_SHAREDEXP;
|
|
#endif
|
|
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
|
return DXGI_FORMAT_R10G10B10A2_UNORM;
|
|
// AntonK: we don't need sRGB space for fp formats, because there is enough precision
|
|
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
|
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
|
case DXGI_FORMAT_R11G11B10_FLOAT:
|
|
return DXGI_FORMAT_R11G11B10_FLOAT;
|
|
// There is no SRGB format for BC4
|
|
case DXGI_FORMAT_BC4_SNORM:
|
|
return DXGI_FORMAT_BC4_SNORM;
|
|
case DXGI_FORMAT_BC4_UNORM:
|
|
return DXGI_FORMAT_BC4_UNORM;
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
return fmt;
|
|
}
|
|
|
|
D3DFormat CTexture::ConvertToSignedFmt(D3DFormat fmt)
|
|
{
|
|
switch (fmt)
|
|
{
|
|
case DXGI_FORMAT_R8_UNORM:
|
|
return DXGI_FORMAT_R8_SNORM;
|
|
case DXGI_FORMAT_R8G8_UNORM:
|
|
return DXGI_FORMAT_R8G8_SNORM;
|
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
|
return DXGI_FORMAT_R8G8B8A8_SNORM;
|
|
case DXGI_FORMAT_R16_UNORM:
|
|
return DXGI_FORMAT_R16_SNORM;
|
|
case DXGI_FORMAT_R16G16_UNORM:
|
|
return DXGI_FORMAT_R16G16_SNORM;
|
|
case DXGI_FORMAT_R16G16B16A16_UNORM:
|
|
return DXGI_FORMAT_R16G16B16A16_SNORM;
|
|
case DXGI_FORMAT_BC4_UNORM:
|
|
return DXGI_FORMAT_BC4_SNORM;
|
|
case DXGI_FORMAT_BC5_UNORM:
|
|
return DXGI_FORMAT_BC5_SNORM;
|
|
case DXGI_FORMAT_BC6H_UF16:
|
|
return DXGI_FORMAT_BC6H_SF16;
|
|
|
|
case DXGI_FORMAT_R32G32B32A32_UINT:
|
|
return DXGI_FORMAT_R32G32B32A32_SINT;
|
|
case DXGI_FORMAT_R32G32B32_UINT:
|
|
return DXGI_FORMAT_R32G32B32_SINT;
|
|
case DXGI_FORMAT_R16G16B16A16_UINT:
|
|
return DXGI_FORMAT_R16G16B16A16_SINT;
|
|
case DXGI_FORMAT_R32G32_UINT:
|
|
return DXGI_FORMAT_R32G32_SINT;
|
|
case DXGI_FORMAT_R8G8B8A8_UINT:
|
|
return DXGI_FORMAT_R8G8B8A8_SINT;
|
|
case DXGI_FORMAT_R16G16_UINT:
|
|
return DXGI_FORMAT_R16G16_SINT;
|
|
case DXGI_FORMAT_R32_UINT:
|
|
return DXGI_FORMAT_R32_SINT;
|
|
case DXGI_FORMAT_R8G8_UINT:
|
|
return DXGI_FORMAT_R8G8_SINT;
|
|
case DXGI_FORMAT_R16_UINT:
|
|
return DXGI_FORMAT_R16_SINT;
|
|
case DXGI_FORMAT_R8_UINT:
|
|
return DXGI_FORMAT_R8_SINT;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
return fmt;
|
|
}
|
|
|
|
ETEX_Format CTexture::TexFormatFromDeviceFormat(D3DFormat nFormat)
|
|
{
|
|
switch (nFormat)
|
|
{
|
|
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
|
|
return eTF_R8G8B8A8;
|
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
|
return eTF_R8G8B8A8;
|
|
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
|
return eTF_R8G8B8A8;
|
|
case DXGI_FORMAT_R8G8B8A8_SNORM:
|
|
return eTF_R8G8B8A8S;
|
|
|
|
case DXGI_FORMAT_A8_UNORM:
|
|
return eTF_A8;
|
|
case DXGI_FORMAT_R8_TYPELESS:
|
|
case DXGI_FORMAT_R8_UNORM:
|
|
return eTF_R8;
|
|
case DXGI_FORMAT_R8_SNORM:
|
|
return eTF_R8S;
|
|
case DXGI_FORMAT_R16_UNORM:
|
|
return eTF_R16;
|
|
case DXGI_FORMAT_R16_UINT:
|
|
return eTF_R16U;
|
|
case DXGI_FORMAT_R16G16_UINT:
|
|
return eTF_R16G16U;
|
|
case DXGI_FORMAT_R10G10B10A2_UINT:
|
|
return eTF_R10G10B10A2UI;
|
|
case DXGI_FORMAT_R16_FLOAT:
|
|
return eTF_R16F;
|
|
case DXGI_FORMAT_R16_TYPELESS:
|
|
return eTF_R16F;
|
|
case DXGI_FORMAT_R32_FLOAT:
|
|
return eTF_R32F;
|
|
case DXGI_FORMAT_R32_TYPELESS:
|
|
return eTF_R32F;
|
|
case DXGI_FORMAT_R8G8_UNORM:
|
|
return eTF_R8G8;
|
|
case DXGI_FORMAT_R8G8_SNORM:
|
|
return eTF_R8G8S;
|
|
case DXGI_FORMAT_R16G16_UNORM:
|
|
return eTF_R16G16;
|
|
case DXGI_FORMAT_R16G16_SNORM:
|
|
return eTF_R16G16S;
|
|
case DXGI_FORMAT_R16G16_FLOAT:
|
|
return eTF_R16G16F;
|
|
case DXGI_FORMAT_R11G11B10_FLOAT:
|
|
return eTF_R11G11B10F;
|
|
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
|
return eTF_R10G10B10A2;
|
|
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
|
|
return eTF_R10G10B10A2;
|
|
case DXGI_FORMAT_R16G16B16A16_UNORM:
|
|
return eTF_R16G16B16A16;
|
|
case DXGI_FORMAT_R16G16B16A16_SNORM:
|
|
return eTF_R16G16B16A16S;
|
|
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
|
return eTF_R16G16B16A16F;
|
|
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
|
|
return eTF_R16G16B16A16F;
|
|
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
|
return eTF_R32G32B32A32F;
|
|
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
|
|
return eTF_R32G32B32A32F;
|
|
|
|
case DXGI_FORMAT_BC1_TYPELESS:
|
|
return eTF_BC1;
|
|
case DXGI_FORMAT_BC1_UNORM:
|
|
return eTF_BC1;
|
|
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
|
return eTF_BC1;
|
|
case DXGI_FORMAT_BC2_TYPELESS:
|
|
return eTF_BC2;
|
|
case DXGI_FORMAT_BC2_UNORM:
|
|
return eTF_BC2;
|
|
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
|
return eTF_BC2;
|
|
case DXGI_FORMAT_BC3_TYPELESS:
|
|
return eTF_BC3;
|
|
case DXGI_FORMAT_BC3_UNORM:
|
|
return eTF_BC3;
|
|
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
|
return eTF_BC3;
|
|
case DXGI_FORMAT_BC4_TYPELESS:
|
|
return eTF_BC4U;
|
|
case DXGI_FORMAT_BC4_UNORM:
|
|
return eTF_BC4U;
|
|
case DXGI_FORMAT_BC4_SNORM:
|
|
return eTF_BC4S;
|
|
case DXGI_FORMAT_BC5_TYPELESS:
|
|
return eTF_BC5U;
|
|
case DXGI_FORMAT_BC5_UNORM:
|
|
return eTF_BC5U;
|
|
case DXGI_FORMAT_BC5_SNORM:
|
|
return eTF_BC5S;
|
|
case DXGI_FORMAT_BC6H_UF16:
|
|
return eTF_BC6UH;
|
|
case DXGI_FORMAT_BC6H_SF16:
|
|
return eTF_BC6SH;
|
|
case DXGI_FORMAT_BC7_TYPELESS:
|
|
return eTF_BC7;
|
|
case DXGI_FORMAT_BC7_UNORM:
|
|
return eTF_BC7;
|
|
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
|
return eTF_BC7;
|
|
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
|
|
return eTF_R9G9B9E5;
|
|
|
|
// hardware depth buffers
|
|
case DXGI_FORMAT_D16_UNORM:
|
|
return eTF_D16;
|
|
case DXGI_FORMAT_D24_UNORM_S8_UINT:
|
|
return eTF_D24S8;
|
|
case DXGI_FORMAT_D32_FLOAT:
|
|
return eTF_D32F;
|
|
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
|
return eTF_D32FS8;
|
|
|
|
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
|
|
return eTF_D24S8;
|
|
case DXGI_FORMAT_R24G8_TYPELESS:
|
|
return eTF_D24S8;
|
|
case DXGI_FORMAT_R32G8X24_TYPELESS:
|
|
return eTF_D32FS8;
|
|
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
|
return eTF_D32FS8;
|
|
|
|
// only available as hardware format under DX11.1 with DXGI 1.2
|
|
case DXGI_FORMAT_B5G6R5_UNORM:
|
|
return eTF_B5G6R5;
|
|
case DXGI_FORMAT_B5G5R5A1_UNORM:
|
|
return eTF_B5G5R5;
|
|
// case DXGI_FORMAT_B4G4R4A4_UNORM: return eTF_B4G4R4A4;
|
|
|
|
#if defined(OPENGL) || defined(CRY_USE_METAL)
|
|
// only available as hardware format under OpenGL
|
|
case DXGI_FORMAT_EAC_R11_UNORM:
|
|
case DXGI_FORMAT_EAC_R11_TYPELESS:
|
|
return eTF_EAC_R11;
|
|
case DXGI_FORMAT_EAC_RG11_UNORM:
|
|
case DXGI_FORMAT_EAC_RG11_TYPELESS:
|
|
return eTF_EAC_RG11;
|
|
case DXGI_FORMAT_ETC2_UNORM:
|
|
case DXGI_FORMAT_ETC2_UNORM_SRGB:
|
|
case DXGI_FORMAT_ETC2_TYPELESS:
|
|
return eTF_ETC2;
|
|
case DXGI_FORMAT_ETC2A_UNORM:
|
|
case DXGI_FORMAT_ETC2A_UNORM_SRGB:
|
|
case DXGI_FORMAT_ETC2A_TYPELESS:
|
|
return eTF_ETC2A;
|
|
#endif //defined(OPENGL)
|
|
|
|
#ifdef CRY_USE_METAL
|
|
case DXGI_FORMAT_PVRTC2_TYPELESS:
|
|
case DXGI_FORMAT_PVRTC2_UNORM:
|
|
case DXGI_FORMAT_PVRTC2_UNORM_SRGB:
|
|
return eTF_PVRTC2;
|
|
case DXGI_FORMAT_PVRTC4_TYPELESS:
|
|
case DXGI_FORMAT_PVRTC4_UNORM:
|
|
case DXGI_FORMAT_PVRTC4_UNORM_SRGB:
|
|
return eTF_PVRTC4;
|
|
#endif
|
|
#if defined(ANDROID) || defined(CRY_USE_METAL)
|
|
case DXGI_FORMAT_ASTC_4x4_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_4x4_UNORM:
|
|
case DXGI_FORMAT_ASTC_4x4_UNORM_SRGB:
|
|
return eTF_ASTC_4x4;
|
|
case DXGI_FORMAT_ASTC_5x4_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_5x4_UNORM:
|
|
case DXGI_FORMAT_ASTC_5x4_UNORM_SRGB:
|
|
return eTF_ASTC_5x4;
|
|
case DXGI_FORMAT_ASTC_5x5_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_5x5_UNORM:
|
|
case DXGI_FORMAT_ASTC_5x5_UNORM_SRGB:
|
|
return eTF_ASTC_5x5;
|
|
case DXGI_FORMAT_ASTC_6x5_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_6x5_UNORM:
|
|
case DXGI_FORMAT_ASTC_6x5_UNORM_SRGB:
|
|
return eTF_ASTC_6x5;
|
|
case DXGI_FORMAT_ASTC_6x6_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_6x6_UNORM:
|
|
case DXGI_FORMAT_ASTC_6x6_UNORM_SRGB:
|
|
return eTF_ASTC_6x6;
|
|
case DXGI_FORMAT_ASTC_8x5_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_8x5_UNORM:
|
|
case DXGI_FORMAT_ASTC_8x5_UNORM_SRGB:
|
|
return eTF_ASTC_8x5;
|
|
case DXGI_FORMAT_ASTC_8x6_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_8x6_UNORM:
|
|
case DXGI_FORMAT_ASTC_8x6_UNORM_SRGB:
|
|
return eTF_ASTC_8x6;
|
|
case DXGI_FORMAT_ASTC_8x8_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_8x8_UNORM:
|
|
case DXGI_FORMAT_ASTC_8x8_UNORM_SRGB:
|
|
return eTF_ASTC_8x8;
|
|
case DXGI_FORMAT_ASTC_10x5_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_10x5_UNORM:
|
|
case DXGI_FORMAT_ASTC_10x5_UNORM_SRGB:
|
|
return eTF_ASTC_10x5;
|
|
case DXGI_FORMAT_ASTC_10x6_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_10x6_UNORM:
|
|
case DXGI_FORMAT_ASTC_10x6_UNORM_SRGB:
|
|
return eTF_ASTC_10x6;
|
|
case DXGI_FORMAT_ASTC_10x8_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_10x8_UNORM:
|
|
case DXGI_FORMAT_ASTC_10x8_UNORM_SRGB:
|
|
return eTF_ASTC_10x8;
|
|
case DXGI_FORMAT_ASTC_10x10_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_10x10_UNORM:
|
|
case DXGI_FORMAT_ASTC_10x10_UNORM_SRGB:
|
|
return eTF_ASTC_10x10;
|
|
case DXGI_FORMAT_ASTC_12x10_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_12x10_UNORM:
|
|
case DXGI_FORMAT_ASTC_12x10_UNORM_SRGB:
|
|
return eTF_ASTC_12x10;
|
|
case DXGI_FORMAT_ASTC_12x12_TYPELESS:
|
|
case DXGI_FORMAT_ASTC_12x12_UNORM:
|
|
case DXGI_FORMAT_ASTC_12x12_UNORM_SRGB:
|
|
return eTF_ASTC_12x12;
|
|
#endif
|
|
|
|
// only available as hardware format under DX9
|
|
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
|
|
return eTF_B8G8R8A8;
|
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
|
return eTF_B8G8R8A8;
|
|
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
|
return eTF_B8G8R8A8;
|
|
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
|
|
return eTF_B8G8R8X8;
|
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
|
return eTF_B8G8R8X8;
|
|
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
|
return eTF_B8G8R8X8;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
return eTF_Unknown;
|
|
}
|
|
|
|
// this function is valid for FT_USAGE_DEPTHSTENCIL textures only
|
|
D3DFormat CTexture::ConvertToDepthStencilFmt(D3DFormat nFormat)
|
|
{
|
|
switch (nFormat)
|
|
{
|
|
case DXGI_FORMAT_R16_TYPELESS:
|
|
return DXGI_FORMAT_D16_UNORM;
|
|
case DXGI_FORMAT_R24G8_TYPELESS:
|
|
return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
|
case DXGI_FORMAT_R32_TYPELESS:
|
|
return DXGI_FORMAT_D32_FLOAT;
|
|
case DXGI_FORMAT_R32G8X24_TYPELESS:
|
|
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
|
|
|
// Don't assert if they pass in a valid depth format...
|
|
case DXGI_FORMAT_D16_UNORM:
|
|
case DXGI_FORMAT_D24_UNORM_S8_UINT:
|
|
case DXGI_FORMAT_D32_FLOAT:
|
|
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
|
return nFormat;
|
|
|
|
default:
|
|
assert(nFormat == DXGI_FORMAT_D16_UNORM || nFormat == DXGI_FORMAT_D24_UNORM_S8_UINT || nFormat == DXGI_FORMAT_D32_FLOAT || nFormat == DXGI_FORMAT_D32_FLOAT_S8X24_UINT);
|
|
}
|
|
|
|
return nFormat;
|
|
}
|
|
|
|
D3DFormat CTexture::ConvertToStencilFmt(D3DFormat nFormat)
|
|
{
|
|
switch (nFormat)
|
|
{
|
|
case DXGI_FORMAT_R32G8X24_TYPELESS:
|
|
return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
|
|
case DXGI_FORMAT_R24G8_TYPELESS:
|
|
return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
|
|
|
|
default:
|
|
assert(nFormat == DXGI_FORMAT_X32_TYPELESS_G8X24_UINT || nFormat == DXGI_FORMAT_X24_TYPELESS_G8_UINT);
|
|
}
|
|
|
|
return nFormat;
|
|
}
|
|
|
|
D3DFormat CTexture::ConvertToShaderResourceFmt(D3DFormat nFormat)
|
|
{
|
|
//handle special cases
|
|
switch (nFormat)
|
|
{
|
|
case DXGI_FORMAT_R16_TYPELESS:
|
|
return DXGI_FORMAT_R16_UNORM;
|
|
case DXGI_FORMAT_R24G8_TYPELESS:
|
|
return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
|
case DXGI_FORMAT_R32_TYPELESS:
|
|
return DXGI_FORMAT_R32_FLOAT;
|
|
case DXGI_FORMAT_R32G8X24_TYPELESS:
|
|
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
|
// case DXGI_FORMAT_R32G32_TYPELESS: return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
|
|
|
default:
|
|
break; //pass through
|
|
}
|
|
|
|
return nFormat;
|
|
}
|
|
|
|
D3DFormat CTexture::ConvertToTypelessFmt(D3DFormat fmt)
|
|
{
|
|
switch (fmt)
|
|
{
|
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
|
return DXGI_FORMAT_R8G8B8A8_TYPELESS;
|
|
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
|
return DXGI_FORMAT_R8G8B8A8_TYPELESS;
|
|
case DXGI_FORMAT_R8G8B8A8_SNORM:
|
|
return DXGI_FORMAT_R8G8B8A8_TYPELESS;
|
|
case DXGI_FORMAT_R8G8B8A8_UINT:
|
|
return DXGI_FORMAT_R8G8B8A8_TYPELESS;
|
|
case DXGI_FORMAT_R8G8B8A8_SINT:
|
|
return DXGI_FORMAT_R8G8B8A8_TYPELESS;
|
|
|
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
|
return DXGI_FORMAT_B8G8R8A8_TYPELESS;
|
|
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
|
return DXGI_FORMAT_B8G8R8A8_TYPELESS;
|
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
|
return DXGI_FORMAT_B8G8R8X8_TYPELESS;
|
|
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
|
return DXGI_FORMAT_B8G8R8X8_TYPELESS;
|
|
|
|
case DXGI_FORMAT_R8_UNORM:
|
|
return DXGI_FORMAT_R8_TYPELESS;
|
|
case DXGI_FORMAT_R8_SNORM:
|
|
return DXGI_FORMAT_R8_TYPELESS;
|
|
case DXGI_FORMAT_R8_UINT:
|
|
return DXGI_FORMAT_R8_TYPELESS;
|
|
case DXGI_FORMAT_R8_SINT:
|
|
return DXGI_FORMAT_R8_TYPELESS;
|
|
|
|
case DXGI_FORMAT_R16_UNORM:
|
|
return DXGI_FORMAT_R16_TYPELESS;
|
|
case DXGI_FORMAT_R16_SNORM:
|
|
return DXGI_FORMAT_R16_TYPELESS;
|
|
case DXGI_FORMAT_R16_FLOAT:
|
|
return DXGI_FORMAT_R16_TYPELESS;
|
|
case DXGI_FORMAT_R16_UINT:
|
|
return DXGI_FORMAT_R16_TYPELESS;
|
|
case DXGI_FORMAT_R16_SINT:
|
|
return DXGI_FORMAT_R16_TYPELESS;
|
|
|
|
case DXGI_FORMAT_R32_FLOAT:
|
|
return DXGI_FORMAT_R32_TYPELESS;
|
|
case DXGI_FORMAT_R32_UINT:
|
|
return DXGI_FORMAT_R32_TYPELESS;
|
|
case DXGI_FORMAT_R32_SINT:
|
|
return DXGI_FORMAT_R32_TYPELESS;
|
|
|
|
case DXGI_FORMAT_R8G8_UNORM:
|
|
return DXGI_FORMAT_R8G8_TYPELESS;
|
|
case DXGI_FORMAT_R8G8_SNORM:
|
|
return DXGI_FORMAT_R8G8_TYPELESS;
|
|
case DXGI_FORMAT_R8G8_UINT:
|
|
return DXGI_FORMAT_R8G8_TYPELESS;
|
|
case DXGI_FORMAT_R8G8_SINT:
|
|
return DXGI_FORMAT_R8G8_TYPELESS;
|
|
|
|
case DXGI_FORMAT_R16G16_FLOAT:
|
|
return DXGI_FORMAT_R16G16_TYPELESS;
|
|
case DXGI_FORMAT_R16G16_UNORM:
|
|
return DXGI_FORMAT_R16G16_TYPELESS;
|
|
case DXGI_FORMAT_R16G16_SNORM:
|
|
return DXGI_FORMAT_R16G16_TYPELESS;
|
|
case DXGI_FORMAT_R16G16_UINT:
|
|
return DXGI_FORMAT_R16G16_TYPELESS;
|
|
case DXGI_FORMAT_R16G16_SINT:
|
|
return DXGI_FORMAT_R16G16_TYPELESS;
|
|
|
|
case DXGI_FORMAT_R32G32_FLOAT:
|
|
return DXGI_FORMAT_R32G32_TYPELESS;
|
|
case DXGI_FORMAT_R32G32_UINT:
|
|
return DXGI_FORMAT_R32G32_TYPELESS;
|
|
case DXGI_FORMAT_R32G32_SINT:
|
|
return DXGI_FORMAT_R32G32_TYPELESS;
|
|
|
|
case DXGI_FORMAT_R32G32B32_FLOAT:
|
|
return DXGI_FORMAT_R32G32B32_TYPELESS;
|
|
case DXGI_FORMAT_R32G32B32_UINT:
|
|
return DXGI_FORMAT_R32G32B32_TYPELESS;
|
|
case DXGI_FORMAT_R32G32B32_SINT:
|
|
return DXGI_FORMAT_R32G32B32_TYPELESS;
|
|
|
|
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
|
return DXGI_FORMAT_R10G10B10A2_TYPELESS;
|
|
case DXGI_FORMAT_R10G10B10A2_UINT:
|
|
return DXGI_FORMAT_R10G10B10A2_TYPELESS;
|
|
|
|
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
|
return DXGI_FORMAT_R16G16B16A16_TYPELESS;
|
|
case DXGI_FORMAT_R16G16B16A16_UNORM:
|
|
return DXGI_FORMAT_R16G16B16A16_TYPELESS;
|
|
case DXGI_FORMAT_R16G16B16A16_SNORM:
|
|
return DXGI_FORMAT_R16G16B16A16_TYPELESS;
|
|
case DXGI_FORMAT_R16G16B16A16_UINT:
|
|
return DXGI_FORMAT_R16G16B16A16_TYPELESS;
|
|
case DXGI_FORMAT_R16G16B16A16_SINT:
|
|
return DXGI_FORMAT_R16G16B16A16_TYPELESS;
|
|
|
|
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
|
return DXGI_FORMAT_R32G32B32A32_TYPELESS;
|
|
case DXGI_FORMAT_R32G32B32A32_UINT:
|
|
return DXGI_FORMAT_R32G32B32A32_TYPELESS;
|
|
case DXGI_FORMAT_R32G32B32A32_SINT:
|
|
return DXGI_FORMAT_R32G32B32A32_TYPELESS;
|
|
|
|
case DXGI_FORMAT_BC1_UNORM:
|
|
return DXGI_FORMAT_BC1_TYPELESS;
|
|
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
|
return DXGI_FORMAT_BC1_TYPELESS;
|
|
|
|
case DXGI_FORMAT_BC2_UNORM:
|
|
return DXGI_FORMAT_BC2_TYPELESS;
|
|
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
|
return DXGI_FORMAT_BC2_TYPELESS;
|
|
|
|
case DXGI_FORMAT_BC3_UNORM:
|
|
return DXGI_FORMAT_BC3_TYPELESS;
|
|
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
|
return DXGI_FORMAT_BC3_TYPELESS;
|
|
|
|
case DXGI_FORMAT_BC4_UNORM:
|
|
return DXGI_FORMAT_BC4_TYPELESS;
|
|
case DXGI_FORMAT_BC4_SNORM:
|
|
return DXGI_FORMAT_BC4_TYPELESS;
|
|
|
|
case DXGI_FORMAT_BC5_UNORM:
|
|
return DXGI_FORMAT_BC5_TYPELESS;
|
|
case DXGI_FORMAT_BC5_SNORM:
|
|
return DXGI_FORMAT_BC5_TYPELESS;
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_2
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
|
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#else
|
|
case DXGI_FORMAT_BC6H_UF16:
|
|
return DXGI_FORMAT_BC6H_TYPELESS;
|
|
case DXGI_FORMAT_BC6H_SF16:
|
|
return DXGI_FORMAT_BC6H_TYPELESS;
|
|
#endif
|
|
case DXGI_FORMAT_BC7_UNORM:
|
|
return DXGI_FORMAT_BC7_TYPELESS;
|
|
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
|
return DXGI_FORMAT_BC7_TYPELESS;
|
|
|
|
#if defined(OPENGL) && !defined(CRY_USE_METAL)
|
|
case DXGI_FORMAT_EAC_R11_UNORM:
|
|
return DXGI_FORMAT_EAC_R11_TYPELESS;
|
|
case DXGI_FORMAT_EAC_R11_SNORM:
|
|
return DXGI_FORMAT_EAC_R11_TYPELESS;
|
|
case DXGI_FORMAT_EAC_RG11_UNORM:
|
|
return DXGI_FORMAT_EAC_RG11_TYPELESS;
|
|
case DXGI_FORMAT_EAC_RG11_SNORM:
|
|
return DXGI_FORMAT_EAC_RG11_TYPELESS;
|
|
case DXGI_FORMAT_ETC2_UNORM:
|
|
return DXGI_FORMAT_ETC2_TYPELESS;
|
|
case DXGI_FORMAT_ETC2_UNORM_SRGB:
|
|
return DXGI_FORMAT_ETC2_TYPELESS;
|
|
case DXGI_FORMAT_ETC2A_UNORM:
|
|
return DXGI_FORMAT_ETC2A_TYPELESS;
|
|
case DXGI_FORMAT_ETC2A_UNORM_SRGB:
|
|
return DXGI_FORMAT_ETC2A_TYPELESS;
|
|
#endif //defined(OPENGL)
|
|
|
|
case DXGI_FORMAT_D16_UNORM:
|
|
return DXGI_FORMAT_R16_TYPELESS;
|
|
case DXGI_FORMAT_D24_UNORM_S8_UINT:
|
|
return DXGI_FORMAT_R24G8_TYPELESS;
|
|
case DXGI_FORMAT_D32_FLOAT:
|
|
return DXGI_FORMAT_R32_TYPELESS;
|
|
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
|
return DXGI_FORMAT_R32G8X24_TYPELESS;
|
|
|
|
// todo: add missing formats if they found required
|
|
|
|
#ifdef CRY_USE_METAL
|
|
case DXGI_FORMAT_PVRTC2_UNORM:
|
|
case DXGI_FORMAT_PVRTC2_UNORM_SRGB:
|
|
return DXGI_FORMAT_PVRTC2_TYPELESS;
|
|
|
|
case DXGI_FORMAT_PVRTC4_UNORM:
|
|
case DXGI_FORMAT_PVRTC4_UNORM_SRGB:
|
|
return DXGI_FORMAT_PVRTC4_TYPELESS;
|
|
#endif
|
|
#if defined(ANDROID) || defined(CRY_USE_METAL)
|
|
case DXGI_FORMAT_ASTC_4x4_UNORM:
|
|
case DXGI_FORMAT_ASTC_4x4_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_4x4_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_5x4_UNORM:
|
|
case DXGI_FORMAT_ASTC_5x4_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_5x4_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_5x5_UNORM:
|
|
case DXGI_FORMAT_ASTC_5x5_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_5x5_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_6x5_UNORM:
|
|
case DXGI_FORMAT_ASTC_6x5_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_6x5_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_6x6_UNORM:
|
|
case DXGI_FORMAT_ASTC_6x6_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_6x6_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_8x5_UNORM:
|
|
case DXGI_FORMAT_ASTC_8x5_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_8x5_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_8x6_UNORM:
|
|
case DXGI_FORMAT_ASTC_8x6_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_8x6_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_8x8_UNORM:
|
|
case DXGI_FORMAT_ASTC_8x8_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_8x8_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_10x5_UNORM:
|
|
case DXGI_FORMAT_ASTC_10x5_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_10x5_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_10x6_UNORM:
|
|
case DXGI_FORMAT_ASTC_10x6_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_10x6_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_10x8_UNORM:
|
|
case DXGI_FORMAT_ASTC_10x8_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_10x8_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_10x10_UNORM:
|
|
case DXGI_FORMAT_ASTC_10x10_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_10x10_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_12x10_UNORM:
|
|
case DXGI_FORMAT_ASTC_12x10_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_12x10_TYPELESS;
|
|
|
|
case DXGI_FORMAT_ASTC_12x12_UNORM:
|
|
case DXGI_FORMAT_ASTC_12x12_UNORM_SRGB:
|
|
return DXGI_FORMAT_ASTC_12x12_TYPELESS;
|
|
|
|
#endif
|
|
|
|
// No conversion on floating point format.
|
|
case DXGI_FORMAT_R11G11B10_FLOAT:
|
|
return DXGI_FORMAT_R11G11B10_FLOAT;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
return fmt;
|
|
}
|
|
|
|
bool CTexture::IsFormatSupported(ETEX_Format eTFDst)
|
|
{
|
|
const SPixFormatSupport* rd = &gcpRendD3D->m_hwTexFormatSupport;
|
|
|
|
int D3DFmt = DeviceFormatFromTexFormat(eTFDst);
|
|
if (!D3DFmt)
|
|
{
|
|
return false;
|
|
}
|
|
SPixFormat* pFmt;
|
|
for (pFmt = rd->m_FirstPixelFormat; pFmt; pFmt = pFmt->Next)
|
|
{
|
|
if (pFmt->DeviceFormat == D3DFmt && pFmt->IsValid())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ETEX_Format CTexture::ClosestFormatSupported(ETEX_Format eTFDst)
|
|
{
|
|
return ClosestFormatSupported(eTFDst, m_pPixelFormat);
|
|
}
|
|
|
|
ETEX_Format CTexture::ClosestFormatSupported(ETEX_Format eTFDst, const SPixFormat*& pPF)
|
|
{
|
|
const SPixFormatSupport* rd = &gcpRendD3D->m_hwTexFormatSupport;
|
|
|
|
switch (eTFDst)
|
|
{
|
|
case eTF_R8G8B8A8S:
|
|
if (rd->m_FormatR8G8B8A8S.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8G8B8A8S;
|
|
return eTF_R8G8B8A8S;
|
|
}
|
|
return eTF_Unknown;
|
|
case eTF_R8G8B8A8:
|
|
if (rd->m_FormatR8G8B8A8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8G8B8A8;
|
|
return eTF_R8G8B8A8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_B5G5R5:
|
|
if (rd->m_FormatB5G5R5.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatB5G5R5;
|
|
return eTF_B5G5R5;
|
|
}
|
|
case eTF_B5G6R5:
|
|
if (rd->m_FormatB5G6R5.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatB5G6R5;
|
|
return eTF_B5G6R5;
|
|
}
|
|
|
|
case eTF_B8G8R8X8:
|
|
if (rd->m_FormatB8G8R8X8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatB8G8R8X8;
|
|
return eTF_B8G8R8X8;
|
|
}
|
|
return eTF_Unknown;
|
|
case eTF_B4G4R4A4:
|
|
if (rd->m_FormatB4G4R4A4.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatB4G4R4A4;
|
|
return eTF_B4G4R4A4;
|
|
}
|
|
case eTF_B8G8R8A8:
|
|
if (rd->m_FormatB8G8R8A8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatB8G8R8A8;
|
|
return eTF_B8G8R8A8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_A8:
|
|
if (rd->m_FormatA8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatA8;
|
|
return eTF_A8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
|
|
case eTF_R8:
|
|
if (rd->m_FormatR8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8;
|
|
return eTF_R8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R8S:
|
|
if (rd->m_FormatR8S.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8S;
|
|
return eTF_R8S;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R16:
|
|
if (rd->m_FormatR16.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16;
|
|
return eTF_R16;
|
|
}
|
|
if (rd->m_FormatR16G16.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16;
|
|
return eTF_R16G16;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R16U:
|
|
if (rd->m_FormatR16U.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16U;
|
|
return eTF_R16U;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R16G16U:
|
|
if (rd->m_FormatR16G16U.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16U;
|
|
return eTF_R16G16U;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R10G10B10A2UI:
|
|
if (rd->m_FormatR10G10B10A2UI.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR10G10B10A2UI;
|
|
return eTF_R10G10B10A2UI;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R16F:
|
|
if (rd->m_FormatR16F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16F;
|
|
return eTF_R16F;
|
|
}
|
|
if (rd->m_FormatR16G16F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16F;
|
|
return eTF_R16G16F;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R32F:
|
|
if (rd->m_FormatR32F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR32F;
|
|
return eTF_R32F;
|
|
}
|
|
if (rd->m_FormatR16G16F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16F;
|
|
return eTF_R16G16F;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R8G8:
|
|
if (rd->m_FormatR8G8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8G8;
|
|
return eTF_R8G8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R8G8S:
|
|
if (rd->m_FormatR8G8S.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8G8S;
|
|
return eTF_R8G8S;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R16G16:
|
|
if (rd->m_FormatR16G16.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16;
|
|
return eTF_R16G16;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R16G16S:
|
|
if (rd->m_FormatR16G16S.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16S;
|
|
return eTF_R16G16S;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R16G16F:
|
|
if (rd->m_FormatR16G16F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16F;
|
|
return eTF_R16G16F;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R11G11B10F:
|
|
if (rd->m_FormatR11G11B10F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR11G11B10F;
|
|
return eTF_R11G11B10F;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R10G10B10A2:
|
|
if (rd->m_FormatR10G10B10A2.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR10G10B10A2;
|
|
return eTF_R10G10B10A2;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R16G16B16A16:
|
|
if (rd->m_FormatR16G16B16A16.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16B16A16;
|
|
return eTF_R16G16B16A16;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R16G16B16A16S:
|
|
if (rd->m_FormatR16G16B16A16S.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16B16A16S;
|
|
return eTF_R16G16B16A16S;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R16G16B16A16F:
|
|
if (rd->m_FormatR16G16B16A16F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16B16A16F;
|
|
return eTF_R16G16B16A16F;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R32G32B32A32F:
|
|
if (rd->m_FormatR32G32B32A32F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR32G32B32A32F;
|
|
return eTF_R32G32B32A32F;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_BC1:
|
|
if (rd->m_FormatBC1.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatBC1;
|
|
return eTF_BC1;
|
|
}
|
|
if (rd->m_FormatR8G8B8A8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8G8B8A8;
|
|
return eTF_R8G8B8A8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_BC2:
|
|
if (rd->m_FormatBC2.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatBC2;
|
|
return eTF_BC2;
|
|
}
|
|
if (rd->m_FormatR8G8B8A8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8G8B8A8;
|
|
return eTF_R8G8B8A8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_BC3:
|
|
if (rd->m_FormatBC3.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatBC3;
|
|
return eTF_BC3;
|
|
}
|
|
if (rd->m_FormatR8G8B8A8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8G8B8A8;
|
|
return eTF_R8G8B8A8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_BC4U:
|
|
if (rd->m_FormatBC4U.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatBC4U;
|
|
return eTF_BC4U;
|
|
}
|
|
if (rd->m_FormatR8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8;
|
|
return eTF_R8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_BC4S:
|
|
if (rd->m_FormatBC4S.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatBC4S;
|
|
return eTF_BC4S;
|
|
}
|
|
if (rd->m_FormatR8S.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8S;
|
|
return eTF_R8S;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_BC5U:
|
|
if (rd->m_FormatBC5U.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatBC5U;
|
|
return eTF_BC5U;
|
|
}
|
|
if (rd->m_FormatR8G8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8G8;
|
|
return eTF_R8G8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_BC5S:
|
|
if (rd->m_FormatBC5S.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatBC5S;
|
|
return eTF_BC5S;
|
|
}
|
|
if (rd->m_FormatR8G8S.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8G8S;
|
|
return eTF_R8G8S;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_BC6UH:
|
|
if (rd->m_FormatBC6UH.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatBC6UH;
|
|
return eTF_BC6UH;
|
|
}
|
|
if (rd->m_FormatR16F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16F;
|
|
return eTF_R16F;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_BC6SH:
|
|
if (rd->m_FormatBC6SH.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatBC6SH;
|
|
return eTF_BC6SH;
|
|
}
|
|
if (rd->m_FormatR16F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16F;
|
|
return eTF_R16F;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_BC7:
|
|
if (rd->m_FormatBC7.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatBC7;
|
|
return eTF_BC7;
|
|
}
|
|
if (rd->m_FormatR8G8B8A8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR8G8B8A8;
|
|
return eTF_R8G8B8A8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_R9G9B9E5:
|
|
if (rd->m_FormatR9G9B9E5.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR9G9B9E5;
|
|
return eTF_R9G9B9E5;
|
|
}
|
|
if (rd->m_FormatR16G16B16A16F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatR16G16B16A16F;
|
|
return eTF_R16G16B16A16F;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_D16:
|
|
if (rd->m_FormatD16.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatD16;
|
|
return eTF_D16;
|
|
}
|
|
case eTF_D24S8:
|
|
if (rd->m_FormatD24S8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatD24S8;
|
|
return eTF_D24S8;
|
|
}
|
|
case eTF_D32F:
|
|
if (rd->m_FormatD32F.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatD32F;
|
|
return eTF_D32F;
|
|
}
|
|
case eTF_D32FS8:
|
|
if (rd->m_FormatD32FS8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatD32FS8;
|
|
return eTF_D32FS8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_EAC_R11:
|
|
if (rd->m_FormatEAC_R11.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatEAC_R11;
|
|
return eTF_EAC_R11;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_EAC_RG11:
|
|
if (rd->m_FormatEAC_RG11.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatEAC_RG11;
|
|
return eTF_EAC_RG11;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ETC2:
|
|
if (rd->m_FormatETC2.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatETC2;
|
|
return eTF_ETC2;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ETC2A:
|
|
if (rd->m_FormatETC2A.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatETC2A;
|
|
return eTF_ETC2A;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
#ifdef CRY_USE_METAL
|
|
case eTF_PVRTC2:
|
|
if (rd->m_FormatPVRTC2.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatPVRTC2;
|
|
return eTF_PVRTC2;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_PVRTC4:
|
|
if (rd->m_FormatPVRTC4.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatPVRTC4;
|
|
return eTF_PVRTC4;
|
|
}
|
|
return eTF_Unknown;
|
|
#endif
|
|
#if defined(ANDROID) || defined(CRY_USE_METAL)
|
|
case eTF_ASTC_4x4:
|
|
if (rd->m_FormatASTC_4x4.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_4x4;
|
|
return eTF_ASTC_4x4;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_5x4:
|
|
if (rd->m_FormatASTC_5x4.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_5x4;
|
|
return eTF_ASTC_5x4;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_5x5:
|
|
if (rd->m_FormatASTC_5x5.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_5x5;
|
|
return eTF_ASTC_5x5;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_6x5:
|
|
if (rd->m_FormatASTC_6x5.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_6x5;
|
|
return eTF_ASTC_6x5;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_6x6:
|
|
if (rd->m_FormatASTC_6x6.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_6x6;
|
|
return eTF_ASTC_6x6;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_8x5:
|
|
if (rd->m_FormatASTC_8x5.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_8x5;
|
|
return eTF_ASTC_8x5;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_8x6:
|
|
if (rd->m_FormatASTC_8x6.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_8x6;
|
|
return eTF_ASTC_8x6;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_8x8:
|
|
if (rd->m_FormatASTC_8x8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_8x8;
|
|
return eTF_ASTC_8x8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_10x5:
|
|
if (rd->m_FormatASTC_10x5.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_10x5;
|
|
return eTF_ASTC_10x5;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_10x6:
|
|
if (rd->m_FormatASTC_10x6.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_10x6;
|
|
return eTF_ASTC_10x6;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_10x8:
|
|
if (rd->m_FormatASTC_10x8.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_10x8;
|
|
return eTF_ASTC_10x8;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_10x10:
|
|
if (rd->m_FormatASTC_10x10.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_10x10;
|
|
return eTF_ASTC_10x10;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_12x10:
|
|
if (rd->m_FormatASTC_12x10.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_12x10;
|
|
return eTF_ASTC_12x10;
|
|
}
|
|
return eTF_Unknown;
|
|
|
|
case eTF_ASTC_12x12:
|
|
if (rd->m_FormatASTC_12x12.IsValid())
|
|
{
|
|
pPF = &rd->m_FormatASTC_12x12;
|
|
return eTF_ASTC_12x12;
|
|
}
|
|
return eTF_Unknown;
|
|
#endif
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
return eTF_Unknown;
|
|
}
|
|
|
|
//===============================================================================
|
|
|
|
bool CTexture::CreateRenderTarget(ETEX_Format eTF, const ColorF& cClear)
|
|
{
|
|
if (eTF == eTF_Unknown)
|
|
{
|
|
eTF = m_eTFDst;
|
|
}
|
|
if (eTF == eTF_Unknown)
|
|
{
|
|
return false;
|
|
}
|
|
const byte* pData[6] = { NULL };
|
|
|
|
ETEX_Format eTFDst = ClosestFormatSupported(eTF);
|
|
if (eTF != eTFDst)
|
|
{
|
|
return false;
|
|
}
|
|
m_eTFDst = eTF;
|
|
m_nFlags |= FT_USAGE_RENDERTARGET;
|
|
m_cClearColor = cClear;
|
|
bool bRes = CreateDeviceTexture(pData);
|
|
PostCreate();
|
|
|
|
// Assign name to RT for enhanced debugging
|
|
#if !defined(_RELEASE)
|
|
#if defined(WIN32)
|
|
#define D3DTEXTURE_CPP_USE_PRIVATEDATA
|
|
#elif defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_3
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(D3DTEXTURE_CPP_USE_PRIVATEDATA)
|
|
if (bRes)
|
|
{
|
|
m_pDevTexture->GetBaseTexture()->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(m_SrcName.c_str()), m_SrcName.c_str());
|
|
}
|
|
#endif
|
|
|
|
return bRes;
|
|
}
|
|
|
|
// Resolve anti-aliased RT to the texture
|
|
bool CTexture::Resolve([[maybe_unused]] int nTarget, [[maybe_unused]] bool bUseViewportSize)
|
|
{
|
|
if (m_bResolved)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
m_bResolved = true;
|
|
if (!(m_nFlags & FT_USAGE_MSAA))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
assert ((m_nFlags & FT_USAGE_RENDERTARGET) && (m_nFlags & FT_USAGE_MSAA) && m_pDeviceShaderResource && m_pDevTexture && m_pRenderTargetData->m_pDeviceTextureMSAA);
|
|
CDeviceTexture* pDestSurf = GetDevTexture();
|
|
CDeviceTexture* pSrcSurf = GetDevTextureMSAA();
|
|
|
|
assert(pSrcSurf != NULL);
|
|
assert(pDestSurf != NULL);
|
|
|
|
gcpRendD3D->GetDeviceContext().ResolveSubresource(pDestSurf->Get2DTexture(), 0, pSrcSurf->Get2DTexture(), 0, (DXGI_FORMAT)m_pPixelFormat->DeviceFormat);
|
|
return true;
|
|
}
|
|
|
|
bool CTexture::CreateDeviceTexture(const byte* pData[6])
|
|
{
|
|
if (!m_pPixelFormat)
|
|
{
|
|
ETEX_Format eTF = ClosestFormatSupported(m_eTFDst);
|
|
|
|
assert(eTF != eTF_Unknown);
|
|
assert(eTF == m_eTFDst);
|
|
}
|
|
assert(m_pPixelFormat);
|
|
if (!m_pPixelFormat)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (gRenDev->m_pRT->RC_CreateDeviceTexture(this, pData))
|
|
{
|
|
// Assign name to Texture for enhanced debugging
|
|
#if !defined(RELEASE)
|
|
#if defined (WIN64)
|
|
m_pDevTexture->GetBaseTexture()->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(m_SrcName.c_str()), m_SrcName.c_str());
|
|
#elif defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_4
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void CTexture::Unbind()
|
|
{
|
|
if (m_pDeviceShaderResource)
|
|
{
|
|
gcpRendD3D->m_DevMan.UnbindSRV(m_pDeviceShaderResource);
|
|
}
|
|
|
|
CDeviceTexture* pDevTex = m_pDevTexture;
|
|
|
|
if (pDevTex)
|
|
{
|
|
pDevTex->Unbind();
|
|
}
|
|
}
|
|
|
|
bool CTexture::RT_CreateDeviceTexture(const byte* pData[6])
|
|
{
|
|
SCOPED_RENDERER_ALLOCATION_NAME_HINT(GetSourceName());
|
|
AZ_ASSET_ATTACH_TO_SCOPE(this);
|
|
|
|
HRESULT hr;
|
|
|
|
int32 nESRAMOffset = -1;
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_5
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
|
|
//if we have any device owned resources allocated, we must sync with render thread
|
|
if (m_pDevTexture)
|
|
{
|
|
ReleaseDeviceTexture(false);
|
|
}
|
|
else
|
|
{
|
|
SAFE_DELETE(m_pRenderTargetData);
|
|
}
|
|
|
|
CD3D9Renderer* r = gcpRendD3D;
|
|
int nWdt = m_nWidth;
|
|
int nHgt = m_nHeight;
|
|
int nDepth = m_nDepth;
|
|
int nMips = m_nMips;
|
|
AZ_Assert(nWdt > 0 && nHgt > 0 && nMips > 0, "Attempting to create a device texture '%s' with height:%d, width:%d, and mip levels:%d. All three must be > 0", GetSourceName(), nHgt, nWdt, nMips);
|
|
|
|
#ifdef CRY_USE_METAL
|
|
bool isMetalCompressedTextureFormat = GetBlockDim(m_eTFSrc) != Vec2i(1);
|
|
#else
|
|
bool isMetalCompressedTextureFormat = false;
|
|
#endif
|
|
|
|
bool allowReinterpretingColorSpace = !isMetalCompressedTextureFormat && RenderCapabilities::SupportsTextureViews();
|
|
|
|
byte* pTemp = NULL;
|
|
|
|
CDeviceManager* pDevMan = &r->m_DevMan;
|
|
|
|
bool resetSRGB = true;
|
|
|
|
if (m_nFlags & (FT_USAGE_RENDERTARGET | FT_USAGE_UNORDERED_ACCESS))
|
|
{
|
|
m_pRenderTargetData = new RenderTargetData();
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_6
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
}
|
|
|
|
uint32 nArraySize = m_nArraySize;
|
|
|
|
if (m_eTT == eTT_2D)
|
|
{
|
|
STextureInfo TI;
|
|
D3DFormat D3DFmt = m_pPixelFormat->DeviceFormat;
|
|
|
|
//nMips = 1;
|
|
DXGI_FORMAT nFormatOrig = D3DFmt;
|
|
|
|
resetSRGB = false;
|
|
|
|
m_bIsSRGB &= m_pPixelFormat->bCanReadSRGB && (m_nFlags & (FT_USAGE_MSAA | FT_USAGE_RENDERTARGET)) == 0;
|
|
|
|
if (m_bIsSRGB)
|
|
{
|
|
D3DFmt = ConvertToSRGBFmt(D3DFmt);
|
|
}
|
|
|
|
// must use typeless format to allow runtime casting
|
|
if (m_nFlags & FT_USAGE_ALLOWREADSRGB && allowReinterpretingColorSpace)
|
|
{
|
|
D3DFmt = ConvertToTypelessFmt(D3DFmt);
|
|
}
|
|
|
|
uint32 nUsage = 0;
|
|
if (m_nFlags & FT_USAGE_DEPTHSTENCIL)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_DEPTH_STENCIL;
|
|
}
|
|
if (m_nFlags & FT_USAGE_RENDERTARGET)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_RENDER_TARGET;
|
|
}
|
|
|
|
#if defined(AZ_PLATFORM_IOS)
|
|
if (m_nFlags & FT_USAGE_MEMORYLESS)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_MEMORYLESS;
|
|
}
|
|
#endif
|
|
|
|
if (m_nFlags & FT_USAGE_DYNAMIC)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_DYNAMIC;
|
|
}
|
|
if (m_nFlags & FT_STAGE_READBACK)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_STAGE_ACCESS | CDeviceManager::USAGE_CPU_READ;
|
|
}
|
|
if (m_nFlags & FT_STAGE_UPLOAD)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_STAGE_ACCESS | CDeviceManager::USAGE_CPU_WRITE;
|
|
}
|
|
if (m_nFlags & FT_USAGE_UNORDERED_ACCESS
|
|
#if defined(SUPPORT_DEVICE_INFO)
|
|
&& r->DevInfo().FeatureLevel() >= D3D_FEATURE_LEVEL_11_0
|
|
#endif //defined(SUPPORT_DEVICE_INFO)
|
|
)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_UNORDERED_ACCESS;
|
|
}
|
|
if ((m_nFlags & (FT_DONT_RELEASE | FT_DONT_STREAM)) == (FT_DONT_RELEASE | FT_DONT_STREAM))
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_ETERNAL;
|
|
}
|
|
if (m_nFlags & FT_USAGE_UAV_RWTEXTURE)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_UAV_RWTEXTURE;
|
|
}
|
|
|
|
if (m_nFlags & FT_FORCE_MIPS)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_AUTOGENMIPS;
|
|
if (nMips <= 1)
|
|
{
|
|
m_nMips = nMips = max(1, CTexture::CalcNumMips(nWdt, nHgt) - 2);
|
|
}
|
|
}
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_14
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
|
|
if (m_nFlags & FT_USAGE_MSAA)
|
|
{
|
|
m_pRenderTargetData->m_nMSAASamples = (uint8)r->m_RP.m_MSAAData.Type;
|
|
m_pRenderTargetData->m_nMSAAQuality = (uint8)r->m_RP.m_MSAAData.Quality;
|
|
|
|
TI.m_nMSAASamples = m_pRenderTargetData->m_nMSAASamples;
|
|
TI.m_nMSAAQuality = m_pRenderTargetData->m_nMSAAQuality;
|
|
hr = pDevMan->Create2DTexture(m_SrcName, nWdt, nHgt, nMips, nArraySize, nUsage, m_cClearColor, D3DFmt, (D3DPOOL)0, &m_pRenderTargetData->m_pDeviceTextureMSAA, &TI);
|
|
|
|
AZ_Assert(SUCCEEDED(hr), "Call to Create2DTexture failed for '%s'.", GetSourceName());
|
|
m_bResolved = false;
|
|
|
|
TI.m_nMSAASamples = 1;
|
|
TI.m_nMSAAQuality = 0;
|
|
}
|
|
|
|
if (pData[0])
|
|
{
|
|
{
|
|
STextureInfoData InitData[20];
|
|
int w = nWdt;
|
|
int h = nHgt;
|
|
int nOffset = 0;
|
|
const byte* src = pData[0];
|
|
for (int i = 0; i < nMips; i++)
|
|
{
|
|
if (!w && !h)
|
|
{
|
|
break;
|
|
}
|
|
if (!w)
|
|
{
|
|
w = 1;
|
|
}
|
|
if (!h)
|
|
{
|
|
h = 1;
|
|
}
|
|
|
|
int nSize = TextureDataSize(w, h, 1, 1, 1, m_eTFSrc, m_eSrcTileMode);
|
|
InitData[i].pSysMem = &src[nOffset];
|
|
if (m_eSrcTileMode == eTM_None)
|
|
{
|
|
const Vec2i BlockDim = GetBlockDim(m_eTFSrc);
|
|
if (BlockDim == Vec2i(1))
|
|
{
|
|
InitData[i].SysMemPitch = TextureDataSize(w, 1, 1, 1, 1, m_eTFSrc, eTM_None);
|
|
}
|
|
else
|
|
{
|
|
int blockSize = CImageExtensionHelper::BytesPerBlock(m_eTFSrc);
|
|
InitData[i].SysMemPitch = (w + BlockDim.x - 1) / BlockDim.x * blockSize;
|
|
}
|
|
|
|
//ignored
|
|
InitData[i].SysMemSlicePitch = nSize;
|
|
InitData[i].SysMemTileMode = eTM_None;
|
|
}
|
|
else
|
|
{
|
|
InitData[i].SysMemPitch = 0;
|
|
InitData[i].SysMemSlicePitch = 0;
|
|
InitData[i].SysMemTileMode = m_eSrcTileMode;
|
|
}
|
|
|
|
w >>= 1;
|
|
h >>= 1;
|
|
nOffset += nSize;
|
|
}
|
|
|
|
TI.m_pData = InitData;
|
|
|
|
SAFE_RELEASE(m_pDevTexture);
|
|
hr = pDevMan->Create2DTexture(m_SrcName, nWdt, nHgt, nMips, nArraySize, nUsage, m_cClearColor, D3DFmt, (D3DPOOL)0, &m_pDevTexture, &TI);
|
|
if (!FAILED(hr) && m_pDevTexture)
|
|
{
|
|
m_pDevTexture->SetNoDelete(!!(m_nFlags & FT_DONT_RELEASE));
|
|
}
|
|
}
|
|
}
|
|
else // no texture data so just make an empty texture
|
|
{
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_7
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
|
|
SAFE_RELEASE(m_pDevTexture);
|
|
hr = pDevMan->Create2DTexture(m_SrcName, nWdt, nHgt, nMips, nArraySize, nUsage, m_cClearColor, D3DFmt, (D3DPOOL)0, &m_pDevTexture, &TI, false, nESRAMOffset);
|
|
if (!FAILED(hr) && m_pDevTexture)
|
|
{
|
|
m_pDevTexture->SetNoDelete(!!(m_nFlags & FT_DONT_RELEASE));
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
AZ_Assert(0, "Call to Create2DTexture failed for '%s'.", GetSourceName());
|
|
return false;
|
|
}
|
|
|
|
// Restore format
|
|
if (m_nFlags & FT_USAGE_ALLOWREADSRGB)
|
|
{
|
|
D3DFmt = nFormatOrig;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
m_pDeviceShaderResource = static_cast<D3DShaderResourceView*> (CreateDeviceResourceView(SResourceView::ShaderResourceView(m_eTFDst, 0, -1, 0, nMips, m_bIsSRGB, false)));
|
|
|
|
m_nMinMipVidActive = 0;
|
|
|
|
if (m_nFlags & FT_USAGE_ALLOWREADSRGB && allowReinterpretingColorSpace)
|
|
{
|
|
m_pDeviceShaderResourceSRGB = static_cast<D3DShaderResourceView*> (CreateDeviceResourceView(SResourceView::ShaderResourceView(m_eTFDst, 0, -1, 0, nMips, true, false)));
|
|
}
|
|
}
|
|
else if (m_eTT == eTT_Cube)
|
|
{
|
|
STextureInfo TI;
|
|
D3DFormat D3DFmt = m_pPixelFormat->DeviceFormat;
|
|
uint32 nUsage = 0;
|
|
if (m_nFlags & FT_USAGE_DEPTHSTENCIL)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_DEPTH_STENCIL;
|
|
}
|
|
if (m_nFlags & FT_USAGE_RENDERTARGET)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_RENDER_TARGET;
|
|
}
|
|
|
|
#if defined(AZ_PLATFORM_IOS)
|
|
if (m_nFlags & FT_USAGE_MEMORYLESS)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_MEMORYLESS;
|
|
}
|
|
#endif
|
|
|
|
if (m_nFlags & FT_USAGE_DYNAMIC)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_DYNAMIC;
|
|
}
|
|
if (m_nFlags & FT_STAGE_READBACK)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_STAGE_ACCESS | CDeviceManager::USAGE_CPU_READ;
|
|
}
|
|
if (m_nFlags & FT_STAGE_UPLOAD)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_STAGE_ACCESS | CDeviceManager::USAGE_CPU_WRITE;
|
|
}
|
|
if ((m_nFlags & (FT_DONT_RELEASE | FT_DONT_STREAM)) == (FT_DONT_RELEASE | FT_DONT_STREAM))
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_ETERNAL;
|
|
}
|
|
|
|
if (m_nFlags & FT_FORCE_MIPS)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_AUTOGENMIPS;
|
|
if (nMips <= 1)
|
|
{
|
|
m_nMips = nMips = max(1, CTexture::CalcNumMips(nWdt, nHgt) - 2);
|
|
}
|
|
}
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_14
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
|
|
if (m_nFlags & FT_USAGE_MSAA)
|
|
{
|
|
m_pRenderTargetData->m_nMSAASamples = (uint8)r->m_RP.m_MSAAData.Type;
|
|
m_pRenderTargetData->m_nMSAAQuality = (uint8)r->m_RP.m_MSAAData.Quality;
|
|
|
|
TI.m_nMSAASamples = m_pRenderTargetData->m_nMSAASamples;
|
|
TI.m_nMSAAQuality = m_pRenderTargetData->m_nMSAAQuality;
|
|
hr = pDevMan->CreateCubeTexture(m_SrcName, nWdt, nMips, m_nArraySize, nUsage, m_cClearColor, D3DFmt, (D3DPOOL)0, &m_pRenderTargetData->m_pDeviceTextureMSAA, &TI);
|
|
|
|
AZ_Assert(SUCCEEDED(hr), "Call to CreateCubeTexuture failed for '%s'.", GetSourceName());
|
|
m_bResolved = false;
|
|
|
|
TI.m_nMSAASamples = 1;
|
|
TI.m_nMSAAQuality = 0;
|
|
}
|
|
DXGI_FORMAT nFormatOrig = D3DFmt;
|
|
DXGI_FORMAT nFormatSRGB = D3DFmt;
|
|
|
|
resetSRGB = false;
|
|
|
|
{
|
|
m_bIsSRGB &= m_pPixelFormat->bCanReadSRGB && (m_nFlags & (FT_USAGE_MSAA | FT_USAGE_RENDERTARGET)) == 0;
|
|
|
|
if ((m_bIsSRGB || m_nFlags & FT_USAGE_ALLOWREADSRGB))
|
|
{
|
|
nFormatSRGB = ConvertToSRGBFmt(D3DFmt);
|
|
}
|
|
|
|
if (m_bIsSRGB)
|
|
{
|
|
D3DFmt = nFormatSRGB;
|
|
}
|
|
|
|
// must use typeless format to allow runtime casting
|
|
if (m_nFlags & FT_USAGE_ALLOWREADSRGB)
|
|
{
|
|
D3DFmt = ConvertToTypelessFmt(D3DFmt);
|
|
}
|
|
}
|
|
|
|
if (pData[0])
|
|
{
|
|
AZ_Assert(m_nArraySize == 1, "There is no implementation for tex array data.");
|
|
|
|
STextureInfoData InitData[g_nD3D10MaxSupportedSubres];
|
|
|
|
for (int nSide = 0; nSide < 6; nSide++)
|
|
{
|
|
int w = nWdt;
|
|
int h = nHgt;
|
|
int nOffset = 0;
|
|
const byte* src = (!(m_nFlags & FT_REPLICATE_TO_ALL_SIDES)) ? pData[nSide] : pData[0];
|
|
|
|
for (int i = 0; i < nMips; i++)
|
|
{
|
|
if (!w && !h)
|
|
{
|
|
break;
|
|
}
|
|
if (!w)
|
|
{
|
|
w = 1;
|
|
}
|
|
if (!h)
|
|
{
|
|
h = 1;
|
|
}
|
|
|
|
int nSubresInd = nSide * nMips + i;
|
|
int nSize = TextureDataSize(w, h, 1, 1, 1, m_eTFSrc, m_eSrcTileMode);
|
|
|
|
InitData[nSubresInd].pSysMem = &src[nOffset];
|
|
|
|
if (m_eSrcTileMode == eTM_None)
|
|
{
|
|
InitData[nSubresInd].SysMemPitch = TextureDataSize(w, 1, 1, 1, 1, m_eTFSrc, eTM_None);
|
|
|
|
//ignored
|
|
InitData[nSubresInd].SysMemSlicePitch = nSize;
|
|
InitData[nSubresInd].SysMemTileMode = eTM_None;
|
|
}
|
|
else
|
|
{
|
|
InitData[nSubresInd].SysMemPitch = 0;
|
|
InitData[nSubresInd].SysMemSlicePitch = 0;
|
|
InitData[nSubresInd].SysMemTileMode = m_eSrcTileMode;
|
|
}
|
|
|
|
w >>= 1;
|
|
h >>= 1;
|
|
nOffset += nSize;
|
|
}
|
|
}
|
|
|
|
TI.m_pData = InitData;
|
|
SAFE_RELEASE(m_pDevTexture);
|
|
hr = pDevMan->CreateCubeTexture(m_SrcName, nWdt, nMips, m_nArraySize, nUsage, m_cClearColor, D3DFmt, (D3DPOOL)0, &m_pDevTexture, &TI);
|
|
if (!FAILED(hr) && m_pDevTexture)
|
|
{
|
|
m_pDevTexture->SetNoDelete(!!(m_nFlags & FT_DONT_RELEASE));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//hr = gcpRendD3D->GetDevice().CreateTexture2D(&Desc, 0, 0); // validates parameters
|
|
//assert(hr == S_FALSE);
|
|
SAFE_RELEASE(m_pDevTexture);
|
|
hr = pDevMan->CreateCubeTexture(m_SrcName, nWdt, nMips, m_nArraySize, nUsage, m_cClearColor, D3DFmt, (D3DPOOL)0, &m_pDevTexture, &TI);
|
|
if (!FAILED(hr) && m_pDevTexture)
|
|
{
|
|
m_pDevTexture->SetNoDelete(!!(m_nFlags & FT_DONT_RELEASE));
|
|
}
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
AZ_Assert(0, "Call to CreateCubeTexture failed for '%s'.", GetSourceName());
|
|
return false;
|
|
}
|
|
|
|
if (m_nFlags & FT_USAGE_ALLOWREADSRGB)
|
|
{
|
|
D3DFmt = nFormatOrig;
|
|
}
|
|
|
|
D3DCubeTexture* pID3DTexture = m_pDevTexture->GetCubeTexture();
|
|
|
|
D3DShaderResourceView* pRes = NULL;
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC ResDesc;
|
|
ZeroStruct(ResDesc);
|
|
ResDesc.Format = (DXGI_FORMAT)ConvertToShaderResourceFmt(D3DFmt);
|
|
|
|
if (m_nArraySize > 1)
|
|
{
|
|
ResDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
|
|
ResDesc.TextureCubeArray.MipLevels = nMips;
|
|
ResDesc.TextureCubeArray.First2DArrayFace = 0;
|
|
ResDesc.TextureCubeArray.NumCubes = m_nArraySize;
|
|
|
|
// Create the multi-slice shader resource view
|
|
hr = gcpRendD3D->GetDevice().CreateShaderResourceView(pID3DTexture, &ResDesc, &pRes);
|
|
if (FAILED(hr))
|
|
{
|
|
AZ_Assert(0, "Call to CreateShaderResourceView failed for '%s'.", GetSourceName());
|
|
return false;
|
|
}
|
|
m_pDeviceShaderResource = pRes;
|
|
m_nMinMipVidActive = 0;
|
|
}
|
|
else
|
|
{
|
|
ResDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
|
ResDesc.TextureCube.MipLevels = nMips;
|
|
ResDesc.TextureCube.MostDetailedMip = 0;
|
|
hr = gcpRendD3D->GetDevice().CreateShaderResourceView(pID3DTexture, &ResDesc, &pRes);
|
|
if (FAILED(hr))
|
|
{
|
|
AZ_Assert(0, "Call to CreateShaderResourceView failed for '%s'.", GetSourceName());
|
|
return false;
|
|
}
|
|
m_pDeviceShaderResource = pRes;
|
|
m_nMinMipVidActive = 0;
|
|
|
|
if (m_nFlags & FT_USAGE_ALLOWREADSRGB)
|
|
{
|
|
ResDesc.Format = (DXGI_FORMAT)ConvertToShaderResourceFmt(nFormatSRGB);
|
|
|
|
D3DShaderResourceView* pSRGBRes = NULL;
|
|
hr = gcpRendD3D->GetDevice().CreateShaderResourceView(pID3DTexture, &ResDesc, &pSRGBRes);
|
|
if (FAILED(hr))
|
|
{
|
|
AZ_Assert(0, "Call to CreateShaderResourceView failed for '%s'.", GetSourceName());
|
|
return false;
|
|
}
|
|
//assign shader resource views
|
|
m_pDeviceShaderResourceSRGB = pSRGBRes;
|
|
}
|
|
}
|
|
}
|
|
else if (m_eTT == eTT_3D)
|
|
{
|
|
STextureInfo TI;
|
|
D3DFormat D3DFmt = m_pPixelFormat->DeviceFormat;
|
|
|
|
uint32 nUsage = 0;
|
|
if (m_nFlags & FT_USAGE_DEPTHSTENCIL)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_DEPTH_STENCIL;
|
|
}
|
|
if (m_nFlags & FT_USAGE_RENDERTARGET)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_RENDER_TARGET;
|
|
}
|
|
|
|
#if defined(AZ_PLATFORM_IOS)
|
|
if (m_nFlags & FT_USAGE_MEMORYLESS)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_MEMORYLESS;
|
|
}
|
|
#endif
|
|
|
|
if (m_nFlags & FT_USAGE_DYNAMIC)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_DYNAMIC;
|
|
}
|
|
if ((m_nFlags & (FT_DONT_RELEASE | FT_DONT_STREAM)) == (FT_DONT_RELEASE | FT_DONT_STREAM))
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_ETERNAL;
|
|
}
|
|
if (m_nFlags & FT_STAGE_READBACK)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_STAGE_ACCESS | CDeviceManager::USAGE_CPU_READ;
|
|
}
|
|
if (m_nFlags & FT_STAGE_UPLOAD)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_STAGE_ACCESS | CDeviceManager::USAGE_CPU_WRITE;
|
|
}
|
|
if (m_nFlags & FT_USAGE_UNORDERED_ACCESS
|
|
#if defined(SUPPORT_DEVICE_INFO)
|
|
&& r->DevInfo().FeatureLevel() >= D3D_FEATURE_LEVEL_11_0
|
|
#endif //defined(SUPPORT_DEVICE_INFO)
|
|
)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_UNORDERED_ACCESS;
|
|
}
|
|
if (m_nFlags & FT_USAGE_UAV_RWTEXTURE)
|
|
{
|
|
nUsage |= CDeviceManager::USAGE_UAV_RWTEXTURE;
|
|
}
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_14
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
|
|
if (m_nFlags & FT_USAGE_MSAA)
|
|
{
|
|
m_pRenderTargetData->m_nMSAASamples = (uint8)r->m_RP.m_MSAAData.Type;
|
|
m_pRenderTargetData->m_nMSAAQuality = (uint8)r->m_RP.m_MSAAData.Quality;
|
|
|
|
TI.m_nMSAASamples = m_pRenderTargetData->m_nMSAASamples;
|
|
TI.m_nMSAAQuality = m_pRenderTargetData->m_nMSAAQuality;
|
|
hr = pDevMan->CreateVolumeTexture(m_SrcName, nWdt, nHgt, m_nDepth, nMips, nUsage, m_cClearColor, D3DFmt, (D3DPOOL)0, &m_pRenderTargetData->m_pDeviceTextureMSAA, &TI);
|
|
|
|
AZ_Assert(SUCCEEDED(hr), "Call to CreateVolumeTexture failed for '%s'.", GetSourceName());
|
|
m_bResolved = false;
|
|
|
|
TI.m_nMSAASamples = 1;
|
|
TI.m_nMSAAQuality = 0;
|
|
}
|
|
if (pData[0])
|
|
{
|
|
STextureInfoData InitData[15];
|
|
|
|
int w = nWdt;
|
|
int h = nHgt;
|
|
int d = nDepth;
|
|
int nOffset = 0;
|
|
const byte* src = pData[0];
|
|
|
|
for (int i = 0; i < nMips; i++)
|
|
{
|
|
if (!w && !h && !d)
|
|
{
|
|
break;
|
|
}
|
|
if (!w)
|
|
{
|
|
w = 1;
|
|
}
|
|
if (!h)
|
|
{
|
|
h = 1;
|
|
}
|
|
if (!d)
|
|
{
|
|
d = 1;
|
|
}
|
|
|
|
int nSliceSize = TextureDataSize(w, h, 1, 1, 1, m_eTFSrc);
|
|
int nMipSize = TextureDataSize(w, h, d, 1, 1, m_eTFSrc);
|
|
InitData[i].pSysMem = &src[nOffset];
|
|
InitData[i].SysMemPitch = TextureDataSize(w, 1, 1, 1, 1, m_eTFSrc);
|
|
|
|
//ignored
|
|
InitData[i].SysMemSlicePitch = nSliceSize;
|
|
InitData[i].SysMemTileMode = eTM_None;
|
|
|
|
w >>= 1;
|
|
h >>= 1;
|
|
d >>= 1;
|
|
|
|
nOffset += nMipSize;
|
|
}
|
|
|
|
TI.m_pData = InitData;
|
|
SAFE_RELEASE(m_pDevTexture);
|
|
hr = pDevMan->CreateVolumeTexture(m_SrcName, nWdt, nHgt, nDepth, nMips, nUsage, m_cClearColor, D3DFmt, (D3DPOOL)0, &m_pDevTexture, &TI);
|
|
if (!FAILED(hr) && m_pDevTexture)
|
|
{
|
|
m_pDevTexture->SetNoDelete(!!(m_nFlags & FT_DONT_RELEASE));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//hr = gcpRendD3D->GetDevice().CreateTexture2D(&Desc, 0, 0); // validates parameters
|
|
//assert(hr == S_FALSE);
|
|
SAFE_RELEASE(m_pDevTexture);
|
|
hr = pDevMan->CreateVolumeTexture(m_SrcName, nWdt, nHgt, nDepth, nMips, nUsage, m_cClearColor, D3DFmt, (D3DPOOL)0, &m_pDevTexture, &TI);
|
|
if (!FAILED(hr) && m_pDevTexture)
|
|
{
|
|
m_pDevTexture->SetNoDelete(!!(m_nFlags & FT_DONT_RELEASE));
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PREFAST_ASSUME(m_pDevTexture);
|
|
|
|
m_pDeviceShaderResource = static_cast<D3DShaderResourceView*> (CreateDeviceResourceView(SResourceView::ShaderResourceView(m_eTFDst)));
|
|
m_nMinMipVidActive = 0;
|
|
}
|
|
else
|
|
{
|
|
AZ_Assert(0, "Call to CreateVolumeTexture failed for '%s'.", GetSourceName());
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AZ_Assert(0, "Texture type not supported for this function.");
|
|
return false;
|
|
}
|
|
|
|
SetTexStates();
|
|
|
|
AZ_Assert(!IsStreamed(), "IsStreamed must be false.");
|
|
if (m_pDevTexture)
|
|
{
|
|
m_nActualSize = m_nPersistentSize = m_pDevTexture->GetDeviceSize();
|
|
if (m_nFlags & (FT_USAGE_DYNAMIC | FT_USAGE_RENDERTARGET))
|
|
{
|
|
CTexture::s_nStatsCurDynamicTexMem += m_nActualSize;
|
|
}
|
|
else
|
|
{
|
|
CTexture::s_nStatsCurManagedNonStreamedTexMem += m_nActualSize;
|
|
}
|
|
}
|
|
|
|
// Notify that resource is dirty
|
|
InvalidateDeviceResource(eDeviceResourceDirty | eDeviceResourceViewDirty);
|
|
|
|
#if defined(D3DTEXTURE_CPP_USE_PRIVATEDATA)
|
|
if (m_pDevTexture)
|
|
{
|
|
m_pDevTexture->GetBaseTexture()->SetPrivateData(WKPDID_D3DDebugObjectName, m_SrcName.length(), m_SrcName.c_str());
|
|
}
|
|
#endif
|
|
|
|
if (!pData[0])
|
|
{
|
|
return true;
|
|
}
|
|
|
|
int nOffset = 0;
|
|
|
|
if (resetSRGB)
|
|
{
|
|
m_bIsSRGB = false;
|
|
}
|
|
|
|
SetWasUnload(false);
|
|
|
|
SAFE_DELETE_ARRAY(pTemp);
|
|
return true;
|
|
}
|
|
|
|
void CTexture::ReleaseDeviceTexture(bool bKeepLastMips, bool bFromUnload)
|
|
{
|
|
PROFILE_FRAME(CTexture_ReleaseDeviceTexture);
|
|
AZ_TRACE_METHOD();
|
|
|
|
if (!gcpRendD3D->m_pRT->IsRenderThread())
|
|
{
|
|
if (!gcpRendD3D->m_pRT->IsMainThread())
|
|
{
|
|
CryFatalError("Texture is deleted from non-main and non-render thread, which causes command buffer corruption!");
|
|
}
|
|
|
|
// Push to render thread to process
|
|
gcpRendD3D->m_pRT->RC_ReleaseDeviceTexture(this);
|
|
return;
|
|
}
|
|
|
|
Unbind();
|
|
|
|
if (!bFromUnload)
|
|
{
|
|
AbortStreamingTasks(this);
|
|
}
|
|
|
|
if (s_pTextureStreamer)
|
|
{
|
|
s_pTextureStreamer->OnTextureDestroy(this);
|
|
}
|
|
|
|
SAFE_DELETE(m_pRenderTargetData);
|
|
|
|
if (!m_bNoTexture)
|
|
{
|
|
CDeviceTexture* pTex = m_pDevTexture;
|
|
|
|
D3DShaderResourceView* pSRVSRGB = m_pDeviceShaderResourceSRGB;
|
|
SAFE_RELEASE(pSRVSRGB);
|
|
m_pDeviceShaderResourceSRGB = NULL;
|
|
|
|
D3DShaderResourceView* pSRV = m_pDeviceShaderResource;
|
|
SAFE_RELEASE(pSRV);
|
|
m_pDeviceShaderResource = 0;
|
|
|
|
D3DSurface* pRTV = m_pDeviceRTV;
|
|
SAFE_RELEASE(pRTV);
|
|
m_pDeviceRTV = NULL;
|
|
|
|
D3DSurface* pRTVMS = m_pDeviceRTVMS;
|
|
SAFE_RELEASE(pRTVMS);
|
|
m_pDeviceRTVMS = NULL;
|
|
|
|
if (!m_pFileTexMips || !m_pFileTexMips->m_pPoolItem)
|
|
{
|
|
if (IsStreamed())
|
|
{
|
|
SAFE_DELETE(pTex); // for manually created textures
|
|
}
|
|
else
|
|
{
|
|
SAFE_RELEASE(pTex);
|
|
}
|
|
}
|
|
|
|
m_pDevTexture = NULL;
|
|
|
|
// otherwise it's already taken into account in the m_pFileTexMips->m_pPoolItem's dtor
|
|
if (!m_pFileTexMips || !m_pFileTexMips->m_pPoolItem)
|
|
{
|
|
if (IsDynamic())
|
|
{
|
|
assert(CTexture::s_nStatsCurDynamicTexMem >= m_nActualSize);
|
|
CTexture::s_nStatsCurDynamicTexMem -= m_nActualSize;
|
|
}
|
|
else if (!IsStreamed())
|
|
{
|
|
assert(CTexture::s_nStatsCurManagedNonStreamedTexMem >= m_nActualSize);
|
|
CTexture::s_nStatsCurManagedNonStreamedTexMem -= m_nActualSize;
|
|
}
|
|
}
|
|
if (m_pFileTexMips)
|
|
{
|
|
m_bStreamPrepared = false;
|
|
StreamRemoveFromPool();
|
|
if (bKeepLastMips)
|
|
{
|
|
const int nLastMipsStart = m_nMips - m_CacheFileHeader.m_nMipsPersistent;
|
|
int nSides = StreamGetNumSlices();
|
|
for (int nS = 0; nS < nSides; nS++)
|
|
{
|
|
for (int i = 0; i < nLastMipsStart; i++)
|
|
{
|
|
SMipData* mp = &m_pFileTexMips->m_pMipHeader[i].m_Mips[nS];
|
|
mp->Free();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Unlink();
|
|
StreamState_ReleaseInfo(this, m_pFileTexMips);
|
|
m_pFileTexMips = NULL;
|
|
m_bStreamed = false;
|
|
SetStreamingInProgress(InvalidStreamSlot);
|
|
m_bStreamRequested = false;
|
|
}
|
|
}
|
|
m_nActualSize = 0;
|
|
m_nPersistentSize = 0;
|
|
}
|
|
else
|
|
{
|
|
m_pDevTexture = NULL;
|
|
m_pDeviceRTV = NULL;
|
|
m_pDeviceShaderResource = NULL;
|
|
m_pDeviceShaderResourceSRGB = NULL;
|
|
}
|
|
m_bNoTexture = false;
|
|
}
|
|
|
|
void* CTexture::CreateDeviceResourceView(const SResourceView& rv)
|
|
{
|
|
const SPixFormat* pPixFormat = NULL;
|
|
if (ClosestFormatSupported((ETEX_Format)rv.m_Desc.nFormat, pPixFormat) == eTF_Unknown)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
HRESULT hr = E_FAIL;
|
|
void* pResult = NULL;
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_8
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
|
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#else
|
|
// DX expects -1 for selecting all mip maps/slices. max count throws an exception
|
|
const uint nSliceCount = rv.m_Desc.nSliceCount == SResourceView().m_Desc.nSliceCount ? (uint) - 1 : (uint)rv.m_Desc.nSliceCount;
|
|
#endif
|
|
|
|
if (!m_pDevTexture)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
D3DTexture* pTex = m_pDevTexture->Get2DTexture();
|
|
|
|
switch (rv.m_Desc.eViewType)
|
|
{
|
|
case SResourceView::eShaderResourceView:
|
|
{
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
|
SetShaderResourceViewDesc(rv, m_eTT, pPixFormat->DeviceFormat, m_nArraySize, nSliceCount, srvDesc);
|
|
if (rv.m_Desc.bMultisample && m_eTT == eTT_2D)
|
|
{
|
|
pTex = m_pRenderTargetData->m_pDeviceTextureMSAA->Get2DTexture();
|
|
}
|
|
D3DShaderResourceView* pSRV = NULL;
|
|
hr = gcpRendD3D->GetDevice().CreateShaderResourceView(pTex, &srvDesc, &pSRV);
|
|
pResult = pSRV;
|
|
|
|
#if defined(D3DTEXTURE_CPP_USE_PRIVATEDATA)
|
|
if (pSRV)
|
|
{
|
|
AZStd::string srvName = AZStd::string::format("[SRV] %s", m_SrcName.c_str());
|
|
pSRV->SetPrivateData(WKPDID_D3DDebugObjectName, srvName.length(), srvName.c_str());
|
|
}
|
|
#endif
|
|
|
|
}
|
|
break;
|
|
case SResourceView::eRenderTargetView:
|
|
{
|
|
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
|
|
SetRenderTargetViewDesc(rv, m_eTT, pPixFormat->DeviceFormat, m_nArraySize, nSliceCount, rtvDesc);
|
|
if (rv.m_Desc.bMultisample && m_eTT == eTT_2D)
|
|
{
|
|
pTex = m_pRenderTargetData->m_pDeviceTextureMSAA->Get2DTexture();
|
|
}
|
|
D3DSurface* pRTV = NULL;
|
|
hr = gcpRendD3D->GetDevice().CreateRenderTargetView(pTex, &rtvDesc, &pRTV);
|
|
pResult = pRTV;
|
|
|
|
#if defined(D3DTEXTURE_CPP_USE_PRIVATEDATA)
|
|
if (pRTV)
|
|
{
|
|
AZStd::string rtvName = AZStd::string::format("[RTV] %s", m_SrcName.c_str());
|
|
pRTV->SetPrivateData(WKPDID_D3DDebugObjectName, rtvName.length(), rtvName.c_str());
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
case SResourceView::eDepthStencilView:
|
|
{
|
|
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
|
|
SetDepthStencilViewDesc(rv, m_eTT, pPixFormat->DeviceFormat, m_nArraySize, nSliceCount, dsvDesc);
|
|
|
|
dsvDesc.Flags = rv.m_Desc.nFlags;
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_9
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
|
|
D3DDepthSurface* pDSV = NULL;
|
|
hr = gcpRendD3D->GetDevice().CreateDepthStencilView(pTex, &dsvDesc, &pDSV);
|
|
pResult = pDSV;
|
|
|
|
#if defined(D3DTEXTURE_CPP_USE_PRIVATEDATA)
|
|
if (pDSV)
|
|
{
|
|
AZStd::string dsvName = AZStd::string::format("[DSV] %s", m_SrcName.c_str());
|
|
pDSV->SetPrivateData(WKPDID_D3DDebugObjectName, dsvName.length(), dsvName.c_str());
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
case SResourceView::eUnorderedAccessView:
|
|
{
|
|
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
|
|
|
|
SetUnorderedAccessViewDesc(rv, m_eTT, pPixFormat->DeviceFormat, m_nArraySize, nSliceCount, uavDesc);
|
|
|
|
if (rv.m_Desc.nFlags & 0x1) // typed UAV loads are only allowed for single-component 32-bit element types
|
|
{
|
|
uavDesc.Format = DXGI_FORMAT_R32_UINT;
|
|
}
|
|
|
|
D3DUnorderedAccessView* pUAV = NULL;
|
|
hr = gcpRendD3D->GetDevice().CreateUnorderedAccessView(pTex, &uavDesc, &pUAV);
|
|
|
|
pResult = pUAV;
|
|
#if defined(D3DTEXTURE_CPP_USE_PRIVATEDATA)
|
|
if (pUAV)
|
|
{
|
|
AZStd::string uavName = AZStd::string::format("[UAV] %s", m_SrcName.c_str());
|
|
pUAV->SetPrivateData(WKPDID_D3DDebugObjectName, uavName.length(), uavName.c_str());
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
CRY_ASSERT(0);
|
|
return NULL;
|
|
}
|
|
|
|
return pResult;
|
|
}
|
|
|
|
void CTexture::SetTexStates()
|
|
{
|
|
STexState s;
|
|
|
|
const bool noMipFiltering = m_nMips <= 1 && !(m_nFlags & FT_FORCE_MIPS);
|
|
s.m_nMinFilter = FILTER_LINEAR;
|
|
s.m_nMagFilter = FILTER_LINEAR;
|
|
s.m_nMipFilter = noMipFiltering ? FILTER_NONE : FILTER_LINEAR;
|
|
|
|
const int addrMode = (m_nFlags & FT_STATE_CLAMP || m_eTT == eTT_Cube) ? TADDR_CLAMP : TADDR_WRAP;
|
|
s.SetClampMode(addrMode, addrMode, addrMode);
|
|
|
|
m_nDefState = (uint16)CTexture::GetTexState(s);
|
|
}
|
|
|
|
static uint32 sAddressMode(int nAddress)
|
|
{
|
|
IF (nAddress < 0, 0)
|
|
{
|
|
nAddress = TADDR_WRAP;
|
|
}
|
|
|
|
switch (nAddress)
|
|
{
|
|
case TADDR_WRAP:
|
|
return D3D11_TEXTURE_ADDRESS_WRAP;
|
|
case TADDR_CLAMP:
|
|
return D3D11_TEXTURE_ADDRESS_CLAMP;
|
|
case TADDR_BORDER:
|
|
return D3D11_TEXTURE_ADDRESS_BORDER;
|
|
case TADDR_MIRROR:
|
|
return D3D11_TEXTURE_ADDRESS_MIRROR;
|
|
default:
|
|
assert(0);
|
|
return D3D11_TEXTURE_ADDRESS_WRAP;
|
|
}
|
|
}
|
|
|
|
void STexState::SetComparisonFilter(bool bEnable)
|
|
{
|
|
if (m_pDeviceState)
|
|
{
|
|
D3DSamplerState* pSamp = (D3DSamplerState*)m_pDeviceState;
|
|
SAFE_RELEASE(pSamp);
|
|
m_pDeviceState = NULL;
|
|
}
|
|
m_bComparison = bEnable;
|
|
}
|
|
|
|
bool STexState::SetClampMode(int nAddressU, int nAddressV, int nAddressW)
|
|
{
|
|
if (m_pDeviceState)
|
|
{
|
|
D3DSamplerState* pSamp = (D3DSamplerState*)m_pDeviceState;
|
|
SAFE_RELEASE(pSamp);
|
|
m_pDeviceState = NULL;
|
|
}
|
|
|
|
m_nAddressU = sAddressMode(nAddressU);
|
|
m_nAddressV = sAddressMode(nAddressV);
|
|
m_nAddressW = sAddressMode(nAddressW);
|
|
return true;
|
|
}
|
|
|
|
bool STexState::SetFilterMode(int nFilter)
|
|
{
|
|
IF (nFilter < 0, 0)
|
|
{
|
|
nFilter = FILTER_TRILINEAR;
|
|
}
|
|
|
|
if (m_pDeviceState)
|
|
{
|
|
D3DSamplerState* pSamp = (D3DSamplerState*)m_pDeviceState;
|
|
SAFE_RELEASE(pSamp);
|
|
m_pDeviceState = NULL;
|
|
}
|
|
|
|
switch (nFilter)
|
|
{
|
|
case FILTER_POINT:
|
|
case FILTER_NONE:
|
|
m_nMinFilter = FILTER_POINT;
|
|
m_nMagFilter = FILTER_POINT;
|
|
m_nMipFilter = FILTER_NONE;
|
|
m_nAnisotropy = 1;
|
|
break;
|
|
case FILTER_LINEAR:
|
|
m_nMinFilter = FILTER_LINEAR;
|
|
m_nMagFilter = FILTER_LINEAR;
|
|
m_nMipFilter = FILTER_NONE;
|
|
m_nAnisotropy = 1;
|
|
break;
|
|
case FILTER_BILINEAR:
|
|
m_nMinFilter = FILTER_LINEAR;
|
|
m_nMagFilter = FILTER_LINEAR;
|
|
m_nMipFilter = FILTER_POINT;
|
|
m_nAnisotropy = 1;
|
|
break;
|
|
case FILTER_TRILINEAR:
|
|
m_nMinFilter = FILTER_LINEAR;
|
|
m_nMagFilter = FILTER_LINEAR;
|
|
m_nMipFilter = FILTER_LINEAR;
|
|
m_nAnisotropy = 1;
|
|
break;
|
|
case FILTER_ANISO2X:
|
|
case FILTER_ANISO4X:
|
|
case FILTER_ANISO8X:
|
|
case FILTER_ANISO16X:
|
|
m_nMinFilter = nFilter;
|
|
m_nMagFilter = nFilter;
|
|
m_nMipFilter = nFilter;
|
|
if (nFilter == FILTER_ANISO2X)
|
|
{
|
|
m_nAnisotropy = min(gcpRendD3D->m_MaxAnisotropyLevel, 2);
|
|
}
|
|
else
|
|
if (nFilter == FILTER_ANISO4X)
|
|
{
|
|
m_nAnisotropy = min(gcpRendD3D->m_MaxAnisotropyLevel, 4);
|
|
}
|
|
else
|
|
if (nFilter == FILTER_ANISO8X)
|
|
{
|
|
m_nAnisotropy = min(gcpRendD3D->m_MaxAnisotropyLevel, 8);
|
|
}
|
|
else
|
|
if (nFilter == FILTER_ANISO16X)
|
|
{
|
|
m_nAnisotropy = min(gcpRendD3D->m_MaxAnisotropyLevel, 16);
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void STexState::SetBorderColor(DWORD dwColor)
|
|
{
|
|
if (m_pDeviceState)
|
|
{
|
|
D3DSamplerState* pSamp = (D3DSamplerState*)m_pDeviceState;
|
|
SAFE_RELEASE(pSamp);
|
|
m_pDeviceState = NULL;
|
|
}
|
|
|
|
m_dwBorderColor = dwColor;
|
|
}
|
|
|
|
void STexState::PostCreate()
|
|
{
|
|
if (m_pDeviceState)
|
|
{
|
|
return;
|
|
}
|
|
|
|
D3D11_SAMPLER_DESC Desc;
|
|
ZeroStruct(Desc);
|
|
D3DSamplerState* pSamp = NULL;
|
|
// AddressMode of 0 is INVALIDARG
|
|
Desc.AddressU = m_nAddressU ? (D3D11_TEXTURE_ADDRESS_MODE)m_nAddressU : D3D11_TEXTURE_ADDRESS_WRAP;
|
|
Desc.AddressV = m_nAddressV ? (D3D11_TEXTURE_ADDRESS_MODE)m_nAddressV : D3D11_TEXTURE_ADDRESS_WRAP;
|
|
Desc.AddressW = m_nAddressW ? (D3D11_TEXTURE_ADDRESS_MODE)m_nAddressW : D3D11_TEXTURE_ADDRESS_WRAP;
|
|
ColorF col((uint32)m_dwBorderColor);
|
|
Desc.BorderColor[0] = col.r;
|
|
Desc.BorderColor[1] = col.g;
|
|
Desc.BorderColor[2] = col.b;
|
|
Desc.BorderColor[3] = col.a;
|
|
if (m_bComparison)
|
|
{
|
|
Desc.ComparisonFunc = D3D11_COMPARISON_LESS;
|
|
}
|
|
else
|
|
{
|
|
Desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
|
}
|
|
|
|
Desc.MaxAnisotropy = 1;
|
|
Desc.MinLOD = 0;
|
|
if (m_nMipFilter == FILTER_NONE)
|
|
{
|
|
Desc.MaxLOD = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
Desc.MaxLOD = 100.0f;
|
|
}
|
|
|
|
Desc.MipLODBias = m_MipBias;
|
|
|
|
if (m_bComparison)
|
|
{
|
|
if (m_nMinFilter == FILTER_LINEAR && m_nMagFilter == FILTER_LINEAR && m_nMipFilter == FILTER_LINEAR || m_nMinFilter == FILTER_TRILINEAR || m_nMagFilter == FILTER_TRILINEAR)
|
|
{
|
|
Desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
|
|
}
|
|
else
|
|
if (m_nMinFilter == FILTER_LINEAR && m_nMagFilter == FILTER_LINEAR && (m_nMipFilter == FILTER_NONE || m_nMipFilter == FILTER_POINT) || m_nMinFilter == FILTER_BILINEAR || m_nMagFilter == FILTER_BILINEAR)
|
|
{
|
|
Desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
|
|
}
|
|
else
|
|
if (m_nMinFilter == FILTER_POINT && m_nMagFilter == FILTER_POINT && (m_nMipFilter == FILTER_NONE || m_nMipFilter == FILTER_POINT))
|
|
{
|
|
Desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
|
|
}
|
|
else
|
|
if (m_nMinFilter >= FILTER_ANISO2X && m_nMagFilter >= FILTER_ANISO2X && m_nMipFilter >= FILTER_ANISO2X)
|
|
{
|
|
Desc.Filter = D3D11_FILTER_COMPARISON_ANISOTROPIC;
|
|
Desc.MaxAnisotropy = m_nAnisotropy;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_nMinFilter == FILTER_LINEAR && m_nMagFilter == FILTER_LINEAR && m_nMipFilter == FILTER_LINEAR || m_nMinFilter == FILTER_TRILINEAR || m_nMagFilter == FILTER_TRILINEAR)
|
|
{
|
|
Desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
|
}
|
|
else
|
|
if (m_nMinFilter == FILTER_LINEAR && m_nMagFilter == FILTER_LINEAR && (m_nMipFilter == FILTER_NONE || m_nMipFilter == FILTER_POINT) || m_nMinFilter == FILTER_BILINEAR || m_nMagFilter == FILTER_BILINEAR)
|
|
{
|
|
Desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
|
}
|
|
else
|
|
if (m_nMinFilter == FILTER_POINT && m_nMagFilter == FILTER_POINT && (m_nMipFilter == FILTER_NONE || m_nMipFilter == FILTER_POINT))
|
|
{
|
|
Desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
|
}
|
|
else
|
|
if (m_nMinFilter >= FILTER_ANISO2X && m_nMagFilter >= FILTER_ANISO2X && m_nMipFilter >= FILTER_ANISO2X)
|
|
{
|
|
Desc.Filter = D3D11_FILTER_ANISOTROPIC;
|
|
Desc.MaxAnisotropy = m_nAnisotropy;
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
HRESULT hr = gcpRendD3D->GetDevice().CreateSamplerState(&Desc, &pSamp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_pDeviceState = pSamp;
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
void STexState::Destroy()
|
|
{
|
|
if (m_pDeviceState)
|
|
{
|
|
D3DSamplerState* pSamp = (D3DSamplerState*)m_pDeviceState;
|
|
SAFE_RELEASE(pSamp);
|
|
m_pDeviceState = NULL;
|
|
}
|
|
}
|
|
|
|
void STexState::Init(const STexState& src)
|
|
{
|
|
memcpy(this, &src, sizeof(src));
|
|
if (m_pDeviceState)
|
|
{
|
|
D3DSamplerState* pSamp = (D3DSamplerState*)m_pDeviceState;
|
|
pSamp->AddRef();
|
|
}
|
|
}
|
|
|
|
bool CTexture::SetClampingMode(int nAddressU, int nAddressV, int nAddressW)
|
|
{
|
|
return s_sDefState.SetClampMode(nAddressU, nAddressV, nAddressW);
|
|
}
|
|
|
|
bool CTexture::SetFilterMode(int nFilter)
|
|
{
|
|
return s_sDefState.SetFilterMode(nFilter);
|
|
}
|
|
|
|
void CTexture::UpdateTexStates()
|
|
{
|
|
m_nDefState = (uint16)CTexture::GetTexState(s_sDefState);
|
|
}
|
|
|
|
void CTexture::SetSamplerState(int nTS, int nSUnit, EHWShaderClass eHWSC)
|
|
{
|
|
FUNCTION_PROFILER_RENDER_FLAT
|
|
assert(gcpRendD3D->m_pRT->IsRenderThread());
|
|
STexStageInfo* const __restrict TexStages = s_TexStages;
|
|
|
|
STexState* pTS = &s_TexStates[nTS];
|
|
D3DSamplerState* pSamp = (D3DSamplerState*)pTS->m_pDeviceState;
|
|
|
|
assert(pSamp);
|
|
|
|
if (pSamp)
|
|
{
|
|
if (eHWSC == eHWSC_Pixel)
|
|
{
|
|
gcpRendD3D->m_DevMan.BindSampler(eHWSC_Pixel, &pSamp, nSUnit, 1);
|
|
}
|
|
else
|
|
if (eHWSC == eHWSC_Domain)
|
|
{
|
|
gcpRendD3D->m_DevMan.BindSampler(eHWSC_Domain, &pSamp, nSUnit, 1);
|
|
}
|
|
else
|
|
if (eHWSC == eHWSC_Vertex)
|
|
{
|
|
gcpRendD3D->m_DevMan.BindSampler(eHWSC_Vertex, &pSamp, nSUnit, 1);
|
|
}
|
|
else
|
|
if (eHWSC == eHWSC_Compute)
|
|
{
|
|
gcpRendD3D->m_DevMan.BindSampler(eHWSC_Compute, &pSamp, nSUnit, 1);
|
|
}
|
|
else
|
|
if (eHWSC == eHWSC_Geometry)
|
|
{
|
|
gcpRendD3D->m_DevMan.BindSampler(eHWSC_Geometry, &pSamp, nSUnit, 1);
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTexture::ApplySamplerState(int nSUnit, EHWShaderClass eHWSC, int nState)
|
|
{
|
|
FUNCTION_PROFILER_RENDER_FLAT
|
|
|
|
uint32 nTSSel = Isel32(nState, (int32)m_nDefState);
|
|
assert(nTSSel >= 0 && nTSSel < s_TexStates.size());
|
|
|
|
STexStageInfo *TexStages = s_TexStages;
|
|
CDeviceTexture* pDevTex = m_pDevTexture;
|
|
|
|
// avoiding L2 cache misses from usage from up ahead
|
|
PrefetchLine(pDevTex, 0);
|
|
|
|
assert(nSUnit >= 0 && nSUnit < 16);
|
|
assert((nSUnit >= 0 || nSUnit == -2) && nSUnit < gcpRendD3D->m_NumSamplerSlots);
|
|
|
|
CD3D9Renderer *const __restrict rd = gcpRendD3D;
|
|
const int nFrameID = rd->m_RP.m_TI[rd->m_RP.m_nProcessThreadID].m_nFrameUpdateID;
|
|
|
|
if (IsVertexTexture())
|
|
eHWSC = eHWSC_Vertex;
|
|
|
|
SetSamplerState(nTSSel, nSUnit, eHWSC);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Given a texture and a binding slot, this is the method that actually refreshes
|
|
// the texture resource, validates it and finally binds it to the HW stage.
|
|
void CTexture::ApplyTexture(int nTUnit, EHWShaderClass eHWSC, SResourceView::KeyType nResViewKey)
|
|
{
|
|
FUNCTION_PROFILER_RENDER_FLAT
|
|
|
|
STexStageInfo *TexStages = s_TexStages;
|
|
CDeviceTexture* pDevTex = m_pDevTexture;
|
|
|
|
// avoiding L2 cache misses from usage from up ahead
|
|
PrefetchLine(pDevTex, 0);
|
|
|
|
assert(nTUnit >= 0 && nTUnit < gcpRendD3D->m_NumResourceSlots);
|
|
|
|
CD3D9Renderer *const __restrict rd = gcpRendD3D;
|
|
const int nFrameID = rd->m_RP.m_TI[rd->m_RP.m_nProcessThreadID].m_nFrameUpdateID;
|
|
|
|
if (IsStreamed() && !m_bPostponed)
|
|
{
|
|
bool bIsUnloaded = IsUnloaded();
|
|
|
|
assert(m_pFileTexMips);
|
|
if (bIsUnloaded || !m_bStreamPrepared || IsPartiallyLoaded())
|
|
{
|
|
PROFILE_FRAME(Texture_Precache);
|
|
if (!CRenderer::CV_r_texturesstreaming || !m_bStreamPrepared || bIsUnloaded)
|
|
{
|
|
if (bIsUnloaded)
|
|
StreamLoadFromCache(0);
|
|
else
|
|
Load(m_eTFDst);
|
|
|
|
pDevTex = m_pDevTexture;
|
|
}
|
|
}
|
|
}
|
|
|
|
IF(this != CTexture::s_pTexNULL && (!pDevTex || !pDevTex->GetBaseTexture()), 0)
|
|
{
|
|
// apply black by default
|
|
CTexture* pBlackTexture = CTextureManager::Instance()->GetBlackTexture();
|
|
if (m_eTT != eTT_Cube && pBlackTexture)
|
|
{
|
|
pBlackTexture->ApplyTexture(nTUnit, eHWSC, nResViewKey);
|
|
}
|
|
else
|
|
{
|
|
pBlackTexture = CTextureManager::Instance()->GetBlackTextureCM();
|
|
if (m_eTT == eTT_Cube && pBlackTexture)
|
|
{
|
|
pBlackTexture->ApplyTexture(nTUnit, eHWSC, nResViewKey);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Resolve multisampled RT to texture
|
|
if (!m_bResolved)
|
|
{
|
|
Resolve();
|
|
}
|
|
|
|
bool bStreamed = IsStreamed();
|
|
if (m_nAccessFrameID != nFrameID)
|
|
{
|
|
m_nAccessFrameID = nFrameID;
|
|
|
|
#if !defined(_RELEASE)
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_NumTextures++;
|
|
if (m_nFlags & (FT_USAGE_RENDERTARGET | FT_USAGE_DYNAMIC))
|
|
{
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_DynTexturesSize += m_nActualSize;
|
|
}
|
|
else
|
|
{
|
|
if (bStreamed)
|
|
{
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_ManagedTexturesStreamVidSize += m_nActualSize;
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_ManagedTexturesStreamSysSize += StreamComputeDevDataSize(0);
|
|
}
|
|
else
|
|
{
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_ManagedTexturesSysMemSize += m_nActualSize;
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_ManagedTexturesVidMemSize += m_nActualSize;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// mip map fade in
|
|
if (bStreamed)
|
|
{
|
|
const float fCurrentMipBias = m_fCurrentMipBias;
|
|
if (fabsf(fCurrentMipBias) > 0.26667f)
|
|
{
|
|
// one mip per half a second
|
|
m_fCurrentMipBias -= 0.26667f * fCurrentMipBias;
|
|
|
|
gcpRendD3D->GetDeviceContext().SetResourceMinLOD(pDevTex->Get2DTexture(), m_fCurrentMipBias + (float)m_nMinMipVidUploaded);
|
|
}
|
|
else if (fCurrentMipBias != 0.f)
|
|
{
|
|
m_fCurrentMipBias = 0.f;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IsVertexTexture())
|
|
eHWSC = eHWSC_Vertex;
|
|
|
|
const bool bUnnorderedAcessView = SResourceView(nResViewKey).m_Desc.eViewType == SResourceView::eUnorderedAccessView;
|
|
|
|
D3DShaderResourceView* pResView = GetShaderResourceView(nResViewKey);
|
|
|
|
if (pDevTex == TexStages[nTUnit].m_DevTexture && pResView == TexStages[nTUnit].m_pCurResView && eHWSC == TexStages[nTUnit].m_eHWSC)
|
|
return;
|
|
|
|
TexStages[nTUnit].m_pCurResView = pResView;
|
|
TexStages[nTUnit].m_eHWSC = eHWSC;
|
|
|
|
// <DEPRECATED> This must get re-factored post C3.
|
|
// This check is ultra-buggy, render targets setup is deferred until last moment might not be matching this check at all. Also very wrong for MRTs
|
|
|
|
if (rd->m_pCurTarget[0] == this)
|
|
{
|
|
//assert(rd->m_pCurTarget[0]->m_pDeviceRTV);
|
|
rd->m_pNewTarget[0]->m_bWasSetRT = false;
|
|
rd->GetDeviceContext().OMSetRenderTargets(1, &rd->m_pNewTarget[0]->m_pTarget, rd->m_pNewTarget[0]->m_pDepth);
|
|
}
|
|
|
|
TexStages[nTUnit].m_DevTexture = pDevTex;
|
|
|
|
#if !defined(_RELEASE)
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_NumTextChanges++;
|
|
#endif
|
|
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log >= 3)
|
|
{
|
|
if (IsNoTexture())
|
|
{
|
|
rd->Logv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "CTexture::Apply(): (%d) \"%s\" (Not found)\n", nTUnit, m_SrcName.c_str());
|
|
}
|
|
else
|
|
{
|
|
rd->Logv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "CTexture::Apply(): (%d) \"%s\"\n", nTUnit, m_SrcName.c_str());
|
|
}
|
|
}
|
|
#endif
|
|
|
|
{
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log >= 3 && int64(nResViewKey) >= 0)
|
|
{
|
|
rd->Logv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "CTexture::Apply(): Shader Resource View: %ul \n", nResViewKey);
|
|
}
|
|
#endif
|
|
|
|
if (bUnnorderedAcessView)
|
|
{
|
|
// todo:
|
|
// - add support for pixel shader side via OMSetRenderTargetsAndUnorderedAccessViews
|
|
// - DX11.1 very likely API will be similar to CSSetUnorderedAccessViews, but for all stages
|
|
D3DUnorderedAccessView *pUAV = (D3DUnorderedAccessView*)pResView;
|
|
rd->GetDeviceContext().CSSetUnorderedAccessViews(nTUnit, 1, &pUAV, NULL);
|
|
return;
|
|
}
|
|
|
|
{
|
|
if (IsVertexTexture())
|
|
eHWSC = eHWSC_Vertex;
|
|
|
|
if (eHWSC == eHWSC_Pixel)
|
|
{
|
|
rd->m_DevMan.BindSRV(eHWSC_Pixel, pResView, nTUnit);
|
|
}
|
|
else if (eHWSC == eHWSC_Vertex)
|
|
{
|
|
rd->m_DevMan.BindSRV(eHWSC_Vertex, pResView, nTUnit);
|
|
}
|
|
else if (eHWSC == eHWSC_Domain)
|
|
{
|
|
rd->m_DevMan.BindSRV(eHWSC_Domain, pResView, nTUnit);
|
|
}
|
|
else if (eHWSC == eHWSC_Compute)
|
|
{
|
|
rd->m_DevMan.BindSRV(eHWSC_Compute, pResView, nTUnit);
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTexture::Apply(int nTUnit, int nState, int nTexMatSlot, int nSUnit, SResourceView::KeyType nResViewKey, EHWShaderClass eHWSC)
|
|
{
|
|
FUNCTION_PROFILER_RENDER_FLAT
|
|
assert(nTUnit >= 0);
|
|
|
|
uint32 nTSSel = Isel32(nState, (int32)m_nDefState);
|
|
assert(nTSSel >= 0 && nTSSel < s_TexStates.size());
|
|
|
|
#if defined(OPENGL)
|
|
// Due to driver issues on MALI gpus only point filtering is allowed for 32 bit float textures.
|
|
// If another filtering is used the sampler returns black.
|
|
if ((gcpRendD3D->m_Features | RFT_HW_ARM_MALI) &&
|
|
(m_eTFDst == eTF_R32F || m_eTFDst == eTF_R32G32B32A32F) &&
|
|
(s_TexStates[nTSSel].m_nMagFilter != FILTER_POINT || s_TexStates[nTSSel].m_nMinFilter != FILTER_POINT))
|
|
{
|
|
STexState newState = s_TexStates[nTSSel];
|
|
newState.SetFilterMode(FILTER_POINT);
|
|
nTSSel = CTexture::GetTexState(newState);
|
|
AZ_WarningOnce("Texture", false, "The current device only supports point filtering for full float textures. Forcing filtering for texture in slot %d", nTUnit);
|
|
}
|
|
#endif // defined(OPENGL)
|
|
|
|
STexStageInfo* TexStages = s_TexStages;
|
|
|
|
CDeviceTexture* pDevTex = m_pDevTexture;
|
|
|
|
// avoiding L2 cache misses from usage from up ahead
|
|
PrefetchLine(pDevTex, 0);
|
|
|
|
if (nSUnit >= -1)
|
|
{
|
|
nSUnit = Isel32(nSUnit, nTUnit);
|
|
}
|
|
|
|
assert(nTUnit >= 0 && nTUnit < gcpRendD3D->m_NumResourceSlots);
|
|
assert((nSUnit >= 0 || nSUnit == -2) && nSUnit < gcpRendD3D->m_NumSamplerSlots);
|
|
|
|
CD3D9Renderer* const __restrict rd = gcpRendD3D;
|
|
const int nFrameID = rd->m_RP.m_TI[rd->m_RP.m_nProcessThreadID].m_nFrameUpdateID;
|
|
|
|
if (IsStreamed() && !m_bPostponed)
|
|
{
|
|
bool bIsUnloaded = IsUnloaded();
|
|
|
|
assert(m_pFileTexMips);
|
|
if (bIsUnloaded || !m_bStreamPrepared || IsPartiallyLoaded())
|
|
{
|
|
PROFILE_FRAME(Texture_Precache);
|
|
if (!CRenderer::CV_r_texturesstreaming || !m_bStreamPrepared || bIsUnloaded)
|
|
{
|
|
if (bIsUnloaded)
|
|
{
|
|
StreamLoadFromCache(0);
|
|
}
|
|
else
|
|
{
|
|
Load(m_eTFDst);
|
|
}
|
|
|
|
pDevTex = m_pDevTexture;
|
|
}
|
|
}
|
|
|
|
if (nTexMatSlot != EFTT_UNKNOWN)
|
|
{
|
|
m_nStreamingPriority = max((int8)m_nStreamingPriority, TextureHelpers::LookupTexPriority((EEfResTextures)nTexMatSlot));
|
|
}
|
|
}
|
|
|
|
IF (this != CTexture::s_pTexNULL && (!pDevTex || !pDevTex->GetBaseTexture()), 0)
|
|
{
|
|
// apply black by default
|
|
if (m_eTT != eTT_Cube && CTextureManager::Instance()->GetBlackTexture() && this != CTextureManager::Instance()->GetBlackTexture())
|
|
{
|
|
CTextureManager::Instance()->GetBlackTexture()->Apply(nTUnit, nState, nTexMatSlot, nSUnit, nResViewKey);
|
|
}
|
|
else if (m_eTT == eTT_Cube && CTextureManager::Instance()->GetBlackTextureCM() && this != CTextureManager::Instance()->GetBlackTextureCM())
|
|
{
|
|
CTextureManager::Instance()->GetBlackTextureCM()->Apply(nTUnit, nState, nTexMatSlot, nSUnit, nResViewKey);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Resolve multisampled RT to texture
|
|
if (!m_bResolved)
|
|
{
|
|
Resolve();
|
|
}
|
|
bool bStreamed = IsStreamed();
|
|
if (m_nAccessFrameID != nFrameID)
|
|
{
|
|
m_nAccessFrameID = nFrameID;
|
|
|
|
#if !defined(_RELEASE)
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_NumTextures++;
|
|
if (m_nFlags & (FT_USAGE_RENDERTARGET | FT_USAGE_DYNAMIC))
|
|
{
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_DynTexturesSize += m_nActualSize;
|
|
}
|
|
else
|
|
{
|
|
if (bStreamed)
|
|
{
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_ManagedTexturesStreamVidSize += m_nActualSize;
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_ManagedTexturesStreamSysSize += StreamComputeDevDataSize(0);
|
|
}
|
|
else
|
|
{
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_ManagedTexturesSysMemSize += m_nActualSize;
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_ManagedTexturesVidMemSize += m_nActualSize;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// mip map fade in
|
|
if (bStreamed)
|
|
{
|
|
const float fCurrentMipBias = m_fCurrentMipBias;
|
|
if (fabsf(fCurrentMipBias) > 0.26667f)
|
|
{
|
|
// one mip per half a second
|
|
m_fCurrentMipBias -= 0.26667f * fCurrentMipBias;
|
|
#if defined(CRY_USE_METAL)
|
|
//For metal, the lodminclamp is set once at initialization for the mtlsamplerstate. The mtlSamplerDescriptor's properties
|
|
//are only used during mtlSamplerState object creation; once created the behaviour of a sampler state object is
|
|
//fixed and cannot be changed. Hence we modify the descriptor with minlod and recreate the sampler state.
|
|
STexState* pTS = &s_TexStates[nTSSel];
|
|
D3DSamplerState* pSamp = (D3DSamplerState*)pTS->m_pDeviceState;
|
|
pSamp->SetLodMinClamp(m_fCurrentMipBias + static_cast<float>(m_nMinMipVidUploaded));
|
|
#else
|
|
gcpRendD3D->GetDeviceContext().SetResourceMinLOD(pDevTex->Get2DTexture(), m_fCurrentMipBias + static_cast<float>(m_nMinMipVidUploaded));
|
|
#endif
|
|
}
|
|
else if (fCurrentMipBias != 0.f)
|
|
{
|
|
m_fCurrentMipBias = 0.f;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IsVertexTexture())
|
|
{
|
|
eHWSC = eHWSC_Vertex;
|
|
}
|
|
|
|
const bool bUnnorderedAcessView = SResourceView(nResViewKey).m_Desc.eViewType == SResourceView::eUnorderedAccessView;
|
|
if (!bUnnorderedAcessView && nSUnit >= 0)
|
|
{
|
|
SetSamplerState(nTSSel, nSUnit, eHWSC);
|
|
}
|
|
|
|
D3DShaderResourceView* pResView = GetShaderResourceView(nResViewKey, s_TexStates[nTSSel].m_bSRGBLookup);
|
|
|
|
if (pDevTex == TexStages[nTUnit].m_DevTexture && pResView == TexStages[nTUnit].m_pCurResView && eHWSC == TexStages[nTUnit].m_eHWSC)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TexStages[nTUnit].m_pCurResView = pResView;
|
|
TexStages[nTUnit].m_eHWSC = eHWSC;
|
|
// <DEPRECATED> This must get re-factored post C3.
|
|
// - This check is ultra-buggy, render targets setup is deferred until last moment might not be matching this check at all. Also very wrong for MRTs
|
|
|
|
if (rd->m_pCurTarget[0] == this)
|
|
{
|
|
//assert(rd->m_pCurTarget[0]->m_pDeviceRTV);
|
|
rd->m_pNewTarget[0]->m_bWasSetRT = false;
|
|
rd->GetDeviceContext().OMSetRenderTargets(1, &rd->m_pNewTarget[0]->m_pTarget, rd->m_pNewTarget[0]->m_pDepth);
|
|
}
|
|
|
|
TexStages[nTUnit].m_DevTexture = pDevTex;
|
|
|
|
#if !defined(_RELEASE)
|
|
rd->m_RP.m_PS[rd->m_RP.m_nProcessThreadID].m_NumTextChanges++;
|
|
#endif
|
|
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log >= 3)
|
|
{
|
|
if (IsNoTexture())
|
|
{
|
|
rd->Logv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "CTexture::Apply(): (%d) \"%s\" (Not found)\n", nTUnit, m_SrcName.c_str());
|
|
}
|
|
else
|
|
{
|
|
rd->Logv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "CTexture::Apply(): (%d) \"%s\"\n", nTUnit, m_SrcName.c_str());
|
|
}
|
|
}
|
|
#endif
|
|
|
|
{
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log >= 3 && int64(nResViewKey) >= 0)
|
|
{
|
|
rd->Logv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "CTexture::Apply(): Shader Resource View: %ul \n", nResViewKey);
|
|
}
|
|
#endif
|
|
|
|
if (bUnnorderedAcessView)
|
|
{
|
|
// todo:
|
|
// - add support for pixel shader side via OMSetRenderTargetsAndUnorderedAccessViews
|
|
// - DX11.1 very likely API will be similar to CSSetUnorderedAccessViews, but for all stages
|
|
D3DUnorderedAccessView* pUAV = (D3DUnorderedAccessView*)pResView;
|
|
rd->GetDeviceContext().CSSetUnorderedAccessViews(nTUnit, 1, &pUAV, NULL);
|
|
return;
|
|
}
|
|
|
|
{
|
|
if (IsVertexTexture())
|
|
{
|
|
eHWSC = eHWSC_Vertex;
|
|
}
|
|
|
|
if (eHWSC == eHWSC_Pixel)
|
|
{
|
|
rd->m_DevMan.BindSRV(eHWSC_Pixel, pResView, nTUnit);
|
|
}
|
|
else
|
|
if (eHWSC == eHWSC_Vertex)
|
|
{
|
|
rd->m_DevMan.BindSRV(eHWSC_Vertex, pResView, nTUnit);
|
|
}
|
|
else
|
|
if (eHWSC == eHWSC_Domain)
|
|
{
|
|
rd->m_DevMan.BindSRV(eHWSC_Domain, pResView, nTUnit);
|
|
}
|
|
else
|
|
if (eHWSC == eHWSC_Compute)
|
|
{
|
|
rd->m_DevMan.BindSRV(eHWSC_Compute, pResView, nTUnit);
|
|
}
|
|
else
|
|
if (eHWSC == eHWSC_Geometry)
|
|
{
|
|
rd->m_DevMan.BindSRV(eHWSC_Geometry, pResView, nTUnit);
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTexture::UpdateTextureRegion(const uint8_t* data, int nX, int nY, int nZ, int USize, int VSize, int ZSize, ETEX_Format eTFSrc)
|
|
{
|
|
gRenDev->m_pRT->RC_UpdateTextureRegion(this, data, nX, nY, nZ, USize, VSize, ZSize, eTFSrc);
|
|
}
|
|
|
|
void CTexture::RT_UpdateTextureRegion(const byte* data, int nX, int nY, int nZ, int USize, int VSize, int ZSize, ETEX_Format eTFSrc)
|
|
{
|
|
PROFILE_FRAME(UpdateTextureRegion);
|
|
|
|
if (m_eTT != eTT_2D && m_eTT != eTT_3D)
|
|
{
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
CDeviceTexture* pDevTexture = GetDevTexture();
|
|
assert(pDevTexture);
|
|
if (!pDevTexture)
|
|
{
|
|
return;
|
|
}
|
|
|
|
DXGI_FORMAT frmtSrc = (DXGI_FORMAT)CTexture::DeviceFormatFromTexFormat(eTFSrc);
|
|
bool bDone = false;
|
|
D3D11_BOX rc = {aznumeric_caster(nX), aznumeric_caster(nY), 0, aznumeric_caster(nX + USize), aznumeric_caster(nY + VSize), 1};
|
|
if (m_eTT == eTT_2D)
|
|
{
|
|
if (GetBlockDim(m_eTFDst) == Vec2i(1))
|
|
{
|
|
int nBPPSrc = CTexture::BytesPerBlock(eTFSrc);
|
|
int nBPPDst = CTexture::BytesPerBlock(m_eTFDst);
|
|
if (nBPPSrc == nBPPDst)
|
|
{
|
|
int nRowPitch = CTexture::TextureDataSize(USize, 1, 1, 1, 1, eTFSrc);
|
|
const int nSlicePitch = CTexture::TextureDataSize(USize, VSize, 1, 1, 1, eTFSrc);
|
|
gcpRendD3D->GetDeviceContext().UpdateSubresource(pDevTexture->Get2DTexture(), 0, &rc, data, nRowPitch, nSlicePitch);
|
|
bDone = true;
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
bDone = true;
|
|
}
|
|
}
|
|
}
|
|
else if (m_eTT == eTT_3D)
|
|
{
|
|
int nFrame = gRenDev->m_nFrameSwapID;
|
|
rc.front = nZ;
|
|
rc.back = nZ + ZSize;
|
|
|
|
int nBPPSrc = CTexture::BytesPerBlock(eTFSrc);
|
|
int nBPPDst = CTexture::BytesPerBlock(m_eTFDst);
|
|
if (nBPPSrc == nBPPDst)
|
|
{
|
|
if (m_nFlags & FT_USAGE_DYNAMIC)
|
|
{
|
|
D3DVolumeTexture* pDT = pDevTexture->GetVolumeTexture();
|
|
int cZ, cY;
|
|
for (cZ = nZ; cZ < ZSize; cZ++)
|
|
{
|
|
D3D11_MAPPED_SUBRESOURCE lrct;
|
|
uint32 nLockFlags = D3D11_MAP_WRITE_DISCARD;
|
|
uint32 nSubRes = D3D11CalcSubresource(0, cZ, 1);
|
|
|
|
hr = gcpRendD3D->GetDeviceContext().Map(pDT, nSubRes, (D3D11_MAP)nLockFlags, 0, &lrct);
|
|
assert(hr == S_OK);
|
|
|
|
byte* pDst = ((byte*)lrct.pData) + nX * 4 + nY * lrct.RowPitch;
|
|
for (cY = 0; cY < VSize; cY++)
|
|
{
|
|
cryMemcpy(pDst, data, USize * 4);
|
|
data += USize * 4;
|
|
pDst += lrct.RowPitch;
|
|
}
|
|
gcpRendD3D->GetDeviceContext().Unmap(pDT, nSubRes);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int U = USize;
|
|
int V = VSize;
|
|
int Z = ZSize;
|
|
for (int i = 0; i < m_nMips; i++)
|
|
{
|
|
if (!U)
|
|
{
|
|
U = 1;
|
|
}
|
|
if (!V)
|
|
{
|
|
V = 1;
|
|
}
|
|
if (!Z)
|
|
{
|
|
Z = 1;
|
|
}
|
|
|
|
int nRowPitch = CTexture::TextureDataSize(U, 1, 1, 1, 1, eTFSrc);
|
|
int nDepthPitch = m_eTT == eTT_3D ? CTexture::TextureDataSize(U, V, 1, 1, 1, eTFSrc) : 0;
|
|
|
|
gcpRendD3D->GetDeviceContext().UpdateSubresource(pDevTexture->GetBaseTexture(), i, &rc, data, nRowPitch, nDepthPitch);
|
|
bDone = true;
|
|
|
|
data += nDepthPitch * Z;
|
|
|
|
U >>= 1;
|
|
V >>= 1;
|
|
Z >>= 1;
|
|
|
|
rc.front >>= 1;
|
|
rc.left >>= 1;
|
|
rc.top >>= 1;
|
|
|
|
rc.back = max(rc.front + 1, rc.back >> 1);
|
|
rc.right = max(rc.left + 4, rc.right >> 1);
|
|
rc.bottom = max(rc.top + 4, rc.bottom >> 1);
|
|
}
|
|
}
|
|
}
|
|
else if ((eTFSrc == eTF_B8G8R8A8 || eTFSrc == eTF_B8G8R8X8) && (m_eTFDst == eTF_B5G6R5))
|
|
{
|
|
assert(0);
|
|
bDone = true;
|
|
}
|
|
}
|
|
|
|
if (!bDone)
|
|
{
|
|
D3D11_BOX box;
|
|
ZeroStruct(box);
|
|
box.right = USize;
|
|
box.bottom = VSize;
|
|
box.back = 1;
|
|
const int nPitch = CTexture::TextureDataSize(USize, 1, 1, 1, 1, eTFSrc);
|
|
const int nSlicePitch = CTexture::TextureDataSize(USize, VSize, 1, 1, 1, eTFSrc);
|
|
gcpRendD3D->GetDeviceContext().UpdateSubresource(pDevTexture->Get2DTexture(), 0, &box, data, nPitch, nSlicePitch);
|
|
}
|
|
}
|
|
|
|
bool CTexture::Clear()
|
|
{
|
|
if (!(m_nFlags & FT_USAGE_RENDERTARGET))
|
|
return false;
|
|
|
|
gRenDev->m_pRT->RC_ClearTarget(this, m_cClearColor);
|
|
return true;
|
|
}
|
|
|
|
bool CTexture::Clear(const ColorF& color)
|
|
{
|
|
if (!(m_nFlags & FT_USAGE_RENDERTARGET))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
gRenDev->m_pRT->RC_ClearTarget(this, color);
|
|
return true;
|
|
}
|
|
|
|
void SEnvTexture::Release()
|
|
{
|
|
ReleaseDeviceObjects();
|
|
SAFE_DELETE(m_pTex);
|
|
}
|
|
|
|
void SEnvTexture::RT_SetMatrix()
|
|
{
|
|
Matrix44A matView, matProj;
|
|
gRenDev->GetModelViewMatrix(matView.GetData());
|
|
gRenDev->GetProjectionMatrix(matProj.GetData());
|
|
|
|
float fWidth = m_pTex ? (float)m_pTex->GetWidth() : 1;
|
|
float fHeight = m_pTex ? (float)m_pTex->GetHeight() : 1;
|
|
|
|
Matrix44A matScaleBias(0.5f, 0, 0, 0,
|
|
0, -0.5f, 0, 0,
|
|
0, 0, 0.5f, 0,
|
|
// texel alignment - also push up y axis reflection up a bit
|
|
0.5f + 0.5f / fWidth, 0.5f + 1.0f / fHeight, 0.5f, 1.0f);
|
|
|
|
Matrix44A m = matProj * matScaleBias;
|
|
Matrix44A mm = matView * m;
|
|
m_Matrix = mm;
|
|
}
|
|
|
|
void SEnvTexture::ReleaseDeviceObjects()
|
|
{
|
|
//if (m_pTex)
|
|
// m_pTex->ReleaseDynamicRT(true);
|
|
}
|
|
|
|
#if AZ_RENDER_TO_TEXTURE_GEM_ENABLED
|
|
bool CTexture::RenderToTexture(int handle, const CCamera& camera, AzRTT::RenderContextId contextId)
|
|
{
|
|
if (!CRenderer::CV_r_RTT)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CTexture* pTex = CTexture::GetByID(handle);
|
|
if (!pTex || !pTex->GetDevTexture())
|
|
{
|
|
iLog->Log("Failed to render texture. Invalid texture handle ID.");
|
|
return false;
|
|
}
|
|
|
|
// a context may be invalid because it requires hardware resources that are not available
|
|
bool contextIsValid = false;
|
|
AzRTT::RTTRequestBus::BroadcastResult(contextIsValid, &AzRTT::RTTRequestBus::Events::ContextIsValid, contextId);
|
|
if (!contextIsValid)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const int width = pTex->GetWidth();
|
|
const int height = pTex->GetHeight();
|
|
|
|
// NOTE: the renderer's camera comes from the thread info double buffer, so it is possible
|
|
// GetCamera() will just return the camera using in the last render to texture pass.
|
|
// System::GetViewCamera() will have the camera used for the main rendering view
|
|
CCamera prevSysCamera = gEnv->pSystem->GetViewCamera();
|
|
|
|
// get the current viewport and renderer settings to restore after rendering to texture
|
|
int vX, vY, vWidth, vHeight;
|
|
gRenDev->GetViewport(&vX, &vY, &vWidth, &vHeight);
|
|
|
|
// this flag is used by the engine to denote we are rendering the whole scene to texture
|
|
gcpRendD3D->m_RP.m_TI[gcpRendD3D->m_RP.m_nFillThreadID].m_PersFlags |= RBPF_RENDER_SCENE_TO_TEXTURE;
|
|
|
|
// this resets the view and frame view/proj matrices in the thread info
|
|
gcpRendD3D->BeginFrame();
|
|
|
|
// this frees up previous frame render cameras and waits for jobs. It will trigger MainThreadRenderRequestBus::ExecuteQueuedEvents();
|
|
// The main pass also calls this after BeginFrame and before RenderWorld
|
|
gEnv->p3DEngine->Tick();
|
|
|
|
// set the active camera
|
|
gRenDev->SetCamera(camera);
|
|
|
|
// set the system view camera
|
|
CCamera newSystemCamera = camera;
|
|
gEnv->pSystem->SetViewCamera(newSystemCamera);
|
|
|
|
// we do not call PreWorldStreamUpdate here because it will compare the distance of the rtt
|
|
// camera to the main camera and negatively affect stream settings
|
|
|
|
gRenDev->m_pRT->EnqueueRenderCommand([=]()
|
|
{
|
|
// disable back buffer swap so the renderer doesn't call present
|
|
gRenDev->EnableSwapBuffers(false);
|
|
|
|
CTexture* pTex = CTexture::GetByID(handle);
|
|
|
|
// when you set the render target SetViewport is also called with the size of the target
|
|
gRenDev->RT_PushRenderTarget(0, pTex, nullptr, -1);
|
|
|
|
// TODO manually set the viewport with our own viewport ID if we enabled TAA. Currently
|
|
// doesn't work in multi-threaded mode. Causes flickering vegetation/transparent shadows
|
|
|
|
// disabling temporal effects turns off auto exposure and reduces flicker.
|
|
gRenDev->m_nDisableTemporalEffects = 1;
|
|
});
|
|
|
|
bool contextIsActive = false;
|
|
AzRTT::RTTRequestBus::BroadcastResult(contextIsActive, &AzRTT::RTTRequestBus::Events::SetActiveContext, contextId);
|
|
AZ_Warning("RenderToTexture", contextIsActive, "Failed to activate render to texture context, the render target will not be updated");
|
|
|
|
if (contextIsActive)
|
|
{
|
|
// don't draw UI or console to this RTT
|
|
gEnv->pSystem->SetConsoleDrawEnabled(false);
|
|
gEnv->pSystem->SetUIDrawEnabled(false);
|
|
|
|
AzRTT::RenderContextConfig config;
|
|
AzRTT::RTTRequestBus::BroadcastResult(config, &AzRTT::RTTRequestBus::Events::GetContextConfig, contextId);
|
|
|
|
uint32_t renderPassFlags = SRenderingPassInfo::DEFAULT_FLAGS | SRenderingPassInfo::RENDER_SCENE_TO_TEXTURE;
|
|
|
|
// render to texture does not support merged meshes yet
|
|
renderPassFlags &= ~SRenderingPassInfo::MERGED_MESHES;
|
|
|
|
// do not allow SVO (SHDF_ALLOW_AO) for now
|
|
int renderFlags = SHDF_ZPASS | SHDF_ALLOWHDR | SHDF_ALLOWPOSTPROCESS | SHDF_ALLOW_WATER;
|
|
|
|
if (!config.m_shadowsEnabled)
|
|
{
|
|
renderFlags |= SHDF_NO_SHADOWGEN;
|
|
renderPassFlags &= ~SRenderingPassInfo::SHADOWS;
|
|
}
|
|
|
|
if (!config.m_oceanEnabled)
|
|
{
|
|
renderPassFlags &= ~SRenderingPassInfo::WATEROCEAN;
|
|
}
|
|
|
|
SRenderingPassInfo renderPassInfo = SRenderingPassInfo::CreateGeneralPassRenderingInfo(camera, renderPassFlags);
|
|
gEnv->p3DEngine->RenderWorld(renderFlags, renderPassInfo, __FUNCTION__);
|
|
|
|
gEnv->pSystem->SetConsoleDrawEnabled(true);
|
|
gEnv->pSystem->SetUIDrawEnabled(true);
|
|
|
|
gEnv->p3DEngine->EndOcclusion();
|
|
|
|
gEnv->p3DEngine->WorldStreamUpdate();
|
|
|
|
// NOTE: This is how you could copy from the hdr target to the render target if you wanted no post processing (should probably remove SHDF_ALLOWPOSTPROCESS above)
|
|
//gRenDev->m_pRT->EnqueueRenderCommand([=]()
|
|
//{
|
|
//PostProcessUtils().StretchRect(CTexture::s_ptexHDRTarget, pTex, false, false, false, false, SPostEffectsUtils::eDepthDownsample_None, false, &gcpRendD3D->m_FullResRect);
|
|
//});
|
|
|
|
// this ends up calling FX_FinalComposite which will use our render target for post effects
|
|
gcpRendD3D->SwitchToNativeResolutionBackbuffer();
|
|
}
|
|
|
|
// Pop our render target
|
|
gcpRendD3D->SetRenderTarget(0);
|
|
|
|
gRenDev->m_pRT->EnqueueRenderCommand([=]()
|
|
{
|
|
gcpRendD3D->m_RP.m_TI[gcpRendD3D->m_RP.m_nProcessThreadID].m_PersFlags &= ~RBPF_RENDER_SCENE_TO_TEXTURE;
|
|
|
|
gcpRendD3D->SetViewport(vX, vY, vWidth, vHeight);
|
|
|
|
// Reset the camera on the render thread or the main thread can get our
|
|
// camera info after syncing with main.
|
|
gcpRendD3D->SetCamera(prevSysCamera);
|
|
});
|
|
|
|
AzRTT::RTTRequestBus::Broadcast(&AzRTT::RTTRequestBus::Events::SetActiveContext, AzRTT::RenderContextId::CreateNull());
|
|
|
|
// Free all unused render meshes. Without this you can get lots of fun memory leaks.
|
|
gRenDev->ForceGC();
|
|
|
|
// call endframe on the renderer instead of via d3d to bypass drawing messages
|
|
// set wait to true otherwise EndFrame won't be sent if there is no pending flush condition
|
|
bool wait = true;
|
|
gRenDev->m_pRT->RC_EndFrame(wait);
|
|
|
|
// re-enable swap buffers after calling end frame so the main pass will call present()
|
|
gRenDev->m_pRT->EnqueueRenderCommand([=]()
|
|
{
|
|
gRenDev->EnableSwapBuffers(true);
|
|
});
|
|
|
|
// normally we would need to remove the cull job producer using RemoveCullJobProducer
|
|
// we don't need to because we use e_statobjbufferrendertask = 0
|
|
|
|
// restore previous settings
|
|
gEnv->pSystem->SetViewCamera(prevSysCamera);
|
|
gRenDev->SetCamera(prevSysCamera);
|
|
|
|
// this fixes streaming update sync errors when rendering pre frame
|
|
gEnv->p3DEngine->SyncProcessStreamingUpdate();
|
|
|
|
return true;
|
|
}
|
|
#endif // if AZ_RENDER_TO_TEXTURE_GEM_ENABLED
|
|
|
|
bool CTexture::RenderEnvironmentCMHDR([[maybe_unused]] int size, [[maybe_unused]] Vec3& Pos, [[maybe_unused]] TArray<unsigned short>& vecData)
|
|
{
|
|
#if !defined(CONSOLE)
|
|
|
|
iLog->Log("Start generating a cubemap...");
|
|
|
|
vecData.SetUse(0);
|
|
|
|
int vX, vY, vWidth, vHeight;
|
|
gRenDev->GetViewport(&vX, &vY, &vWidth, &vHeight);
|
|
|
|
const int nOldWidth = gRenDev->GetCurrentContextViewportWidth();
|
|
const int nOldHeight = gRenDev->GetCurrentContextViewportHeight();
|
|
bool bFullScreen = (iConsole->GetCVar("r_Fullscreen")->GetIVal() != 0) && (!gEnv->IsEditor());
|
|
gRenDev->ChangeViewport(0, 0, size, size);
|
|
|
|
int nPFlags = gcpRendD3D->m_RP.m_TI[gcpRendD3D->m_RP.m_nProcessThreadID].m_PersFlags;
|
|
|
|
CTexture* ptexGenEnvironmentCM = CTexture::Create2DTexture("$GenEnvironmentCM", size, size, 0, FT_DONT_STREAM, 0, eTF_R16G16B16A16F, eTF_R16G16B16A16F);
|
|
if (!ptexGenEnvironmentCM || !ptexGenEnvironmentCM->GetDevTexture())
|
|
{
|
|
iLog->Log("Failed generating a cubemap: out of video memory");
|
|
gRenDev->ChangeViewport(0, 0, nOldWidth, nOldHeight);
|
|
|
|
SAFE_RELEASE(ptexGenEnvironmentCM);
|
|
return false;
|
|
}
|
|
|
|
// Disable/set cvars that can affect cube map generation. This is thread unsafe (we assume editor will not run in mt mode), no other way around at this time
|
|
// - coverage buffer unreliable for multiple views
|
|
// - custom view distance ratios
|
|
|
|
ICVar* pCoverageBufferCV = gEnv->pConsole->GetCVar("e_CoverageBuffer");
|
|
const int32 nCoverageBuffer = pCoverageBufferCV ? pCoverageBufferCV->GetIVal() : 0;
|
|
if (pCoverageBufferCV)
|
|
{
|
|
pCoverageBufferCV->Set(0);
|
|
}
|
|
|
|
ICVar* pStatObjBufferRenderTasksCV = gEnv->pConsole->GetCVar("e_StatObjBufferRenderTasks");
|
|
const int32 nStatObjBufferRenderTasks = pStatObjBufferRenderTasksCV ? pStatObjBufferRenderTasksCV->GetIVal() : 0;
|
|
if (pStatObjBufferRenderTasksCV)
|
|
{
|
|
pStatObjBufferRenderTasksCV->Set(0);
|
|
}
|
|
|
|
ICVar* pViewDistRatioCV = gEnv->pConsole->GetCVar("e_ViewDistRatio");
|
|
const float fOldViewDistRatio = pViewDistRatioCV ? pViewDistRatioCV->GetFVal() : 1.f;
|
|
if (pViewDistRatioCV)
|
|
{
|
|
pViewDistRatioCV->Set(10000.f);
|
|
}
|
|
|
|
ICVar* pViewDistRatioVegetationCV = gEnv->pConsole->GetCVar("e_ViewDistRatioVegetation");
|
|
const float fOldViewDistRatioVegetation = pViewDistRatioVegetationCV ? pViewDistRatioVegetationCV->GetFVal() : 100.f;
|
|
if (pViewDistRatioVegetationCV)
|
|
{
|
|
pViewDistRatioVegetationCV->Set(10000.f);
|
|
}
|
|
|
|
ICVar* pLodRatioCV = gEnv->pConsole->GetCVar("e_LodRatio");
|
|
const float fOldLodRatio = pLodRatioCV ? pLodRatioCV->GetFVal() : 1.f;
|
|
if (pLodRatioCV)
|
|
{
|
|
pLodRatioCV->Set(1000.f);
|
|
}
|
|
|
|
Vec3 oldSunDir, oldSunStr, oldSunRGB;
|
|
float oldSkyKm, oldSkyKr, oldSkyG;
|
|
if (CRenderer::CV_r_HideSunInCubemaps)
|
|
{
|
|
gEnv->p3DEngine->GetSkyLightParameters(oldSunDir, oldSunStr, oldSkyKm, oldSkyKr, oldSkyG, oldSunRGB);
|
|
gEnv->p3DEngine->SetSkyLightParameters(oldSunDir, oldSunStr, oldSkyKm, oldSkyKr, 1.0f, oldSunRGB, true); // Hide sun disc
|
|
}
|
|
|
|
const int32 nFlaresCV = CRenderer::CV_r_flares;
|
|
CRenderer::CV_r_flares = 0;
|
|
|
|
ICVar* pSSDOHalfResCV = gEnv->pConsole->GetCVar("r_ssdoHalfRes");
|
|
const int nOldSSDOHalfRes = pSSDOHalfResCV ? pSSDOHalfResCV->GetIVal() : 1;
|
|
if (pSSDOHalfResCV)
|
|
{
|
|
pSSDOHalfResCV->Set(0);
|
|
}
|
|
|
|
ICVar* pDynamicGI = gEnv->pConsole->GetCVar("e_GI");
|
|
const int oldDynamicGIValue = pDynamicGI ? pDynamicGI->GetIVal() : 1;
|
|
if (pDynamicGI)
|
|
{
|
|
pDynamicGI->Set(0);
|
|
}
|
|
|
|
const int nDesktopWidth = gcpRendD3D->m_deskwidth;
|
|
const int nDesktopHeight = gcpRendD3D->m_deskheight;
|
|
gcpRendD3D->m_deskwidth = gcpRendD3D->m_deskheight = size;
|
|
|
|
gcpRendD3D->EnableSwapBuffers(false);
|
|
for (int nSide = 0; nSide < 6; nSide++)
|
|
{
|
|
gcpRendD3D->BeginFrame();
|
|
gcpRendD3D->SetViewport(0, 0, size, size);
|
|
|
|
gcpRendD3D->SetWidth(size);
|
|
gcpRendD3D->SetHeight(size);
|
|
|
|
gcpRendD3D->EF_ClearTargetsLater(FRT_CLEAR, Clr_Transparent);
|
|
|
|
DrawSceneToCubeSide(Pos, size, nSide);
|
|
|
|
// Transfer to sysmem
|
|
D3D11_BOX srcBox;
|
|
srcBox.left = 0;
|
|
srcBox.right = size;
|
|
srcBox.top = 0;
|
|
srcBox.bottom = size;
|
|
srcBox.front = 0;
|
|
srcBox.back = 1;
|
|
|
|
CDeviceTexture* pDevTextureSrc = CTexture::s_ptexHDRTarget->GetDevTexture();
|
|
CDeviceTexture* pDevTextureDst = ptexGenEnvironmentCM->GetDevTexture();
|
|
|
|
gcpRendD3D->GetDeviceContext().CopySubresourceRegion(pDevTextureDst->Get2DTexture(), 0, 0, 0, 0, pDevTextureSrc->Get2DTexture(), 0, &srcBox);
|
|
|
|
CDeviceTexture* pDstDevTex = ptexGenEnvironmentCM->GetDevTexture();
|
|
pDstDevTex->DownloadToStagingResource(0, [&](void* pData, [[maybe_unused]] uint32 rowPitch, [[maybe_unused]] uint32 slicePitch)
|
|
{
|
|
unsigned short* pTarg = (unsigned short*)pData;
|
|
const uint32 nLineStride = CTexture::TextureDataSize(size, 1, 1, 1, 1, eTF_R16G16B16A16F) / sizeof(unsigned short);
|
|
|
|
// Copy vertically flipped image
|
|
for (uint32 nLine = 0; nLine < size; ++nLine)
|
|
{
|
|
vecData.Copy(&pTarg[((size - 1) - nLine) * nLineStride], nLineStride);
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
gcpRendD3D->EndFrame();
|
|
}
|
|
|
|
SAFE_RELEASE(ptexGenEnvironmentCM);
|
|
|
|
// Restore previous states
|
|
|
|
gcpRendD3D->m_deskwidth = nDesktopWidth;
|
|
gcpRendD3D->m_deskheight = nDesktopHeight;
|
|
gRenDev->ChangeViewport(0, 0, nOldWidth, nOldHeight);
|
|
|
|
gcpRendD3D->EnableSwapBuffers(true);
|
|
gcpRendD3D->SetWidth(vWidth);
|
|
gcpRendD3D->SetHeight(vHeight);
|
|
gcpRendD3D->RT_SetViewport(vX, vY, vWidth, vHeight);
|
|
gcpRendD3D->m_RP.m_TI[gcpRendD3D->m_RP.m_nProcessThreadID].m_PersFlags = nPFlags;
|
|
gcpRendD3D->ResetToDefault();
|
|
|
|
if (pCoverageBufferCV)
|
|
{
|
|
pCoverageBufferCV->Set(nCoverageBuffer);
|
|
}
|
|
|
|
if (pStatObjBufferRenderTasksCV)
|
|
{
|
|
pStatObjBufferRenderTasksCV->Set(nStatObjBufferRenderTasks);
|
|
}
|
|
|
|
if (pViewDistRatioCV)
|
|
{
|
|
pViewDistRatioCV->Set(fOldViewDistRatio);
|
|
}
|
|
|
|
if (pViewDistRatioVegetationCV)
|
|
{
|
|
pViewDistRatioVegetationCV->Set(fOldViewDistRatioVegetation);
|
|
}
|
|
|
|
if (pLodRatioCV)
|
|
{
|
|
pLodRatioCV->Set(fOldLodRatio);
|
|
}
|
|
|
|
if (CRenderer::CV_r_HideSunInCubemaps)
|
|
{
|
|
gEnv->p3DEngine->SetSkyLightParameters(oldSunDir, oldSunStr, oldSkyKm, oldSkyKr, oldSkyG, oldSunRGB, true);
|
|
}
|
|
|
|
CRenderer::CV_r_flares = nFlaresCV;
|
|
|
|
if (pSSDOHalfResCV)
|
|
{
|
|
pSSDOHalfResCV->Set(nOldSSDOHalfRes);
|
|
}
|
|
|
|
if (pDynamicGI)
|
|
{
|
|
pDynamicGI->Set(oldDynamicGIValue);
|
|
}
|
|
|
|
iLog->Log("Successfully finished generating a cubemap. The cubemap is being compressed in the background and will update automatically when done.");
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void CTexture::DrawSceneToCubeSide(Vec3& Pos, int tex_size, int side)
|
|
{
|
|
const float sCubeVector[6][7] =
|
|
{
|
|
{ 1, 0, 0, 0, 0, 1, -90}, //posx
|
|
{-1, 0, 0, 0, 0, 1, 90}, //negx
|
|
{ 0, 1, 0, 0, 0, -1, 0}, //posy
|
|
{ 0, -1, 0, 0, 0, 1, 0}, //negy
|
|
{ 0, 0, 1, 0, 1, 0, 0}, //posz
|
|
{ 0, 0, -1, 0, 1, 0, 0}, //negz
|
|
};
|
|
|
|
if (!iSystem)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CRenderer* r = gRenDev;
|
|
CCamera prevCamera = r->GetCamera();
|
|
|
|
I3DEngine* eng = gEnv->p3DEngine;
|
|
|
|
Vec3 vForward = Vec3(sCubeVector[side][0], sCubeVector[side][1], sCubeVector[side][2]);
|
|
Vec3 vUp = Vec3(sCubeVector[side][3], sCubeVector[side][4], sCubeVector[side][5]);
|
|
|
|
Matrix33 matRot = Matrix33::CreateOrientation(vForward, vUp, DEG2RAD(sCubeVector[side][6]));
|
|
Matrix34 mFinal = Matrix34(matRot, Pos);
|
|
|
|
// Use current viewport camera's near/far to capture what is shown in the editor
|
|
const CCamera& viewCamera = gEnv->pSystem->GetViewCamera();
|
|
const float captureNear = viewCamera.GetNearPlane();
|
|
const float captureFar = viewCamera.GetFarPlane();
|
|
const float captureFOV = DEG2RAD(90.0f);
|
|
|
|
CCamera captureCamera;
|
|
captureCamera.SetMatrix(mFinal);
|
|
captureCamera.SetFrustum(tex_size, tex_size, captureFOV, captureNear, captureFar);
|
|
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log)
|
|
{
|
|
r->Logv(SRendItem::m_RecurseLevel[r->m_RP.m_nProcessThreadID], ".. DrawSceneToCubeSide .. (DrawCubeSide %d)\n", side);
|
|
}
|
|
#endif
|
|
|
|
eng->RenderWorld(SHDF_CUBEMAPGEN | SHDF_ALLOWPOSTPROCESS | SHDF_ALLOWHDR | SHDF_ZPASS | SHDF_NOASYNC | SHDF_STREAM_SYNC, SRenderingPassInfo::CreateGeneralPassRenderingInfo(captureCamera, (SRenderingPassInfo::DEFAULT_FLAGS | SRenderingPassInfo::CUBEMAP_GEN)), __FUNCTION__);
|
|
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log)
|
|
{
|
|
r->Logv(SRendItem::m_RecurseLevel[r->m_RP.m_nProcessThreadID], ".. End DrawSceneToCubeSide .. (DrawCubeSide %d)\n", side);
|
|
}
|
|
#endif
|
|
|
|
r->SetCamera(prevCamera);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void CTexture::DrawCubeSide(Vec3& Pos, int tex_size, int side, float fMaxDist)
|
|
{
|
|
const float sCubeVector[6][7] =
|
|
{
|
|
{ 1, 0, 0, 0, 0, 1, -90}, //posx
|
|
{-1, 0, 0, 0, 0, 1, 90}, //negx
|
|
{ 0, -1, 0, 0, 0, 1, 0}, //posy
|
|
{ 0, 1, 0, 0, 0, -1, 0}, //negy
|
|
{ 0, 0, 1, 0, 1, 0, 0}, //posz
|
|
{ 0, 0, -1, 0, 1, 0, 0}, //negz
|
|
};
|
|
|
|
if (!iSystem)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CRenderer* r = gRenDev;
|
|
CCamera prevCamera = r->GetCamera();
|
|
CCamera tmpCamera = prevCamera;
|
|
|
|
I3DEngine* eng = gEnv->p3DEngine;
|
|
float fMinDist = 0.25f;
|
|
|
|
Vec3 vForward = Vec3(sCubeVector[side][0], sCubeVector[side][1], sCubeVector[side][2]);
|
|
Vec3 vUp = Vec3(sCubeVector[side][3], sCubeVector[side][4], sCubeVector[side][5]);
|
|
Matrix33 matRot = Matrix33::CreateOrientation(vForward, vUp, DEG2RAD(sCubeVector[side][6]));
|
|
|
|
// magic orientation we use in engine
|
|
Matrix33 matScale = Matrix33::CreateScale(Vec3(1, -1, 1));
|
|
matRot = matScale * matRot;
|
|
|
|
tmpCamera.SetMatrix(Matrix34(matRot, Pos));
|
|
tmpCamera.SetFrustum(tex_size, tex_size, 90.0f * gf_PI / 180.0f, fMinDist, fMaxDist);
|
|
int nPersFlags = r->m_RP.m_TI[r->m_RP.m_nProcessThreadID].m_PersFlags;
|
|
int nPersFlags2 = r->m_RP.m_PersFlags2;
|
|
r->m_RP.m_TI[r->m_RP.m_nProcessThreadID].m_PersFlags |= /*RBPF_MIRRORCAMERA | */ RBPF_MIRRORCULL | RBPF_DRAWTOTEXTURE | RBPF_ENCODE_HDR;
|
|
int nOldZ = CRenderer::CV_r_usezpass;
|
|
CRenderer::CV_r_usezpass = 0;
|
|
|
|
r->RT_SetViewport(0, 0, tex_size, tex_size);
|
|
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log)
|
|
{
|
|
r->Logv(SRendItem::m_RecurseLevel[r->m_RP.m_nProcessThreadID], ".. DrawLowDetail .. (DrawCubeSide %d)\n", side);
|
|
}
|
|
#endif
|
|
|
|
eng->RenderWorld(SHDF_ALLOWHDR | SHDF_NOASYNC | SHDF_STREAM_SYNC, SRenderingPassInfo::CreateGeneralPassRenderingInfo(tmpCamera), __FUNCTION__);
|
|
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log)
|
|
{
|
|
r->Logv(SRendItem::m_RecurseLevel[r->m_RP.m_nProcessThreadID], ".. End DrawLowDetail .. (DrawCubeSide %d)\n", side);
|
|
}
|
|
#endif
|
|
|
|
r->m_RP.m_TI[r->m_RP.m_nProcessThreadID].m_PersFlags = nPersFlags;
|
|
r->m_RP.m_PersFlags2 = nPersFlags2;
|
|
r->SetCamera(prevCamera);
|
|
CRenderer::CV_r_usezpass = nOldZ;
|
|
}
|
|
|
|
bool CTexture::GenerateMipMaps(bool bSetOrthoProj, bool bUseHW, bool bNormalMap)
|
|
{
|
|
if (!(GetFlags() & FT_FORCE_MIPS)
|
|
|| bSetOrthoProj || !bUseHW || bNormalMap) //todo: implement
|
|
{
|
|
return false;
|
|
}
|
|
|
|
PROFILE_LABEL_SCOPE("GENERATE_MIPS");
|
|
PROFILE_SHADER_SCOPE;
|
|
|
|
CDeviceTexture* pTex = GetDevTexture();
|
|
if (!pTex)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
D3D11_TEXTURE2D_DESC pDesc;
|
|
pTex->Get2DTexture()->GetDesc(&pDesc);
|
|
|
|
// all d3d11 devices support autogenmipmaps
|
|
if (m_pRenderTargetData)
|
|
{
|
|
gcpRendD3D->GetDeviceContext().GenerateMips(m_pDeviceShaderResource);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CTexture::DestroyZMaps()
|
|
{
|
|
//SAFE_RELEASE(s_ptexZTarget);
|
|
}
|
|
|
|
void CTexture::GenerateZMaps()
|
|
{
|
|
if (gcpRendD3D->FX_GetEnabledGmemPath(nullptr))
|
|
{
|
|
// Custom Z-Target for GMEM render path should already be set
|
|
assert(s_ptexZTarget == CTexture::s_ptexGmemStenLinDepth);
|
|
return;
|
|
}
|
|
|
|
int nWidth = gcpRendD3D->m_MainViewport.nWidth; //m_d3dsdBackBuffer.Width;
|
|
int nHeight = gcpRendD3D->m_MainViewport.nHeight; //m_d3dsdBackBuffer.Height;
|
|
ETEX_Format eTFZ = CTexture::s_eTFZ;
|
|
uint32 nFlags = FT_DONT_STREAM | FT_USAGE_RENDERTARGET | FT_DONT_RELEASE;
|
|
if (CRenderer::CV_r_msaa)
|
|
{
|
|
nFlags |= FT_USAGE_MSAA;
|
|
}
|
|
if (!s_ptexZTarget)
|
|
{
|
|
s_ptexZTarget = CreateRenderTarget("$ZTarget", nWidth, nHeight, Clr_White, eTT_2D, nFlags, eTFZ);
|
|
s_ptexFurZTarget = CreateRenderTarget("$FurZTarget", nWidth, nHeight, Clr_White, eTT_2D, nFlags, eTFZ);
|
|
}
|
|
else
|
|
{
|
|
s_ptexZTarget->m_nFlags = nFlags;
|
|
s_ptexZTarget->m_nWidth = nWidth;
|
|
s_ptexZTarget->m_nHeight = nHeight;
|
|
s_ptexZTarget->CreateRenderTarget(eTFZ, Clr_White);
|
|
|
|
s_ptexFurZTarget->m_nFlags = nFlags;
|
|
s_ptexFurZTarget->m_nWidth = nWidth;
|
|
s_ptexFurZTarget->m_nHeight = nHeight;
|
|
s_ptexFurZTarget->CreateRenderTarget(eTFZ, Clr_White);
|
|
}
|
|
}
|
|
|
|
void CTexture::DestroySceneMap()
|
|
{
|
|
//SAFE_RELEASE(s_ptexSceneTarget);
|
|
}
|
|
|
|
void CTexture::GenerateSceneMap(ETEX_Format eTF)
|
|
{
|
|
const int32 nWidth = gcpRendD3D->GetWidth();
|
|
const int32 nHeight = gcpRendD3D->GetHeight();
|
|
uint32 nFlags = FT_DONT_STREAM | FT_USAGE_RENDERTARGET | FT_USAGE_UNORDERED_ACCESS;
|
|
nFlags |= FT_USAGE_UNORDERED_ACCESS;
|
|
|
|
if (!s_ptexSceneTarget)
|
|
{
|
|
s_ptexSceneTarget = CreateRenderTarget("$SceneTarget", nWidth, nHeight, Clr_Empty, eTT_2D, nFlags, eTF, TO_SCENE_TARGET);
|
|
}
|
|
else
|
|
{
|
|
s_ptexSceneTarget->m_nFlags = nFlags;
|
|
s_ptexSceneTarget->m_nWidth = nWidth;
|
|
s_ptexSceneTarget->m_nHeight = nHeight;
|
|
s_ptexSceneTarget->CreateRenderTarget(eTF, Clr_Empty);
|
|
}
|
|
|
|
nFlags &= ~(FT_USAGE_MSAA | FT_USAGE_UNORDERED_ACCESS);
|
|
|
|
// This RT used for all post processes passes and shadow mask (group 0) as well
|
|
ETEX_Format backbufferFormat;
|
|
|
|
static ICVar* DolbyCvar = gEnv->pConsole->GetCVar("r_HDRDolby");
|
|
|
|
if (DolbyCvar->GetIVal() == 1)
|
|
{
|
|
backbufferFormat = eTF_R10G10B10A2;
|
|
}
|
|
else
|
|
{
|
|
backbufferFormat = eTF_R8G8B8A8;
|
|
}
|
|
|
|
// This RT used for all post processes passes and shadow mask (group 0) as well
|
|
if (!CTexture::IsTextureExist(s_ptexBackBuffer))
|
|
{
|
|
s_ptexBackBuffer = CreateRenderTarget("$BackBuffer", nWidth, nHeight, Clr_Transparent, eTT_2D, nFlags, backbufferFormat, TO_BACKBUFFERMAP);
|
|
}
|
|
else
|
|
{
|
|
s_ptexBackBuffer->m_nFlags = nFlags;
|
|
s_ptexBackBuffer->m_nWidth = nWidth;
|
|
s_ptexBackBuffer->m_nHeight = nHeight;
|
|
s_ptexBackBuffer->CreateRenderTarget(backbufferFormat, Clr_Transparent);
|
|
}
|
|
|
|
nFlags &= ~(FT_USAGE_MSAA | FT_USAGE_UNORDERED_ACCESS);
|
|
|
|
// This RT can be used by the Render3DModelMgr if the buffer needs to be persistent
|
|
if (CRenderer::CV_r_UsePersistentRTForModelHUD > 0)
|
|
{
|
|
if (!CTexture::IsTextureExist(s_ptexModelHudBuffer))
|
|
{
|
|
s_ptexModelHudBuffer = CreateRenderTarget("$ModelHUD", nWidth, nHeight, Clr_Transparent, eTT_2D, nFlags, eTF_R8G8B8A8, TO_BACKBUFFERMAP);
|
|
}
|
|
else
|
|
{
|
|
s_ptexModelHudBuffer->m_nFlags = nFlags;
|
|
s_ptexModelHudBuffer->m_nWidth = nWidth;
|
|
s_ptexModelHudBuffer->m_nHeight = nHeight;
|
|
s_ptexModelHudBuffer->CreateRenderTarget(eTF_R8G8B8A8, Clr_Transparent);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTexture::GenerateCachedShadowMaps()
|
|
{
|
|
StaticArray<int, MAX_GSM_LODS_NUM> nResolutions = gRenDev->GetCachedShadowsResolution();
|
|
|
|
// parse shadow resolutions from cvar
|
|
{
|
|
int nCurPos = 0;
|
|
int nCurRes = 0;
|
|
|
|
string strResolutions = gEnv->pConsole->GetCVar("r_ShadowsCacheResolutions")->GetString();
|
|
string strCurRes = strResolutions.Tokenize(" ,;-\t", nCurPos);
|
|
|
|
if (!strCurRes.empty())
|
|
{
|
|
nResolutions.fill(0);
|
|
|
|
while (!strCurRes.empty())
|
|
{
|
|
int nRes = atoi(strCurRes.c_str());
|
|
nResolutions[nCurRes] = clamp_tpl(nRes, 0, 16384);
|
|
|
|
strCurRes = strResolutions.Tokenize(" ,;-\t", nCurPos);
|
|
++nCurRes;
|
|
}
|
|
|
|
gRenDev->SetCachedShadowsResolution(nResolutions);
|
|
}
|
|
}
|
|
|
|
const ETEX_Format texFormat = gEnv->pConsole->GetCVar("r_ShadowsCacheFormat")->GetIVal() == 0 ? eTF_D32F : eTF_D16;
|
|
const int cachedShadowsStart = clamp_tpl(CRenderer::CV_r_ShadowsCache, 0, MAX_GSM_LODS_NUM - 1);
|
|
|
|
int gsmCascadeCount = gEnv->pSystem->GetConfigSpec() == CONFIG_LOW_SPEC ? 4 : 5;
|
|
if (ICVar* pGsmLodsVar = gEnv->pConsole->GetCVar("e_GsmLodsNum"))
|
|
{
|
|
gsmCascadeCount = pGsmLodsVar->GetIVal();
|
|
}
|
|
const int cachedCascadesCount = cachedShadowsStart > 0 ? clamp_tpl(gsmCascadeCount - cachedShadowsStart + 1, 0, MAX_GSM_LODS_NUM) : 0;
|
|
|
|
for (int i = 0; i < MAX_GSM_LODS_NUM; ++i)
|
|
{
|
|
CTexture*& pTx = s_ptexCachedShadowMap[i];
|
|
|
|
if (!pTx)
|
|
{
|
|
char szName[32];
|
|
sprintf_s(szName, "CachedShadowMap_%d", i);
|
|
|
|
uint32 flags = FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_DEPTHSTENCIL | FT_USE_HTILE;
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_13
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
pTx = CTexture::CreateTextureObject(szName, nResolutions[i], nResolutions[i], 1, eTT_2D, flags, texFormat);
|
|
}
|
|
|
|
pTx->Invalidate(nResolutions[i], nResolutions[i], texFormat);
|
|
|
|
// delete existing texture in case it's not needed anymore
|
|
if (CTexture::IsTextureExist(pTx) && nResolutions[i] == 0)
|
|
{
|
|
pTx->ReleaseDeviceTexture(false);
|
|
}
|
|
|
|
// allocate texture directly for all cached cascades
|
|
if (!CTexture::IsTextureExist(pTx) && nResolutions[i] > 0 && i < cachedCascadesCount)
|
|
{
|
|
CryLog("Allocating shadow map cache %d x %d: %.2f MB", nResolutions[i], nResolutions[i], sqr(nResolutions[i]) * CTexture::BytesPerBlock(texFormat) / (1024.f * 1024.f));
|
|
pTx->CreateRenderTarget(texFormat, Clr_FarPlane);
|
|
}
|
|
}
|
|
|
|
// height map AO
|
|
if (CRenderer::CV_r_HeightMapAO)
|
|
{
|
|
const int nTexRes = (int)clamp_tpl(CRenderer::CV_r_HeightMapAOResolution, 0.f, 16384.f);
|
|
|
|
if (!s_ptexHeightMapAODepth[0])
|
|
{
|
|
s_ptexHeightMapAODepth[0] = CTexture::CreateTextureObject("HeightMapAO_Depth_0", nTexRes, nTexRes, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_DEPTHSTENCIL | FT_USE_HTILE, eTF_D16);
|
|
s_ptexHeightMapAODepth[1] = CTexture::CreateTextureObject("HeightMapAO_Depth_1", nTexRes, nTexRes, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET | FT_FORCE_MIPS, eTF_R16);
|
|
}
|
|
|
|
s_ptexHeightMapAODepth[0]->Invalidate(nTexRes, nTexRes, eTF_D16);
|
|
s_ptexHeightMapAODepth[1]->Invalidate(nTexRes, nTexRes, eTF_R16);
|
|
|
|
if (!CTexture::IsTextureExist(s_ptexHeightMapAODepth[0]) && nTexRes > 0)
|
|
{
|
|
s_ptexHeightMapAODepth[0]->CreateRenderTarget(eTF_D16, Clr_FarPlane);
|
|
s_ptexHeightMapAODepth[1]->CreateRenderTarget(eTF_R16, Clr_FarPlane);
|
|
}
|
|
}
|
|
|
|
if (ShadowFrustumMGPUCache* pShadowMGPUCache = gRenDev->GetShadowFrustumMGPUCache())
|
|
{
|
|
pShadowMGPUCache->nUpdateMaskRT = 0;
|
|
pShadowMGPUCache->nUpdateMaskMT = 0;
|
|
}
|
|
}
|
|
|
|
void CTexture::DestroyCachedShadowMaps()
|
|
{
|
|
for (int i = 0; i < MAX_GSM_LODS_NUM; ++i)
|
|
{
|
|
SAFE_RELEASE_FORCE(s_ptexCachedShadowMap[i]);
|
|
}
|
|
|
|
SAFE_RELEASE_FORCE(s_ptexHeightMapAO[0]);
|
|
SAFE_RELEASE_FORCE(s_ptexHeightMapAO[1]);
|
|
}
|
|
|
|
void CTexture::GenerateNearestShadowMap()
|
|
{
|
|
const int texResolution = CRenderer::CV_r_ShadowsNearestMapResolution;
|
|
const ETEX_Format texFormat = eTF_D32F;
|
|
s_ptexNearestShadowMap = CTexture::CreateTextureObject("NearestShadowMap", texResolution, texResolution, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_DEPTHSTENCIL | FT_USE_HTILE, texFormat);
|
|
}
|
|
|
|
void CTexture::DestroyNearestShadowMap()
|
|
{
|
|
if (s_ptexNearestShadowMap)
|
|
{
|
|
SAFE_RELEASE_FORCE(s_ptexNearestShadowMap);
|
|
}
|
|
}
|
|
|
|
bool SDynTexture::RT_Update(int nNewWidth, int nNewHeight)
|
|
{
|
|
AZ_Assert(gRenDev->m_pRT->IsRenderThread(), ("Error - Cannot call SDynTexture::RT_Update from any thread that is not the primary render thread!"));
|
|
|
|
Unlink();
|
|
|
|
assert(s_iNumTextureBytesCheckedOut + s_iNumTextureBytesCheckedIn == s_nMemoryOccupied);
|
|
|
|
if (nNewWidth != m_nReqWidth || nNewHeight != m_nReqHeight)
|
|
{
|
|
if (m_pTexture)
|
|
{
|
|
ReleaseDynamicRT(false);
|
|
}
|
|
m_pTexture = NULL;
|
|
|
|
m_nReqWidth = nNewWidth;
|
|
m_nReqHeight = nNewHeight;
|
|
|
|
AdjustRealSize();
|
|
}
|
|
|
|
if (!m_pTexture)
|
|
{
|
|
int nNeedSpace = CTexture::TextureDataSize(m_nWidth, m_nHeight, 1, 1, 1, m_eTF);
|
|
if (m_eTT == eTT_Cube)
|
|
{
|
|
nNeedSpace *= 6;
|
|
}
|
|
SDynTexture* pTX = SDynTexture::s_Root.m_Prev;
|
|
const uint32 maxDynamicTextureMemory = SDynTexture::s_CurDynTexMaxSize * 1024u * 1024u;
|
|
if (nNeedSpace + s_nMemoryOccupied > maxDynamicTextureMemory)
|
|
{
|
|
// Commit any render target binds/unbinds in case they are still waiting to be set or unset in a shadow state
|
|
gcpRendD3D->FX_SetActiveRenderTargets();
|
|
|
|
m_pTexture = GetDynamicRT();
|
|
if (!m_pTexture)
|
|
{
|
|
bool bFreed = FreeTextures(true, nNeedSpace);
|
|
if (!bFreed)
|
|
{
|
|
bFreed = FreeTextures(false, nNeedSpace);
|
|
}
|
|
|
|
if (!bFreed)
|
|
{
|
|
pTX = SDynTexture::s_Root.m_Next;
|
|
int nFrame = gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_nFrameUpdateID - 1;
|
|
while (nNeedSpace + s_nMemoryOccupied > maxDynamicTextureMemory)
|
|
{
|
|
if (pTX == &SDynTexture::s_Root)
|
|
{
|
|
static int nThrash;
|
|
if (nThrash != nFrame)
|
|
{
|
|
nThrash = nFrame;
|
|
iLog->Log("Error: Dynamic textures thrashing (try to increase texture pool size - r_DynTexMaxSize)...");
|
|
}
|
|
break;
|
|
}
|
|
SDynTexture* pNext = pTX->m_Next;
|
|
// We cannot unload locked texture or texture used in current frame
|
|
// Better to increase pool size temporarily
|
|
if (pTX->m_pTexture && !pTX->m_pTexture->IsActiveRenderTarget())
|
|
{
|
|
if (pTX->m_pTexture->m_nAccessFrameID < nFrame && pTX->m_pTexture->m_nUpdateFrameID < nFrame && !pTX->m_bLocked)
|
|
{
|
|
pTX->ReleaseDynamicRT(true);
|
|
}
|
|
}
|
|
pTX = pNext;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!m_pTexture)
|
|
{
|
|
m_pTexture = CreateDynamicRT();
|
|
}
|
|
|
|
assert(s_iNumTextureBytesCheckedOut + s_iNumTextureBytesCheckedIn == s_nMemoryOccupied);
|
|
|
|
if (m_pTexture)
|
|
{
|
|
Link();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool SDynTexture::RT_SetRT(int nRT, int nWidth, int nHeight, bool bPush, bool bScreenVP)
|
|
{
|
|
Update(m_nWidth, m_nHeight);
|
|
|
|
SDepthTexture* pDepthSurf = nWidth > 0 ? gcpRendD3D->FX_GetDepthSurface(nWidth, nHeight, false) : &gcpRendD3D->m_DepthBufferOrig;
|
|
|
|
assert(m_pTexture);
|
|
if (m_pTexture)
|
|
{
|
|
if (bPush)
|
|
{
|
|
return gcpRendD3D->FX_PushRenderTarget(nRT, m_pTexture, pDepthSurf, -1, bScreenVP);
|
|
}
|
|
else
|
|
{
|
|
return gcpRendD3D->FX_SetRenderTarget(nRT, m_pTexture, pDepthSurf, false, -1, bScreenVP);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool SDynTexture::SetRT(int nRT, bool bPush, SDepthTexture* pDepthSurf, bool bScreenVP)
|
|
{
|
|
Update(m_nWidth, m_nHeight);
|
|
|
|
assert(m_pTexture);
|
|
if (m_pTexture)
|
|
{
|
|
if (bPush)
|
|
{
|
|
return gcpRendD3D->FX_PushRenderTarget(nRT, m_pTexture, pDepthSurf, -1, bScreenVP);
|
|
}
|
|
else
|
|
{
|
|
return gcpRendD3D->FX_SetRenderTarget(nRT, m_pTexture, pDepthSurf, false, -1, bScreenVP);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool SDynTexture::RestoreRT(int nRT, bool bPop)
|
|
{
|
|
if (bPop)
|
|
{
|
|
return gcpRendD3D->FX_PopRenderTarget(nRT);
|
|
}
|
|
else
|
|
{
|
|
return gcpRendD3D->FX_RestoreRenderTarget(nRT);
|
|
}
|
|
}
|
|
|
|
bool SDynTexture::ClearRT()
|
|
{
|
|
gcpRendD3D->FX_ClearTarget(m_pTexture);
|
|
return true;
|
|
}
|
|
|
|
bool SDynTexture2::ClearRT()
|
|
{
|
|
gcpRendD3D->FX_ClearTarget(m_pTexture);
|
|
return true;
|
|
}
|
|
|
|
bool SDynTexture2::SetRT(int nRT, bool bPush, SDepthTexture* pDepthSurf, [[maybe_unused]] bool bScreenVP)
|
|
{
|
|
Update(m_nWidth, m_nHeight);
|
|
|
|
assert(m_pTexture);
|
|
if (m_pTexture)
|
|
{
|
|
bool bRes = false;
|
|
if (bPush)
|
|
{
|
|
bRes = gcpRendD3D->FX_PushRenderTarget(nRT, m_pTexture, pDepthSurf);
|
|
}
|
|
else
|
|
{
|
|
bRes = gcpRendD3D->FX_SetRenderTarget(nRT, m_pTexture, pDepthSurf);
|
|
}
|
|
SetRectStates();
|
|
gcpRendD3D->FX_Commit();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool SDynTexture2::SetRectStates()
|
|
{
|
|
assert(m_pTexture);
|
|
gcpRendD3D->RT_SetViewport(m_nX, m_nY, m_nWidth, m_nHeight);
|
|
gcpRendD3D->EF_Scissor(true, m_nX, m_nY, m_nWidth, m_nHeight);
|
|
return true;
|
|
}
|
|
|
|
bool SDynTexture2::RestoreRT(int nRT, bool bPop)
|
|
{
|
|
bool bRes = false;
|
|
gcpRendD3D->EF_Scissor(false, m_nX, m_nY, m_nWidth, m_nHeight);
|
|
if (bPop)
|
|
{
|
|
bRes = gcpRendD3D->FX_PopRenderTarget(nRT);
|
|
}
|
|
else
|
|
{
|
|
bRes = gcpRendD3D->FX_RestoreRenderTarget(nRT);
|
|
}
|
|
gcpRendD3D->FX_Commit();
|
|
|
|
return bRes;
|
|
}
|
|
|
|
void _DrawText(ISystem* pSystem, int x, int y, const float fScale, const char* format, ...);
|
|
|
|
#if !defined(_RELEASE)
|
|
static int __cdecl RTCallback(const VOID* arg1, const VOID* arg2)
|
|
{
|
|
CTexture* p1 = *(CTexture**)arg1;
|
|
CTexture* p2 = *(CTexture**)arg2;
|
|
|
|
// show big textures first
|
|
int nSize1 = p1->GetDataSize();
|
|
int nSize2 = p2->GetDataSize();
|
|
if (nSize1 > nSize2)
|
|
{
|
|
return -1;
|
|
}
|
|
else if (nSize2 > nSize1)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return strcmp(p1->GetName(), p2->GetName());
|
|
}
|
|
#endif
|
|
|
|
void CD3D9Renderer::DrawAllDynTextures([[maybe_unused]] const char* szFilter, [[maybe_unused]] const bool bLogNames, [[maybe_unused]] const bool bOnlyIfUsedThisFrame)
|
|
{
|
|
#ifndef _RELEASE
|
|
SDynTexture2::TextureSet2Itor itor;
|
|
char name[256]; //, nm[256];
|
|
cry_strcpy(name, szFilter);
|
|
azstrlwr(name, AZ_ARRAY_SIZE(name));
|
|
TArray<CTexture*> UsedRT;
|
|
int nMaxCount = CV_r_ShowDynTexturesMaxCount;
|
|
|
|
float width = 800;
|
|
float height = 600;
|
|
float fArrDim = max(1.f, sqrtf((float)nMaxCount));
|
|
float fPicDimX = width / fArrDim;
|
|
float fPicDimY = height / fArrDim;
|
|
float x = 0;
|
|
float y = 0;
|
|
|
|
TransformationMatrices backupSceneMatrices;
|
|
|
|
Set2DMode(static_cast<uint32>(width), static_cast<uint32>(height), backupSceneMatrices);
|
|
|
|
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
|
|
EF_SetSrgbWrite(false);
|
|
if (name[0] == '*' && !name[1])
|
|
{
|
|
SResourceContainer* pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
|
|
ResourcesMapItor it;
|
|
for (it = pRL->m_RMap.begin(); it != pRL->m_RMap.end(); it++)
|
|
{
|
|
CTexture* tp = (CTexture*)it->second;
|
|
if (tp && !tp->IsNoTexture())
|
|
{
|
|
if ((tp->GetFlags() & (FT_USAGE_RENDERTARGET | FT_USAGE_DYNAMIC)) && tp->GetDevTexture())
|
|
{
|
|
UsedRT.AddElem(tp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SResourceContainer* pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
|
|
ResourcesMapItor it;
|
|
for (it = pRL->m_RMap.begin(); it != pRL->m_RMap.end(); it++)
|
|
{
|
|
CTexture* tp = (CTexture*)it->second;
|
|
if (!tp || tp->IsNoTexture())
|
|
{
|
|
continue;
|
|
}
|
|
if ((tp->GetFlags() & (FT_USAGE_RENDERTARGET | FT_USAGE_DYNAMIC)) && tp->GetDevTexture())
|
|
{
|
|
char nameBuffer[128];
|
|
cry_strcpy(nameBuffer, tp->GetName());
|
|
azstrlwr(nameBuffer, AZ_ARRAY_SIZE(nameBuffer));
|
|
if (CryStringUtils::MatchWildcard(nameBuffer, name))
|
|
{
|
|
UsedRT.AddElem(tp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (UsedRT.Num() > 1)
|
|
{
|
|
qsort(&UsedRT[0], UsedRT.Num(), sizeof(CTexture*), RTCallback);
|
|
}
|
|
fPicDimX = width / fArrDim;
|
|
fPicDimY = height / fArrDim;
|
|
x = 0;
|
|
y = 0;
|
|
for (uint32 i = 0; i < UsedRT.Num(); i++)
|
|
{
|
|
SetState(GS_NODEPTHTEST);
|
|
CTexture* tp = UsedRT[i];
|
|
int nSavedAccessFrameID = tp->m_nAccessFrameID;
|
|
|
|
if (bOnlyIfUsedThisFrame)
|
|
{
|
|
if (tp->m_nUpdateFrameID < m_RP.m_TI[m_RP.m_nProcessThreadID].m_nFrameUpdateID - 2)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (tp->GetTextureType() == eTT_2D)
|
|
{
|
|
Draw2dImage(x, y, fPicDimX - 2, fPicDimY - 2, tp->GetID(), 0, 1, 1, 0, 0);
|
|
}
|
|
|
|
tp->m_nAccessFrameID = nSavedAccessFrameID;
|
|
|
|
const char* pTexName = tp->GetName();
|
|
char nameBuffer[128];
|
|
memset(nameBuffer, 0, sizeof nameBuffer);
|
|
for (int iStr = 0, jStr = 0; pTexName[iStr] && jStr < sizeof nameBuffer - 1; ++iStr)
|
|
{
|
|
if (pTexName[iStr] == '$')
|
|
{
|
|
nameBuffer[jStr] = '$';
|
|
nameBuffer[jStr + 1] = '$';
|
|
jStr += 2;
|
|
}
|
|
else
|
|
{
|
|
nameBuffer[jStr] = pTexName[iStr];
|
|
++jStr;
|
|
}
|
|
}
|
|
nameBuffer[sizeof nameBuffer - 1] = 0;
|
|
pTexName = nameBuffer;
|
|
|
|
int32 nPosX = (int32)ScaleCoordX(x);
|
|
int32 nPosY = (int32)ScaleCoordY(y);
|
|
_DrawText(iSystem, nPosX, nPosY, 1.0f, "%8s", pTexName);
|
|
_DrawText(iSystem, nPosX, nPosY += 10, 1.0f, "%d-%d", tp->m_nUpdateFrameID, tp->m_nAccessFrameID);
|
|
_DrawText(iSystem, nPosX, nPosY += 10, 1.0f, "%dx%d", tp->GetWidth(), tp->GetHeight());
|
|
|
|
if (bLogNames)
|
|
{
|
|
iLog->Log("Mem:%d %dx%d Type:%s Format:%s (%s)",
|
|
tp->GetDeviceDataSize(), tp->GetWidth(), tp->GetHeight(), tp->NameForTextureType(tp->GetTextureType()), tp->NameForTextureFormat(tp->GetDstFormat()), tp->GetName());
|
|
}
|
|
|
|
x += fPicDimX;
|
|
if (x >= width - 10)
|
|
{
|
|
x = 0;
|
|
y += fPicDimY;
|
|
}
|
|
}
|
|
|
|
Unset2DMode(backupSceneMatrices);
|
|
|
|
RT_RenderTextMessages();
|
|
#endif
|
|
}
|
|
|
|
void CTexture::ReleaseSystemTargets()
|
|
{
|
|
CTexture::DestroyHDRMaps();
|
|
CTexture::DestroySceneMap();
|
|
CTexture::DestroyCachedShadowMaps();
|
|
CTexture::DestroyNearestShadowMap();
|
|
|
|
if (CDeferredShading::Instance().IsValid())
|
|
{
|
|
CDeferredShading::Instance().DestroyDeferredMaps();
|
|
}
|
|
|
|
PostProcessUtils().Release();
|
|
|
|
SAFE_RELEASE_FORCE(s_ptexWaterOcean);
|
|
SAFE_RELEASE_FORCE(s_ptexWaterVolumeTemp);
|
|
SAFE_RELEASE_FORCE(s_ptexWaterRipplesDDN);
|
|
|
|
SAFE_RELEASE_FORCE(s_ptexSceneNormalsMap);
|
|
SAFE_RELEASE_FORCE(s_ptexSceneNormalsBent);
|
|
SAFE_RELEASE_FORCE(s_ptexAOColorBleed);
|
|
SAFE_RELEASE_FORCE(s_ptexSceneDiffuse);
|
|
SAFE_RELEASE_FORCE(s_ptexSceneSpecular);
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_10
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
SAFE_RELEASE_FORCE(s_ptexSceneDiffuseAccMap);
|
|
SAFE_RELEASE_FORCE(s_ptexSceneSpecularAccMap);
|
|
SAFE_RELEASE_FORCE(s_ptexBackBuffer);
|
|
SAFE_RELEASE_FORCE(s_ptexSceneTarget);
|
|
SAFE_RELEASE_FORCE(s_ptexZTargetScaled);
|
|
SAFE_RELEASE_FORCE(s_ptexZTargetScaled2);
|
|
SAFE_RELEASE_FORCE(s_ptexAmbientLookup);
|
|
SAFE_RELEASE_FORCE(s_ptexDepthBufferQuarter);
|
|
|
|
gcpRendD3D->m_bSystemTargetsInit = 0;
|
|
}
|
|
|
|
void CTexture::ReleaseMiscTargets()
|
|
{
|
|
if (gcpRendD3D->m_pColorGradingControllerD3D)
|
|
{
|
|
gcpRendD3D->m_pColorGradingControllerD3D->ReleaseTextures();
|
|
}
|
|
}
|
|
|
|
void CTexture::CreateSystemTargets()
|
|
{
|
|
if (!gcpRendD3D->m_bSystemTargetsInit)
|
|
{
|
|
|
|
|
|
gcpRendD3D->m_bSystemTargetsInit = 1;
|
|
|
|
ETEX_Format eTF = (gcpRendD3D->m_RP.m_bUseHDR && gcpRendD3D->m_nHDRType == 1) ? eTF_R16G16B16A16F : eTF_R8G8B8A8;
|
|
|
|
// Create HDR targets
|
|
CTexture::GenerateHDRMaps();
|
|
|
|
// Create scene targets
|
|
CTexture::GenerateSceneMap(eTF);
|
|
|
|
// Create ZTarget
|
|
CTexture::GenerateZMaps();
|
|
|
|
// Allocate cached shadow maps if required
|
|
CTexture::GenerateCachedShadowMaps();
|
|
|
|
// Allocate the nearest shadow map if required
|
|
CTexture::GenerateNearestShadowMap();
|
|
|
|
// Create deferred lighting targets
|
|
if (CDeferredShading::Instance().IsValid())
|
|
{
|
|
CDeferredShading::Instance().CreateDeferredMaps();
|
|
}
|
|
|
|
if (CRenderer::CV_r_DeferredShadingTiled > 0)
|
|
{
|
|
gcpRendD3D->GetTiledShading().CreateResources();
|
|
}
|
|
|
|
gcpRendD3D->GetVolumetricFog().CreateResources();
|
|
|
|
// Create post effects targets
|
|
PostProcessUtils().Create();
|
|
}
|
|
}
|
|
|
|
void CTexture::CopySliceChain(CDeviceTexture* const pDevTexture, int ownerMips, int nDstSlice, int nDstMip, CDeviceTexture* pSrcDevTex, int nSrcSlice, int nSrcMip, int nSrcMips, int nNumMips)
|
|
{
|
|
assert(pSrcDevTex && pDevTexture);
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_11
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
|
|
D3DBaseTexture* pDstResource = pDevTexture->GetBaseTexture();
|
|
D3DBaseTexture* pSrcResource = pSrcDevTex->GetBaseTexture();
|
|
|
|
#ifndef _RELEASE
|
|
if (!pDstResource)
|
|
{
|
|
__debugbreak();
|
|
}
|
|
if (!pSrcResource)
|
|
{
|
|
__debugbreak();
|
|
}
|
|
#endif
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION D3DTEXTURE_CPP_SECTION_12
|
|
#include AZ_RESTRICTED_FILE(D3DTexture_cpp)
|
|
#endif
|
|
assert(nSrcMip >= 0 && nDstMip >= 0);
|
|
for (int i = 0; i < nNumMips; ++i)
|
|
{
|
|
#if defined(DEVICE_SUPPORTS_D3D11_1)
|
|
gcpRendD3D->GetDeviceContext().CopySubresourceRegion1(
|
|
pDstResource,
|
|
D3D11CalcSubresource(nDstMip + i, nDstSlice, ownerMips),
|
|
0, 0, 0,
|
|
pSrcResource,
|
|
D3D11CalcSubresource(nSrcMip + i, nSrcSlice, nSrcMips),
|
|
NULL,
|
|
D3D11_COPY_NO_OVERWRITE);
|
|
#else
|
|
gcpRendD3D->GetDeviceContext().CopySubresourceRegion(
|
|
pDstResource,
|
|
D3D11CalcSubresource(nDstMip + i, nDstSlice, ownerMips),
|
|
0, 0, 0,
|
|
pSrcResource,
|
|
D3D11CalcSubresource(nSrcMip + i, nSrcSlice, nSrcMips),
|
|
NULL);
|
|
#endif
|
|
}
|
|
}
|