@@ -39,7 +39,7 @@ namespace Diligent
3939namespace
4040{
4141
42- bool VerifySparseTextureCompatibility (IRenderDevice* pDevice)
42+ bool VerifySparseTextureCompatibility (IRenderDevice* pDevice, const TextureDesc& Desc )
4343{
4444 VERIFY_EXPR (pDevice != nullptr );
4545
@@ -57,6 +57,13 @@ bool VerifySparseTextureCompatibility(IRenderDevice* pDevice)
5757 return false ;
5858 }
5959
60+ const auto & SparseInfo = pDevice->GetSparseTextureFormatInfo (Desc.Format , Desc.Type , Desc.SampleCount );
61+ if ((SparseInfo.BindFlags & Desc.BindFlags ) != Desc.BindFlags )
62+ {
63+ LOG_WARNING_MESSAGE (" The following bind flags requested for the sparse dynamic texture array are not supported by device: " , GetBindFlagsString (Desc.BindFlags & ~SparseInfo.BindFlags , " , " ));
64+ return false ;
65+ }
66+
6067 return true ;
6168}
6269
@@ -99,7 +106,7 @@ void DynamicTextureArray::CreateSparseTexture(IRenderDevice* pDevice)
99106 VERIFY_EXPR (pDevice != nullptr );
100107 VERIFY_EXPR (m_Desc.Usage == USAGE_SPARSE);
101108
102- if (!VerifySparseTextureCompatibility (pDevice))
109+ if (!VerifySparseTextureCompatibility (pDevice, m_Desc ))
103110 {
104111 LOG_WARNING_MESSAGE (" This device does not support capabilities required for sparse texture 2D arrays. USAGE_DEFAULT texture will be used instead." );
105112 m_Desc.Usage = USAGE_DEFAULT;
@@ -109,9 +116,17 @@ void DynamicTextureArray::CreateSparseTexture(IRenderDevice* pDevice)
109116 const auto & AdapterInfo = pDevice->GetAdapterInfo ();
110117
111118 {
119+ // Some implementations may return UINT64_MAX, so limit the maximum memory size per resource.
120+ // Some implementations will fail to create texture even if size is less than ResourceSpaceSize.
121+ const auto MaxMemorySize = std::min (Uint64{1 } << 40 , AdapterInfo.SparseResources .ResourceSpaceSize ) >> 1 ;
122+ const auto MipProps = GetMipLevelProperties (m_Desc, 0 );
123+
112124 auto TmpDesc = m_Desc;
113125 // Reserve the maximum available number of slices
114126 TmpDesc.ArraySize = AdapterInfo.Texture .MaxTexture2DArraySlices ;
127+ // Account for the maximum virtual space size
128+ TmpDesc.ArraySize = std::min (TmpDesc.ArraySize , StaticCast<Uint32>(MaxMemorySize / (MipProps.MipSize * 4 / 3 )));
129+
115130 pDevice->CreateTexture (TmpDesc, nullptr , &m_pTexture);
116131 DEV_CHECK_ERR (m_pTexture, " Failed to create sparse texture" );
117132 if (!m_pTexture)
@@ -122,7 +137,15 @@ void DynamicTextureArray::CreateSparseTexture(IRenderDevice* pDevice)
122137 }
123138
124139 const auto & TexSparseProps = m_pTexture->GetSparseProperties ();
125- const auto NumNormalMips = std::min (m_Desc.MipLevels , TexSparseProps.FirstMipInTail );
140+ if ((TexSparseProps.Flags & SPARSE_TEXTURE_FLAG_SINGLE_MIPTAIL) != 0 )
141+ {
142+ LOG_WARNING_MESSAGE (" This device requires single mip tail for the sparse texture 2D array, which is not suitable for the dynamic array." );
143+ m_pTexture.Release ();
144+ m_Desc.Usage = USAGE_DEFAULT;
145+ return ;
146+ }
147+
148+ const auto NumNormalMips = std::min (m_Desc.MipLevels , TexSparseProps.FirstMipInTail );
126149 // Compute the total number of blocks in one slice
127150 Uint64 NumBlocksInSlice = 0 ;
128151 for (Uint32 Mip = 0 ; Mip < NumNormalMips; ++Mip)
@@ -304,10 +327,11 @@ void DynamicTextureArray::ResizeSparseTexture(IDeviceContext* pContext)
304327 WaitFenceValue = m_NextBeforeResizeFenceValue++;
305328 pWaitFence = m_pBeforeResizeFence;
306329
307- pWaitFence->Signal (WaitFenceValue);
308330 BindMemAttribs.NumWaitFences = 1 ;
309331 BindMemAttribs.pWaitFenceValues = &WaitFenceValue;
310332 BindMemAttribs.ppWaitFences = &pWaitFence;
333+
334+ pContext->EnqueueSignal (m_pBeforeResizeFence, WaitFenceValue);
311335 }
312336
313337 Uint64 SignalFenceValue = 0 ;
0 commit comments