Add support for Volume textures to have residency changed as regular textures

This commit is contained in:
Wojciech Figat
2022-04-21 12:36:16 +02:00
parent 60d2670e2e
commit 0a458d94c4
11 changed files with 50 additions and 57 deletions

View File

@@ -813,5 +813,5 @@ void GPUTexture::SetResidentMipLevels(int32 count)
if (_residentMipLevels == count || !IsRegularTexture())
return;
_residentMipLevels = count;
onResidentMipsChanged();
OnResidentMipsChanged();
}

View File

@@ -572,7 +572,7 @@ protected:
virtual bool OnInit() = 0;
uint64 calculateMemoryUsage() const;
virtual void onResidentMipsChanged() = 0;
virtual void OnResidentMipsChanged() = 0;
public:

View File

@@ -109,37 +109,37 @@ bool GPUTextureDX11::OnInit()
return false;
}
void GPUTextureDX11::onResidentMipsChanged()
void GPUTextureDX11::OnResidentMipsChanged()
{
// We support changing resident mip maps only for regular textures (render targets and depth buffers don't use that feature at all)
ASSERT(IsRegularTexture() && _handlesPerSlice.Count() == 1);
ASSERT(!IsVolume());
// Fill description
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 = MipLevels() - ResidentMipLevels();
srDesc.TextureCube.MipLevels = ResidentMipLevels();
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 = MipLevels() - ResidentMipLevels();
srDesc.Texture2D.MipLevels = ResidentMipLevels();
srDesc.Texture2D.MostDetailedMip = firstMipIndex;
srDesc.Texture2D.MipLevels = mipLevels;
}
// Create new view
ID3D11ShaderResourceView* srView;
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateShaderResourceView(_resource, &srDesc, &srView));
// Change view
if (_handlesPerSlice[0].GetParent() == nullptr)
_handlesPerSlice[0].Init(this, nullptr, srView, nullptr, nullptr, Format(), MultiSampleLevel());
GPUTextureViewDX11& view = IsVolume() ? _handleVolume : _handlesPerSlice[0];
if (view.GetParent() == nullptr)
view.Init(this, nullptr, srView, nullptr, nullptr, Format(), MultiSampleLevel());
else
_handlesPerSlice[0].SetSRV(srView);
view.SetSRV(srView);
}
void GPUTextureDX11::OnReleaseGPU()

View File

@@ -277,7 +277,7 @@ protected:
// [GPUTexture]
bool OnInit() override;
void onResidentMipsChanged() override;
void OnResidentMipsChanged() override;
void OnReleaseGPU() override;
};

View File

@@ -208,36 +208,39 @@ bool GPUTextureDX12::OnInit()
return false;
}
void GPUTextureDX12::onResidentMipsChanged()
void GPUTextureDX12::OnResidentMipsChanged()
{
// We support changing resident mip maps only for regular textures (render targets and depth buffers don't use that feature at all)
ASSERT(IsRegularTexture() && _handlesPerSlice.Count() == 1);
ASSERT(!IsVolume());
// Fill description
const int32 firstMipIndex = MipLevels() - ResidentMipLevels();
const int32 mipLevels = ResidentMipLevels();
D3D12_SHADER_RESOURCE_VIEW_DESC srDesc;
srDesc.Format = _dxgiFormatSRV;
srDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
if (IsCubeMap())
{
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
srDesc.TextureCube.MostDetailedMip = MipLevels() - ResidentMipLevels();
srDesc.TextureCube.MipLevels = ResidentMipLevels();
srDesc.TextureCube.MostDetailedMip = firstMipIndex;
srDesc.TextureCube.MipLevels = mipLevels;
srDesc.TextureCube.ResourceMinLODClamp = 0;
}
else if (IsVolume())
{
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
srDesc.Texture3D.MostDetailedMip = firstMipIndex;
srDesc.Texture3D.MipLevels = mipLevels;
srDesc.Texture3D.ResourceMinLODClamp = 0;
}
else
{
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srDesc.Texture2D.MostDetailedMip = MipLevels() - ResidentMipLevels();
srDesc.Texture2D.MipLevels = ResidentMipLevels();
srDesc.Texture2D.MostDetailedMip = firstMipIndex;
srDesc.Texture2D.MipLevels = mipLevels;
srDesc.Texture2D.PlaneSlice = 0;
srDesc.Texture2D.ResourceMinLODClamp = 0;
}
// Change view
if (_handlesPerSlice[0].GetParent() == nullptr)
_handlesPerSlice[0].Init(this, _device, this, Format(), MultiSampleLevel());
_handlesPerSlice[0].SetSRV(srDesc);
GPUTextureViewDX12& view = IsVolume() ? _handleVolume : _handlesPerSlice[0];
if (view.GetParent() == nullptr)
view.Init(this, _device, this, Format(), MultiSampleLevel());
view.SetSRV(srDesc);
}
void GPUTextureDX12::OnReleaseGPU()

View File

@@ -216,7 +216,7 @@ protected:
// [GPUTexture]
bool OnInit() override;
void onResidentMipsChanged() override;
void OnResidentMipsChanged() override;
void OnReleaseGPU() override;
};

View File

@@ -57,7 +57,7 @@ protected:
return false;
}
void onResidentMipsChanged() override
void OnResidentMipsChanged() override
{
}
};

View File

@@ -425,29 +425,19 @@ void GPUTextureVulkan::initHandles()
}
}
void GPUTextureVulkan::onResidentMipsChanged()
void GPUTextureVulkan::OnResidentMipsChanged()
{
// We support changing resident mip maps only for regular textures (render targets and depth buffers don't use that feature at all)
ASSERT(IsRegularTexture() && _handlesPerSlice.Count() == 1);
ASSERT(!IsVolume());
// Change view
auto& handle = _handlesPerSlice[0];
handle.Release();
// Update view
VkExtent3D extent;
extent.width = Width();
extent.height = Height();
extent.depth = Depth();
const int32 firstMipIndex = MipLevels() - ResidentMipLevels();
const int32 mipLevels = ResidentMipLevels();
if (IsCubeMap())
{
handle.Init(_device, this, _image, mipLevels, Format(), MultiSampleLevel(), extent, VK_IMAGE_VIEW_TYPE_CUBE, mipLevels, firstMipIndex, ArraySize());
}
else
{
handle.Init(_device, this, _image, mipLevels, Format(), MultiSampleLevel(), extent, VK_IMAGE_VIEW_TYPE_2D, mipLevels, firstMipIndex, ArraySize());
}
const VkImageViewType viewType = IsVolume() ? VK_IMAGE_VIEW_TYPE_3D : (IsCubeMap() ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D);
GPUTextureViewVulkan& view = IsVolume() ? _handleVolume : _handlesPerSlice[0];
view.Release();
view.Init(_device, this, _image, mipLevels, Format(), MultiSampleLevel(), extent, viewType, mipLevels, firstMipIndex, ArraySize());
}
void GPUTextureVulkan::OnReleaseGPU()

View File

@@ -182,7 +182,7 @@ protected:
// [GPUTexture]
bool OnInit() override;
void onResidentMipsChanged() override;
void OnResidentMipsChanged() override;
void OnReleaseGPU() override;
};

View File

@@ -688,7 +688,7 @@ void GlobalSignDistanceFieldPass::RenderDebug(RenderContext& renderContext, GPUC
void GlobalSignDistanceFieldPass::RasterizeModelSDF(Actor* actor, const ModelBase::SDFData& sdf, const Matrix& localToWorld, const BoundingBox& objectBounds)
{
if (!sdf.Texture)
if (!sdf.Texture || sdf.Texture->ResidentMipLevels() == 0)
return;
// Setup object data

View File

@@ -123,7 +123,7 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
*(uint8*)ptr = (uint8)v;
};
}
GPUTextureDescription textureDesc = GPUTextureDescription::New3D(resolution.X, resolution.Y, resolution.Z, format, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, mipCount);
GPUTextureDescription textureDesc = GPUTextureDescription::New3D(resolution.X, resolution.Y, resolution.Z, format, GPUTextureFlags::ShaderResource, mipCount);
if (outputSDF)
{
*outputSDF = sdf;