605 lines
23 KiB
C++
605 lines
23 KiB
C++
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
|
|
|
#if GRAPHICS_API_DIRECTX11
|
|
|
|
#include "GPUTextureDX11.h"
|
|
#include "Engine/Graphics/PixelFormatExtensions.h"
|
|
#include "Engine/Graphics/Textures/TextureData.h"
|
|
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
|
|
|
bool GPUTextureDX11::OnInit()
|
|
{
|
|
// Cache formats
|
|
const PixelFormat format = Format();
|
|
const PixelFormat typelessFormat = PixelFormatExtensions::MakeTypeless(format);
|
|
const DXGI_FORMAT dxgiFormat = RenderToolsDX::ToDxgiFormat(typelessFormat);
|
|
_dxgiFormatDSV = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindDepthStencilFormat(format));
|
|
_dxgiFormatSRV = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindShaderResourceFormat(format, _sRGB));
|
|
_dxgiFormatRTV = _dxgiFormatSRV;
|
|
_dxgiFormatUAV = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindUnorderedAccessFormat(format));
|
|
|
|
// Cache properties
|
|
auto device = _device->GetDevice();
|
|
bool useSRV = IsShaderResource();
|
|
bool useDSV = IsDepthStencil();
|
|
bool useRTV = IsRenderTarget();
|
|
bool useUAV = IsUnorderedAccess();
|
|
|
|
// Create resource
|
|
HRESULT result;
|
|
if (IsVolume())
|
|
{
|
|
// Create texture description
|
|
D3D11_TEXTURE3D_DESC textureDesc;
|
|
textureDesc.MipLevels = MipLevels();
|
|
textureDesc.Format = dxgiFormat;
|
|
textureDesc.Width = Width();
|
|
textureDesc.Height = Height();
|
|
textureDesc.Depth = Depth();
|
|
textureDesc.BindFlags = 0;
|
|
textureDesc.CPUAccessFlags = RenderToolsDX::GetDX11CpuAccessFlagsFromUsage(_desc.Usage);
|
|
textureDesc.MiscFlags = 0;
|
|
textureDesc.Usage = RenderToolsDX::ToD3D11Usage(_desc.Usage);
|
|
if (useSRV)
|
|
textureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
|
|
if (useRTV)
|
|
textureDesc.BindFlags |= D3D11_BIND_RENDER_TARGET;
|
|
if (useDSV)
|
|
textureDesc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
|
|
if (useUAV)
|
|
textureDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
|
|
|
|
// Create texture
|
|
ID3D11Texture3D* texture;
|
|
result = device->CreateTexture3D(&textureDesc, nullptr, &texture);
|
|
_resource = texture;
|
|
}
|
|
else
|
|
{
|
|
// Create texture description
|
|
D3D11_TEXTURE2D_DESC textureDesc;
|
|
textureDesc.MipLevels = MipLevels();
|
|
textureDesc.Format = dxgiFormat;
|
|
textureDesc.Width = Width();
|
|
textureDesc.Height = Height();
|
|
textureDesc.Usage = RenderToolsDX::ToD3D11Usage(_desc.Usage);
|
|
textureDesc.BindFlags = 0;
|
|
textureDesc.CPUAccessFlags = RenderToolsDX::GetDX11CpuAccessFlagsFromUsage(_desc.Usage);
|
|
textureDesc.ArraySize = ArraySize();
|
|
textureDesc.SampleDesc.Count = static_cast<UINT>(_desc.MultiSampleLevel);
|
|
textureDesc.SampleDesc.Quality = 0;
|
|
textureDesc.MiscFlags = 0;
|
|
if (useSRV)
|
|
textureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
|
|
if (useRTV)
|
|
textureDesc.BindFlags |= D3D11_BIND_RENDER_TARGET;
|
|
if (useDSV)
|
|
textureDesc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
|
|
if (useUAV)
|
|
textureDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
|
|
if (_device->GetFeatureLevel() >= FeatureLevel::SM5 && IsMultiSample())
|
|
textureDesc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
|
if (IsCubeMap())
|
|
textureDesc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
|
|
|
|
// Create texture
|
|
ID3D11Texture2D* texture;
|
|
result = device->CreateTexture2D(&textureDesc, nullptr, &texture);
|
|
_resource = texture;
|
|
}
|
|
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
|
ASSERT(_resource != nullptr);
|
|
DX_SET_DEBUG_NAME(_resource, GetName());
|
|
|
|
// Update memory usage
|
|
_memoryUsage = calculateMemoryUsage();
|
|
|
|
// Initialize handles to the resource
|
|
if (IsRegularTexture())
|
|
{
|
|
// 'Regular' texture is using only one handle (texture/cubemap)
|
|
_handlesPerSlice.Resize(1, false);
|
|
}
|
|
else
|
|
{
|
|
// Create all handles
|
|
initHandles();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void GPUTextureDX11::OnResidentMipsChanged()
|
|
{
|
|
const int32 firstMipIndex = MipLevels() - ResidentMipLevels();
|
|
const int32 mipLevels = ResidentMipLevels();
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC srDesc;
|
|
srDesc.Format = _dxgiFormatSRV;
|
|
if (IsCubeMap())
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
|
srDesc.TextureCube.MostDetailedMip = firstMipIndex;
|
|
srDesc.TextureCube.MipLevels = mipLevels;
|
|
}
|
|
else if (IsVolume())
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
|
srDesc.Texture3D.MostDetailedMip = firstMipIndex;
|
|
srDesc.Texture3D.MipLevels = mipLevels;
|
|
}
|
|
else
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
srDesc.Texture2D.MostDetailedMip = firstMipIndex;
|
|
srDesc.Texture2D.MipLevels = mipLevels;
|
|
}
|
|
ID3D11ShaderResourceView* srView = nullptr;
|
|
if (mipLevels != 0)
|
|
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateShaderResourceView(_resource, &srDesc, &srView));
|
|
GPUTextureViewDX11& view = IsVolume() ? _handleVolume : _handlesPerSlice[0];
|
|
if (view.GetParent() == nullptr)
|
|
view.Init(this, nullptr, srView, nullptr, nullptr, Format(), MultiSampleLevel());
|
|
else
|
|
view.SetSRV(srView);
|
|
}
|
|
|
|
void GPUTextureDX11::OnReleaseGPU()
|
|
{
|
|
_handlesPerMip.Resize(0, false);
|
|
_handlesPerSlice.Resize(0, false);
|
|
_handleArray.Release();
|
|
_handleVolume.Release();
|
|
_handleReadOnlyDepth.Release();
|
|
DX_SAFE_RELEASE_CHECK(_resource, 0);
|
|
|
|
// Base
|
|
GPUTexture::OnReleaseGPU();
|
|
}
|
|
|
|
#define CLEAR_VIEWS() rtView = nullptr; srView = nullptr; dsView = nullptr; uaView = nullptr
|
|
|
|
void GPUTextureDX11::initHandles()
|
|
{
|
|
ID3D11RenderTargetView* rtView;
|
|
ID3D11ShaderResourceView* srView;
|
|
ID3D11DepthStencilView* dsView;
|
|
ID3D11UnorderedAccessView* uaView;
|
|
D3D11_RENDER_TARGET_VIEW_DESC rtDesc;
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC srDesc;
|
|
D3D11_DEPTH_STENCIL_VIEW_DESC dsDesc;
|
|
D3D11_UNORDERED_ACCESS_VIEW_DESC uaDesc;
|
|
|
|
CLEAR_VIEWS();
|
|
|
|
rtDesc.Format = _dxgiFormatRTV;
|
|
srDesc.Format = _dxgiFormatSRV;
|
|
dsDesc.Format = _dxgiFormatDSV;
|
|
dsDesc.Flags = 0;
|
|
uaDesc.Format = _dxgiFormatUAV;
|
|
|
|
// Cache properties
|
|
auto device = _device->GetDevice();
|
|
bool useSRV = IsShaderResource();
|
|
bool useDSV = IsDepthStencil();
|
|
bool useRTV = IsRenderTarget();
|
|
bool useUAV = IsUnorderedAccess();
|
|
int32 arraySize = ArraySize();
|
|
int32 mipLevels = MipLevels();
|
|
bool isArray = arraySize > 1;
|
|
bool isCubeMap = IsCubeMap();
|
|
bool isMsaa = IsMultiSample();
|
|
bool isVolume = IsVolume();
|
|
auto format = Format();
|
|
auto msaa = MultiSampleLevel();
|
|
|
|
// Create resource views
|
|
if (isVolume)
|
|
{
|
|
// Create handle for whole 3d texture
|
|
if (useSRV)
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
|
srDesc.Texture3D.MostDetailedMip = 0;
|
|
srDesc.Texture3D.MipLevels = mipLevels;
|
|
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
|
}
|
|
if (useRTV)
|
|
{
|
|
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
|
|
rtDesc.Texture3D.MipSlice = 0;
|
|
rtDesc.Texture3D.FirstWSlice = 0;
|
|
rtDesc.Texture3D.WSize = Depth();
|
|
VALIDATE_DIRECTX_CALL(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
|
}
|
|
if (useUAV)
|
|
{
|
|
uaDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
|
|
uaDesc.Texture3D.MipSlice = 0;
|
|
uaDesc.Texture3D.WSize = Depth();
|
|
uaDesc.Texture3D.FirstWSlice = 0;
|
|
VALIDATE_DIRECTX_CALL(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
|
}
|
|
_handleVolume.Init(this, rtView, srView, nullptr, uaView, format, msaa);
|
|
|
|
// Init per slice views
|
|
_handlesPerSlice.Resize(Depth(), false);
|
|
if (_desc.HasPerSliceViews() && useRTV)
|
|
{
|
|
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
|
|
rtDesc.Texture3D.MipSlice = 0;
|
|
rtDesc.Texture3D.WSize = 1;
|
|
|
|
for (int32 sliceIndex = 0; sliceIndex < Depth(); sliceIndex++)
|
|
{
|
|
rtDesc.Texture3D.FirstWSlice = sliceIndex;
|
|
VALIDATE_DIRECTX_CALL(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
|
_handlesPerSlice[sliceIndex].Init(this, rtView, nullptr, nullptr, nullptr, format, msaa);
|
|
}
|
|
}
|
|
}
|
|
else if (isArray)
|
|
{
|
|
// Resize handles
|
|
_handlesPerSlice.Resize(ArraySize(), false);
|
|
|
|
// Create per array slice handles
|
|
for (int32 arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
|
|
{
|
|
CLEAR_VIEWS();
|
|
|
|
if (useDSV)
|
|
{
|
|
/*if (isCubeMap)
|
|
{
|
|
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
|
dsDesc.Texture2DArray.ArraySize = 6;
|
|
dsDesc.Texture2DArray.FirstArraySlice = arrayIndex * 6;
|
|
dsDesc.Texture2DArray.MipSlice = 0;
|
|
}
|
|
else*/
|
|
{
|
|
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
|
dsDesc.Texture2DArray.ArraySize = 1;
|
|
dsDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
|
dsDesc.Texture2DArray.MipSlice = 0;
|
|
}
|
|
VALIDATE_DIRECTX_CALL(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
|
}
|
|
if (useRTV)
|
|
{
|
|
/*if (isCubeMap)
|
|
{
|
|
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
|
rtDesc.Texture2DArray.ArraySize = 6;
|
|
rtDesc.Texture2DArray.FirstArraySlice = arrayIndex * 6;
|
|
rtDesc.Texture2DArray.MipSlice = 0;
|
|
}
|
|
else*/
|
|
{
|
|
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
|
rtDesc.Texture2DArray.ArraySize = 1;
|
|
rtDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
|
rtDesc.Texture2DArray.MipSlice = 0;
|
|
}
|
|
VALIDATE_DIRECTX_CALL(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
|
}
|
|
if (useSRV)
|
|
{
|
|
// When GetFeatureLevel returns D3D_FEATURE_LEVEL_10_0 or less, Resources created with D3D11_RESOURCE_MISC_TEXTURECUBE may only be treated as cubemap ShaderResourceViews.
|
|
// (ViewDimension must be D3D11_SRV_DIMENSION_TEXTURECUBE) [ STATE_CREATION ERROR #126: CREATESHADERRESOURCEVIEW_INVALIDDESC]
|
|
if (isCubeMap && _device->GetRendererType() != RendererType::DirectX10)
|
|
{
|
|
/*if (isCubeMap)
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
|
|
srDesc.TextureCubeArray.First2DArrayFace = arrayIndex * 6;
|
|
srDesc.TextureCubeArray.NumCubes = 1;
|
|
srDesc.TextureCubeArray.MipLevels = mipLevels;
|
|
srDesc.TextureCubeArray.MostDetailedMip = 0;
|
|
}
|
|
else*/
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
|
srDesc.Texture2DArray.ArraySize = 1;
|
|
srDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
|
srDesc.Texture2DArray.MipLevels = mipLevels;
|
|
srDesc.Texture2DArray.MostDetailedMip = 0;
|
|
}
|
|
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
|
}
|
|
}
|
|
|
|
_handlesPerSlice[arrayIndex].Init(this, rtView, srView, dsView, nullptr, format, msaa);
|
|
}
|
|
|
|
// Create whole array handle
|
|
{
|
|
CLEAR_VIEWS();
|
|
|
|
if (useDSV)
|
|
{
|
|
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
|
dsDesc.Texture2DArray.ArraySize = arraySize;
|
|
dsDesc.Texture2DArray.FirstArraySlice = 0;
|
|
dsDesc.Texture2DArray.MipSlice = 0;
|
|
VALIDATE_DIRECTX_CALL(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
|
}
|
|
if (useRTV)
|
|
{
|
|
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
|
rtDesc.Texture2DArray.ArraySize = arraySize;
|
|
rtDesc.Texture2DArray.FirstArraySlice = 0;
|
|
rtDesc.Texture2DArray.MipSlice = 0;
|
|
VALIDATE_DIRECTX_CALL(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
|
}
|
|
if (useSRV)
|
|
{
|
|
if (isCubeMap)
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
|
srDesc.TextureCube.MostDetailedMip = 0;
|
|
srDesc.TextureCube.MipLevels = mipLevels;
|
|
}
|
|
else
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
|
srDesc.Texture2DArray.ArraySize = arraySize;
|
|
srDesc.Texture2DArray.FirstArraySlice = 0;
|
|
srDesc.Texture2DArray.MipLevels = mipLevels;
|
|
srDesc.Texture2DArray.MostDetailedMip = 0;
|
|
}
|
|
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
|
}
|
|
if (useUAV)
|
|
{
|
|
uaDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
|
|
uaDesc.Texture2DArray.MipSlice = 0;
|
|
uaDesc.Texture2DArray.ArraySize = arraySize;
|
|
uaDesc.Texture2DArray.FirstArraySlice = 0;
|
|
VALIDATE_DIRECTX_CALL(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
|
}
|
|
_handleArray.Init(this, rtView, srView, dsView, uaView, format, msaa);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Resize handles
|
|
_handlesPerSlice.Resize(1, false);
|
|
CLEAR_VIEWS();
|
|
|
|
// Create single handle for the whole texture
|
|
if (useDSV)
|
|
{
|
|
if (isCubeMap)
|
|
{
|
|
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
|
dsDesc.Texture2DArray.MipSlice = 0;
|
|
dsDesc.Texture2DArray.FirstArraySlice = 0;
|
|
dsDesc.Texture2DArray.ArraySize = arraySize * 6;
|
|
}
|
|
else if (isMsaa)
|
|
{
|
|
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
|
|
}
|
|
else
|
|
{
|
|
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
|
dsDesc.Texture2D.MipSlice = 0;
|
|
}
|
|
VALIDATE_DIRECTX_CALL(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
|
}
|
|
if (useRTV)
|
|
{
|
|
if (isCubeMap)
|
|
{
|
|
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
|
rtDesc.Texture2DArray.MipSlice = 0;
|
|
rtDesc.Texture2DArray.FirstArraySlice = 0;
|
|
rtDesc.Texture2DArray.ArraySize = arraySize * 6;
|
|
}
|
|
else if (isMsaa)
|
|
{
|
|
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
|
|
}
|
|
else
|
|
{
|
|
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
|
rtDesc.Texture2D.MipSlice = 0;
|
|
}
|
|
VALIDATE_DIRECTX_CALL(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
|
}
|
|
if (useSRV)
|
|
{
|
|
if (isCubeMap)
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
|
srDesc.TextureCube.MostDetailedMip = 0;
|
|
srDesc.TextureCube.MipLevels = mipLevels;
|
|
}
|
|
else if (isMsaa)
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
|
|
}
|
|
else
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
srDesc.Texture2D.MostDetailedMip = 0;
|
|
srDesc.Texture2D.MipLevels = mipLevels;
|
|
}
|
|
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
|
}
|
|
if (useUAV)
|
|
{
|
|
uaDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
|
|
uaDesc.Texture2D.MipSlice = 0;
|
|
VALIDATE_DIRECTX_CALL(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
|
}
|
|
_handlesPerSlice[0].Init(this, rtView, srView, dsView, uaView, format, msaa);
|
|
}
|
|
|
|
// Init per mip map handles
|
|
if (HasPerMipViews())
|
|
{
|
|
// Init handles
|
|
_handlesPerMip.Resize(arraySize, false);
|
|
for (int32 arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
|
|
{
|
|
auto& slice = _handlesPerMip[arrayIndex];
|
|
slice.Resize(mipLevels, false);
|
|
|
|
for (int32 mipIndex = 0; mipIndex < mipLevels; mipIndex++)
|
|
{
|
|
dsView = nullptr;
|
|
rtView = nullptr;
|
|
srView = nullptr;
|
|
|
|
// DSV
|
|
if (useDSV)
|
|
{
|
|
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
|
dsDesc.Texture2DArray.ArraySize = 1;
|
|
dsDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
|
dsDesc.Texture2DArray.MipSlice = mipIndex;
|
|
_device->GetDevice()->CreateDepthStencilView(_resource, &dsDesc, &dsView);
|
|
}
|
|
|
|
// RTV
|
|
if (useRTV)
|
|
{
|
|
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
|
rtDesc.Texture2DArray.ArraySize = 1;
|
|
rtDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
|
rtDesc.Texture2DArray.MipSlice = mipIndex;
|
|
_device->GetDevice()->CreateRenderTargetView(_resource, &rtDesc, &rtView);
|
|
}
|
|
|
|
// SRV
|
|
if (useSRV)
|
|
{
|
|
// When GetFeatureLevel returns D3D_FEATURE_LEVEL_10_0 or less, Resources created with D3D11_RESOURCE_MISC_TEXTURECUBE may only be treated as cubemap ShaderResourceViews.
|
|
// (ViewDimension must be D3D11_SRV_DIMENSION_TEXTURECUBE) [ STATE_CREATION ERROR #126: CREATESHADERRESOURCEVIEW_INVALIDDESC]
|
|
if ((isCubeMap && _device->GetRendererType() == RendererType::DirectX10) == false)
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
|
srDesc.Texture2DArray.ArraySize = 1;
|
|
srDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
|
srDesc.Texture2DArray.MipLevels = 1;
|
|
srDesc.Texture2DArray.MostDetailedMip = mipIndex;
|
|
_device->GetDevice()->CreateShaderResourceView(_resource, &srDesc, &srView);
|
|
}
|
|
}
|
|
|
|
slice[mipIndex].Init(this, rtView, srView, dsView, nullptr, format, msaa);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Read-only depth-stencil
|
|
if (EnumHasAnyFlags(_desc.Flags, GPUTextureFlags::ReadOnlyDepthView))
|
|
{
|
|
CLEAR_VIEWS();
|
|
|
|
// Create single handle for the whole texture
|
|
if (useDSV)
|
|
{
|
|
if (isCubeMap)
|
|
{
|
|
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
|
dsDesc.Texture2DArray.MipSlice = 0;
|
|
dsDesc.Texture2DArray.FirstArraySlice = 0;
|
|
dsDesc.Texture2DArray.ArraySize = arraySize * 6;
|
|
}
|
|
else if (isMsaa)
|
|
{
|
|
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
|
|
}
|
|
else
|
|
{
|
|
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
|
dsDesc.Texture2D.MipSlice = 0;
|
|
}
|
|
dsDesc.Flags = D3D11_DSV_READ_ONLY_DEPTH;
|
|
if (PixelFormatExtensions::HasStencil(format))
|
|
dsDesc.Flags |= D3D11_DSV_READ_ONLY_STENCIL;
|
|
VALIDATE_DIRECTX_CALL(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
|
}
|
|
ASSERT(!useRTV);
|
|
rtView = nullptr;
|
|
if (useSRV)
|
|
{
|
|
if (isCubeMap)
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
|
srDesc.TextureCube.MostDetailedMip = 0;
|
|
srDesc.TextureCube.MipLevels = mipLevels;
|
|
}
|
|
else if (isMsaa)
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
|
|
}
|
|
else
|
|
{
|
|
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
srDesc.Texture2D.MostDetailedMip = 0;
|
|
srDesc.Texture2D.MipLevels = mipLevels;
|
|
}
|
|
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
|
}
|
|
_handleReadOnlyDepth.Init(this, rtView, srView, dsView, nullptr, format, msaa);
|
|
}
|
|
}
|
|
|
|
bool GPUTextureDX11::GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch)
|
|
{
|
|
if (!IsStaging())
|
|
{
|
|
LOG(Warning, "Texture::GetData is valid only for staging resources.");
|
|
return true;
|
|
}
|
|
|
|
GPUDeviceLock lock(_device);
|
|
|
|
// Map the staging resource mip map for reading
|
|
const uint32 subresource = RenderToolsDX::CalcSubresourceIndex(mipMapIndex, arrayOrDepthSliceIndex, MipLevels());
|
|
D3D11_MAPPED_SUBRESOURCE mapped;
|
|
const HRESULT mapResult = _device->GetIM()->Map(_resource, subresource, D3D11_MAP_READ, 0, &mapped);
|
|
if (FAILED(mapResult))
|
|
{
|
|
LOG_DIRECTX_RESULT(mapResult);
|
|
return true;
|
|
}
|
|
|
|
// Check if target row pitch is the same
|
|
if (mipRowPitch == mapped.RowPitch || mipRowPitch == 0)
|
|
{
|
|
// Init mip info
|
|
data.Lines = mapped.DepthPitch / mapped.RowPitch;
|
|
data.DepthPitch = mapped.DepthPitch;
|
|
data.RowPitch = mapped.RowPitch;
|
|
|
|
// Copy data
|
|
data.Data.Copy((byte*)mapped.pData, mapped.DepthPitch);
|
|
}
|
|
else
|
|
{
|
|
// Init mip info
|
|
data.Lines = mapped.DepthPitch / mapped.RowPitch;
|
|
data.DepthPitch = mipRowPitch * data.Lines;
|
|
data.RowPitch = mipRowPitch;
|
|
|
|
// Copy data
|
|
data.Data.Allocate(data.DepthPitch);
|
|
for (uint32 i = 0; i < data.Lines; i++)
|
|
{
|
|
Platform::MemoryCopy(data.Data.Get() + data.RowPitch * i, ((byte*)mapped.pData) + mapped.RowPitch * i, data.RowPitch);
|
|
}
|
|
}
|
|
|
|
// Unmap texture
|
|
_device->GetIM()->Unmap(_resource, subresource);
|
|
|
|
return false;
|
|
}
|
|
|
|
#endif
|