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()) if (_residentMipLevels == count || !IsRegularTexture())
return; return;
_residentMipLevels = count; _residentMipLevels = count;
onResidentMipsChanged(); OnResidentMipsChanged();
} }

View File

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

View File

@@ -109,37 +109,37 @@ bool GPUTextureDX11::OnInit()
return false; 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) const int32 firstMipIndex = MipLevels() - ResidentMipLevels();
ASSERT(IsRegularTexture() && _handlesPerSlice.Count() == 1); const int32 mipLevels = ResidentMipLevels();
ASSERT(!IsVolume());
// Fill description
D3D11_SHADER_RESOURCE_VIEW_DESC srDesc; D3D11_SHADER_RESOURCE_VIEW_DESC srDesc;
srDesc.Format = _dxgiFormatSRV; srDesc.Format = _dxgiFormatSRV;
if (IsCubeMap()) if (IsCubeMap())
{ {
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
srDesc.TextureCube.MostDetailedMip = MipLevels() - ResidentMipLevels(); srDesc.TextureCube.MostDetailedMip = firstMipIndex;
srDesc.TextureCube.MipLevels = ResidentMipLevels(); srDesc.TextureCube.MipLevels = mipLevels;
}
else if (IsVolume())
{
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
srDesc.Texture3D.MostDetailedMip = firstMipIndex;
srDesc.Texture3D.MipLevels = mipLevels;
} }
else else
{ {
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srDesc.Texture2D.MostDetailedMip = MipLevels() - ResidentMipLevels(); srDesc.Texture2D.MostDetailedMip = firstMipIndex;
srDesc.Texture2D.MipLevels = ResidentMipLevels(); srDesc.Texture2D.MipLevels = mipLevels;
} }
// Create new view
ID3D11ShaderResourceView* srView; ID3D11ShaderResourceView* srView;
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateShaderResourceView(_resource, &srDesc, &srView)); VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateShaderResourceView(_resource, &srDesc, &srView));
GPUTextureViewDX11& view = IsVolume() ? _handleVolume : _handlesPerSlice[0];
// Change view if (view.GetParent() == nullptr)
if (_handlesPerSlice[0].GetParent() == nullptr) view.Init(this, nullptr, srView, nullptr, nullptr, Format(), MultiSampleLevel());
_handlesPerSlice[0].Init(this, nullptr, srView, nullptr, nullptr, Format(), MultiSampleLevel());
else else
_handlesPerSlice[0].SetSRV(srView); view.SetSRV(srView);
} }
void GPUTextureDX11::OnReleaseGPU() void GPUTextureDX11::OnReleaseGPU()

View File

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

View File

@@ -208,36 +208,39 @@ bool GPUTextureDX12::OnInit()
return false; 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) const int32 firstMipIndex = MipLevels() - ResidentMipLevels();
ASSERT(IsRegularTexture() && _handlesPerSlice.Count() == 1); const int32 mipLevels = ResidentMipLevels();
ASSERT(!IsVolume());
// Fill description
D3D12_SHADER_RESOURCE_VIEW_DESC srDesc; D3D12_SHADER_RESOURCE_VIEW_DESC srDesc;
srDesc.Format = _dxgiFormatSRV; srDesc.Format = _dxgiFormatSRV;
srDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
if (IsCubeMap()) if (IsCubeMap())
{ {
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
srDesc.TextureCube.MostDetailedMip = MipLevels() - ResidentMipLevels(); srDesc.TextureCube.MostDetailedMip = firstMipIndex;
srDesc.TextureCube.MipLevels = ResidentMipLevels(); srDesc.TextureCube.MipLevels = mipLevels;
srDesc.TextureCube.ResourceMinLODClamp = 0; 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 else
{ {
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srDesc.Texture2D.MostDetailedMip = MipLevels() - ResidentMipLevels(); srDesc.Texture2D.MostDetailedMip = firstMipIndex;
srDesc.Texture2D.MipLevels = ResidentMipLevels(); srDesc.Texture2D.MipLevels = mipLevels;
srDesc.Texture2D.PlaneSlice = 0; srDesc.Texture2D.PlaneSlice = 0;
srDesc.Texture2D.ResourceMinLODClamp = 0; srDesc.Texture2D.ResourceMinLODClamp = 0;
} }
GPUTextureViewDX12& view = IsVolume() ? _handleVolume : _handlesPerSlice[0];
// Change view if (view.GetParent() == nullptr)
if (_handlesPerSlice[0].GetParent() == nullptr) view.Init(this, _device, this, Format(), MultiSampleLevel());
_handlesPerSlice[0].Init(this, _device, this, Format(), MultiSampleLevel()); view.SetSRV(srDesc);
_handlesPerSlice[0].SetSRV(srDesc);
} }
void GPUTextureDX12::OnReleaseGPU() void GPUTextureDX12::OnReleaseGPU()

View File

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

View File

@@ -57,7 +57,7 @@ protected:
return false; 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) // Update view
ASSERT(IsRegularTexture() && _handlesPerSlice.Count() == 1);
ASSERT(!IsVolume());
// Change view
auto& handle = _handlesPerSlice[0];
handle.Release();
VkExtent3D extent; VkExtent3D extent;
extent.width = Width(); extent.width = Width();
extent.height = Height(); extent.height = Height();
extent.depth = Depth(); extent.depth = Depth();
const int32 firstMipIndex = MipLevels() - ResidentMipLevels(); const int32 firstMipIndex = MipLevels() - ResidentMipLevels();
const int32 mipLevels = ResidentMipLevels(); const int32 mipLevels = ResidentMipLevels();
if (IsCubeMap()) 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];
handle.Init(_device, this, _image, mipLevels, Format(), MultiSampleLevel(), extent, VK_IMAGE_VIEW_TYPE_CUBE, mipLevels, firstMipIndex, ArraySize()); view.Release();
} view.Init(_device, this, _image, mipLevels, Format(), MultiSampleLevel(), extent, viewType, mipLevels, firstMipIndex, ArraySize());
else
{
handle.Init(_device, this, _image, mipLevels, Format(), MultiSampleLevel(), extent, VK_IMAGE_VIEW_TYPE_2D, mipLevels, firstMipIndex, ArraySize());
}
} }
void GPUTextureVulkan::OnReleaseGPU() void GPUTextureVulkan::OnReleaseGPU()

View File

@@ -182,7 +182,7 @@ protected:
// [GPUTexture] // [GPUTexture]
bool OnInit() override; bool OnInit() override;
void onResidentMipsChanged() override; void OnResidentMipsChanged() override;
void OnReleaseGPU() 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) 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; return;
// Setup object data // Setup object data

View File

@@ -123,7 +123,7 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
*(uint8*)ptr = (uint8)v; *(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) if (outputSDF)
{ {
*outputSDF = sdf; *outputSDF = sdf;