summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-07-07 22:40:03 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-07-07 22:40:03 +0000
commit6896a3c7bae82319682f3bb0af80c20a0b907a1d (patch)
treebf7e822be87f5a9dcfc9692d7aea3b622a205c77 /Graphics/GraphicsEngineD3D12
parentFixed Vulkan swapchain present error when window is minimized (diff)
downloadDiligentCore-6896a3c7bae82319682f3bb0af80c20a0b907a1d.tar.gz
DiligentCore-6896a3c7bae82319682f3bb0af80c20a0b907a1d.zip
Implemented mipmap generation in Vulkan
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/include/GenerateMips.h2
-rw-r--r--Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsCS.hlsli9
-rw-r--r--Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp143
3 files changed, 76 insertions, 78 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/GenerateMips.h b/Graphics/GraphicsEngineD3D12/include/GenerateMips.h
index 8bb1266a..124dcc6e 100644
--- a/Graphics/GraphicsEngineD3D12/include/GenerateMips.h
+++ b/Graphics/GraphicsEngineD3D12/include/GenerateMips.h
@@ -52,7 +52,7 @@ namespace Diligent
public:
GenerateMipsHelper(ID3D12Device *pd3d12Device);
- void GenerateMips(class RenderDeviceD3D12Impl *pRenderDeviceD3D12, class TextureViewD3D12Impl *pTexView, class CommandContext &Ctx);
+ void GenerateMips(class RenderDeviceD3D12Impl *pRenderDeviceD3D12, class TextureViewD3D12Impl *pTexView, class CommandContext &Ctx)const;
private:
CComPtr<ID3D12RootSignature> m_pGenerateMipsRS;
diff --git a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsCS.hlsli b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsCS.hlsli
index 56ac04be..d9c9c0c0 100644
--- a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsCS.hlsli
+++ b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsCS.hlsli
@@ -35,9 +35,9 @@ SamplerState BilinearClamp : register(s0);
cbuffer CB : register(b0)
{
- uint SrcMipLevel; // Texture level of source mip
- uint NumMipLevels; // Number of OutMips to write: [1, 4]
- uint ArraySlice; // Texture array slice
+ uint SrcMipLevel; // Texture level of source mip
+ uint NumMipLevels; // Number of OutMips to write: [1, 4]
+ uint FirstArraySlice;
uint Dummy;
float2 TexelSize; // 1.0 / OutMip1.Dimensions
}
@@ -90,7 +90,8 @@ void main( uint GI : SV_GroupIndex, uint3 DTid : SV_DispatchThreadID )
SrcTex.GetDimensions(DstMipSize.x, DstMipSize.y, Elements);
DstMipSize >>= SrcMipLevel;
bool IsValidThread = all(DTid.xy < DstMipSize);
-
+ uint ArraySlice = FirstArraySlice + DTid.z;
+
float4 Src1 = 0;
if( IsValidThread )
{
diff --git a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp
index d6ec20ec..f0377fe1 100644
--- a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp
@@ -103,7 +103,7 @@ namespace Diligent
CreatePSO(m_pGenerateMipsGammaPSO[3], g_pGenerateMipsGammaOddCS);
}
- void GenerateMipsHelper::GenerateMips(RenderDeviceD3D12Impl* pRenderDeviceD3D12, TextureViewD3D12Impl* pTexView, CommandContext& Ctx)
+ void GenerateMipsHelper::GenerateMips(RenderDeviceD3D12Impl* pRenderDeviceD3D12, TextureViewD3D12Impl* pTexView, CommandContext& Ctx)const
{
auto &ComputeCtx = Ctx.AsComputeContext();
ComputeCtx.SetRootSignature(m_pGenerateMipsRS);
@@ -116,80 +116,77 @@ namespace Diligent
auto *pd3d12Device = pRenderDeviceD3D12->GetD3D12Device();
const auto &ViewDesc = pTexView->GetDesc();
- for (Uint32 ArrSlice = ViewDesc.FirstArraySlice; ArrSlice < ViewDesc.FirstArraySlice + ViewDesc.NumArraySlices; ++ArrSlice)
+ for (uint32_t TopMip = 0; TopMip < TexDesc.MipLevels - 1; )
{
- for (uint32_t TopMip = 0; TopMip < TexDesc.MipLevels - 1; )
+ uint32_t SrcWidth = std::max(TexDesc.Width >> TopMip, 1u);
+ uint32_t SrcHeight = std::max(TexDesc.Height >> TopMip, 1u);
+ uint32_t DstWidth = std::max(SrcWidth >> 1, 1u);
+ uint32_t DstHeight = std::max(SrcHeight >> 1, 1u);
+
+ // Determine if the first downsample is more than 2:1. This happens whenever
+ // the source width or height is odd.
+ uint32_t NonPowerOfTwo = (SrcWidth & 1) | (SrcHeight & 1) << 1;
+ if (TexDesc.Format == TEX_FORMAT_RGBA8_UNORM_SRGB)
+ ComputeCtx.SetPipelineState(m_pGenerateMipsGammaPSO[NonPowerOfTwo]);
+ else
+ ComputeCtx.SetPipelineState(m_pGenerateMipsLinearPSO[NonPowerOfTwo]);
+
+ // We can downsample up to four times, but if the ratio between levels is not
+ // exactly 2:1, we have to shift our blend weights, which gets complicated or
+ // expensive. Maybe we can update the code later to compute sample weights for
+ // each successive downsample. We use _BitScanForward to count number of zeros
+ // in the low bits. Zeros indicate we can divide by two without truncating.
+ uint32_t AdditionalMips;
+ _BitScanForward((unsigned long*)&AdditionalMips, DstWidth | DstHeight);
+ uint32_t NumMips = 1 + (AdditionalMips > 3 ? 3 : AdditionalMips);
+ if (TopMip + NumMips > TexDesc.MipLevels - 1)
+ NumMips = TexDesc.MipLevels - 1 - TopMip;
+
+ // These are clamped to 1 after computing additional mips because clamped
+ // dimensions should not limit us from downsampling multiple times. (E.g.
+ // 16x1 -> 8x1 -> 4x1 -> 2x1 -> 1x1.)
+ if (DstWidth == 0)
+ DstWidth = 1;
+ if (DstHeight == 0)
+ DstHeight = 1;
+
+ D3D12_DESCRIPTOR_HEAP_TYPE HeapType = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+ auto DescriptorAlloc = Ctx.AllocateDynamicGPUVisibleDescriptor(HeapType, 5);
+ CommandContext::ShaderDescriptorHeaps Heaps(DescriptorAlloc.GetDescriptorHeap());
+ ComputeCtx.SetDescriptorHeaps(Heaps);
+ Ctx.GetCommandList()->SetComputeRootDescriptorTable(1, DescriptorAlloc.GetGpuHandle(0));
+ Ctx.GetCommandList()->SetComputeRootDescriptorTable(2, DescriptorAlloc.GetGpuHandle(1));
+ struct RootCBData
{
- uint32_t SrcWidth = TexDesc.Width >> TopMip;
- uint32_t SrcHeight = TexDesc.Height >> TopMip;
- uint32_t DstWidth = SrcWidth >> 1;
- uint32_t DstHeight = SrcHeight >> 1;
-
- // Determine if the first downsample is more than 2:1. This happens whenever
- // the source width or height is odd.
- uint32_t NonPowerOfTwo = (SrcWidth & 1) | (SrcHeight & 1) << 1;
- if (TexDesc.Format == TEX_FORMAT_RGBA8_UNORM_SRGB)
- ComputeCtx.SetPipelineState(m_pGenerateMipsGammaPSO[NonPowerOfTwo]);
- else
- ComputeCtx.SetPipelineState(m_pGenerateMipsLinearPSO[NonPowerOfTwo]);
-
- // We can downsample up to four times, but if the ratio between levels is not
- // exactly 2:1, we have to shift our blend weights, which gets complicated or
- // expensive. Maybe we can update the code later to compute sample weights for
- // each successive downsample. We use _BitScanForward to count number of zeros
- // in the low bits. Zeros indicate we can divide by two without truncating.
- uint32_t AdditionalMips;
- _BitScanForward((unsigned long*)&AdditionalMips, DstWidth | DstHeight);
- uint32_t NumMips = 1 + (AdditionalMips > 3 ? 3 : AdditionalMips);
- if (TopMip + NumMips > TexDesc.MipLevels - 1)
- NumMips = TexDesc.MipLevels - 1 - TopMip;
-
- // These are clamped to 1 after computing additional mips because clamped
- // dimensions should not limit us from downsampling multiple times. (E.g.
- // 16x1 -> 8x1 -> 4x1 -> 2x1 -> 1x1.)
- if (DstWidth == 0)
- DstWidth = 1;
- if (DstHeight == 0)
- DstHeight = 1;
-
- D3D12_DESCRIPTOR_HEAP_TYPE HeapType = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
- auto DescriptorAlloc = Ctx.AllocateDynamicGPUVisibleDescriptor(HeapType, 5);
- CommandContext::ShaderDescriptorHeaps Heaps(DescriptorAlloc.GetDescriptorHeap());
- ComputeCtx.SetDescriptorHeaps(Heaps);
- Ctx.GetCommandList()->SetComputeRootDescriptorTable(1, DescriptorAlloc.GetGpuHandle(0));
- Ctx.GetCommandList()->SetComputeRootDescriptorTable(2, DescriptorAlloc.GetGpuHandle(1));
- struct RootCBData
- {
- Uint32 SrcMipLevel; // Texture level of source mip
- Uint32 NumMipLevels; // Number of OutMips to write: [1, 4]
- Uint32 ArraySlice;
- Uint32 Dummy;
- float TexelSize[2]; // 1.0 / OutMip1.Dimensions
- }CBData = { TopMip, NumMips, ArrSlice, 0, 1.0f / static_cast<float>(DstWidth), 1.0f / static_cast<float>(DstHeight) };
- Ctx.GetCommandList()->SetComputeRoot32BitConstants(0, 6, &CBData, 0);
-
- // TODO: Shouldn't we transition top mip to shader resource state?
- D3D12_CPU_DESCRIPTOR_HANDLE DstDescriptorRange = DescriptorAlloc.GetCpuHandle();
- const Uint32 MaxMipsHandledByCS = 4; // Max number of mip levels processed by one CS shader invocation
- UINT DstRangeSize = 1 + MaxMipsHandledByCS;
- D3D12_CPU_DESCRIPTOR_HANDLE SrcDescriptorRanges[5] = {};
- SrcDescriptorRanges[0] = SRVDescriptorHandle;
- UINT SrcRangeSizes[5] = { 1,1,1,1,1 };
- // On Resource Binding Tier 2 hardware, all descriptor tables of type CBV and UAV declared in the set
- // Root Signature must be populated and initialized, even if the shaders do not need the descriptor.
- // So we must populate all 4 slots even though we may actually process less than 4 mip levels
- // Copy top mip level UAV descriptor handle to all unused slots
- for (Uint32 u = 0; u < MaxMipsHandledByCS; ++u)
- SrcDescriptorRanges[1 + u] = pTexD3D12->GetMipLevelUAV(std::min(TopMip + u + 1, TexDesc.MipLevels - 1));
-
- pd3d12Device->CopyDescriptors(1, &DstDescriptorRange, &DstRangeSize, 1 + MaxMipsHandledByCS, SrcDescriptorRanges, SrcRangeSizes, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
-
- ComputeCtx.Dispatch((DstWidth + 7) / 8, (DstHeight + 7) / 8);
-
- Ctx.InsertUAVBarrier(*pTexD3D12, *pTexD3D12);
-
- TopMip += NumMips;
- }
+ Uint32 SrcMipLevel; // Texture level of source mip
+ Uint32 NumMipLevels; // Number of OutMips to write: [1, 4]
+ Uint32 FirstArraySlice;
+ Uint32 Dummy;
+ float TexelSize[2]; // 1.0 / OutMip1.Dimensions
+ }CBData = { TopMip, NumMips, ViewDesc.FirstArraySlice, 0, 1.0f / static_cast<float>(DstWidth), 1.0f / static_cast<float>(DstHeight) };
+ Ctx.GetCommandList()->SetComputeRoot32BitConstants(0, 6, &CBData, 0);
+
+ // TODO: Shouldn't we transition top mip to shader resource state?
+ D3D12_CPU_DESCRIPTOR_HANDLE DstDescriptorRange = DescriptorAlloc.GetCpuHandle();
+ const Uint32 MaxMipsHandledByCS = 4; // Max number of mip levels processed by one CS shader invocation
+ UINT DstRangeSize = 1 + MaxMipsHandledByCS;
+ D3D12_CPU_DESCRIPTOR_HANDLE SrcDescriptorRanges[5] = {};
+ SrcDescriptorRanges[0] = SRVDescriptorHandle;
+ UINT SrcRangeSizes[5] = { 1,1,1,1,1 };
+ // On Resource Binding Tier 2 hardware, all descriptor tables of type CBV and UAV declared in the set
+ // Root Signature must be populated and initialized, even if the shaders do not need the descriptor.
+ // So we must populate all 4 slots even though we may actually process less than 4 mip levels
+ // Copy top mip level UAV descriptor handle to all unused slots
+ for (Uint32 u = 0; u < MaxMipsHandledByCS; ++u)
+ SrcDescriptorRanges[1 + u] = pTexD3D12->GetMipLevelUAV(std::min(TopMip + u + 1, TexDesc.MipLevels - 1));
+
+ pd3d12Device->CopyDescriptors(1, &DstDescriptorRange, &DstRangeSize, 1 + MaxMipsHandledByCS, SrcDescriptorRanges, SrcRangeSizes, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+
+ ComputeCtx.Dispatch((DstWidth + 7) / 8, (DstHeight + 7) / 8, ViewDesc.NumArraySlices);
+
+ Ctx.InsertUAVBarrier(*pTexD3D12, *pTexD3D12);
+
+ TopMip += NumMips;
}
}
}