D3D Crash fix for large array textures

This commit is contained in:
Jack Andersen 2015-12-08 13:57:16 -10:00
parent 08655b7f93
commit 6062302816
3 changed files with 155 additions and 23 deletions

View File

@ -158,16 +158,31 @@ class D3D11TextureSA : public ITextureSA
D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_IMMUTABLE);
const uint8_t* dataIt = static_cast<const uint8_t*>(data);
D3D11_SUBRESOURCE_DATA upData[16] = {};
for (size_t i=0 ; i<layers && i<16 ; ++i)
if (layers > 16)
{
upData[i].pSysMem = dataIt;
upData[i].SysMemPitch = width * pixelPitch;
upData[i].SysMemSlicePitch = upData[i].SysMemPitch * height;
dataIt += upData[i].SysMemSlicePitch;
std::unique_ptr<D3D11_SUBRESOURCE_DATA[]> upData(new D3D11_SUBRESOURCE_DATA[layers]);
for (size_t i=0 ; i<layers ; ++i)
{
upData[i].pSysMem = dataIt;
upData[i].SysMemPitch = width * pixelPitch;
upData[i].SysMemSlicePitch = upData[i].SysMemPitch * height;
dataIt += upData[i].SysMemSlicePitch;
}
ThrowIfFailed(ctx->m_dev->CreateTexture2D(&desc, upData.get(), &m_tex));
}
else
{
D3D11_SUBRESOURCE_DATA upData[16] = {};
for (size_t i=0 ; i<layers ; ++i)
{
upData[i].pSysMem = dataIt;
upData[i].SysMemPitch = width * pixelPitch;
upData[i].SysMemSlicePitch = upData[i].SysMemPitch * height;
dataIt += upData[i].SysMemSlicePitch;
}
ThrowIfFailed(ctx->m_dev->CreateTexture2D(&desc, upData, &m_tex));
}
ThrowIfFailed(ctx->m_dev->CreateTexture2D(&desc, upData, &m_tex));
ThrowIfFailed(ctx->m_dev->CreateShaderResourceView(m_tex.Get(),
&CD3D11_SHADER_RESOURCE_VIEW_DESC(m_tex.Get(), D3D_SRV_DIMENSION_TEXTURE2DARRAY, pixelFmt), &m_srv));
}
@ -628,6 +643,7 @@ struct D3D11CommandQueue : IGraphicsCommandQueue
break;
self->m_drawBuf = self->m_completeBuf;
/* Process dynamic loads */
ID3D11CommandList* list = self->m_dynamicList.Get();
self->m_ctx->m_devCtx->ExecuteCommandList(list, false);
self->m_dynamicList.Reset();
@ -1061,8 +1077,14 @@ void D3D11CommandQueue::execute()
ThrowIfFailed(m_deferredCtx->FinishCommandList(false, &m_cmdLists[m_fillBuf]));
m_workDoPresent[m_fillBuf] = m_doPresent;
m_doPresent = nullptr;
/* Wait for worker thread to become ready */
std::unique_lock<std::mutex> lk(m_mt);
/* Gather dynamic uploads for worker thread */
ThrowIfFailed(m_dynamicCtx->FinishCommandList(false, &m_dynamicList));
/* Ready for next frame */
m_completeBuf = m_fillBuf;
for (size_t i=0 ; i<3 ; ++i)
{
@ -1071,6 +1093,8 @@ void D3D11CommandQueue::execute()
m_fillBuf = i;
break;
}
/* Return control to worker thread */
lk.unlock();
m_cv.notify_one();
}

View File

@ -243,17 +243,33 @@ class D3D12TextureSA : public ITextureSA
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_tex));
const uint8_t* dataIt = static_cast<const uint8_t*>(data);
D3D12_SUBRESOURCE_DATA upData[16] = {};
for (size_t i=0 ; i<layers && i<16 ; ++i)
{
upData[i].pData = dataIt;
upData[i].RowPitch = width * pxPitch;
upData[i].SlicePitch = upData[i].RowPitch * height;
dataIt += upData[i].SlicePitch;
}
if (!PrepSubresources<16>(ctx->m_dev.Get(), &m_gpuDesc, m_tex.Get(), 0, 0, layers, upData))
Log.report(LogVisor::FatalError, "error preparing resource for upload");
if (layers > 16)
{
std::unique_ptr<D3D12_SUBRESOURCE_DATA[]> upData(new D3D12_SUBRESOURCE_DATA[layers]);
for (size_t i=0 ; i<layers ; ++i)
{
upData[i].pData = dataIt;
upData[i].RowPitch = width * pxPitch;
upData[i].SlicePitch = upData[i].RowPitch * height;
dataIt += upData[i].SlicePitch;
}
if (!PrepSubresources(ctx->m_dev.Get(), &m_gpuDesc, m_tex.Get(), 0, 0, layers, upData.get()))
Log.report(LogVisor::FatalError, "error preparing resource for upload");
}
else
{
D3D12_SUBRESOURCE_DATA upData[16] = {};
for (size_t i=0 ; i<layers ; ++i)
{
upData[i].pData = dataIt;
upData[i].RowPitch = width * pxPitch;
upData[i].SlicePitch = upData[i].RowPitch * height;
dataIt += upData[i].SlicePitch;
}
if (!PrepSubresources<16>(ctx->m_dev.Get(), &m_gpuDesc, m_tex.Get(), 0, 0, layers, upData))
Log.report(LogVisor::FatalError, "error preparing resource for upload");
}
}
public:
ComPtr<ID3D12Resource> m_tex;
@ -266,9 +282,18 @@ public:
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr, __uuidof(ID3D12Resource), &m_gpuTex));
CommandSubresourcesTransfer<16>(ctx->m_dev.Get(), ctx->m_loadlist.Get(), m_gpuTex.Get(), m_tex.Get(), 0, 0, m_gpuDesc.DepthOrArraySize);
ctx->m_loadlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_gpuTex.Get(),
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
if (m_gpuDesc.DepthOrArraySize > 16)
{
CommandSubresourcesTransfer(ctx->m_dev.Get(), ctx->m_loadlist.Get(), m_gpuTex.Get(), m_tex.Get(), 0, 0, m_gpuDesc.DepthOrArraySize);
ctx->m_loadlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_gpuTex.Get(),
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
}
else
{
CommandSubresourcesTransfer<16>(ctx->m_dev.Get(), ctx->m_loadlist.Get(), m_gpuTex.Get(), m_tex.Get(), 0, 0, m_gpuDesc.DepthOrArraySize);
ctx->m_loadlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_gpuTex.Get(),
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
}
return NextHeapOffset(offset, ctx->m_dev->GetResourceAllocationInfo(0, 1, &m_gpuDesc));
}

View File

@ -1540,15 +1540,48 @@ inline UINT64 PrepSubresources(
}
//------------------------------------------------------------------------------------------------
// Stack-allocating UpdateSubresources implementation
// Heap-allocating PrepSubresources implementation
inline UINT64 PrepSubresources(
_In_ ID3D12Device* pDevice,
_In_ D3D12_RESOURCE_DESC* DestinationDesc,
_In_ ID3D12Resource* pIntermediate,
UINT64 IntermediateOffset,
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
_In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)
{
UINT64 RequiredSize = 0;
UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
if (MemToAlloc > SIZE_MAX)
{
return 0;
}
void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));
if (pMem == NULL)
{
return 0;
}
D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);
UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
pDevice->GetCopyableFootprints(DestinationDesc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);
UINT64 result = PrepSubresources(pDevice, DestinationDesc, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);
HeapFree(GetProcessHeap(), 0, pMem);
return result;
}
//------------------------------------------------------------------------------------------------
// Stack-allocating PrepSubresources implementation
template <UINT MaxSubresources>
inline UINT64 PrepSubresources(
_In_ ID3D12Device* pDevice,
_In_ D3D12_RESOURCE_DESC* DestinationDesc,
_In_ ID3D12Resource* pIntermediate,
UINT64 IntermediateOffset,
_In_range_(0, MaxSubresources) UINT FirstSubresource,
_In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
_In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)
{
UINT64 RequiredSize = 0;
@ -1561,6 +1594,56 @@ inline UINT64 PrepSubresources(
return PrepSubresources(pDevice, DestinationDesc, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);
}
//------------------------------------------------------------------------------------------------
// Heap-allocating CommandSubresourcesTransfer implementation
inline void CommandSubresourcesTransfer(
_In_ ID3D12Device* pDevice,
_In_ ID3D12GraphicsCommandList* pCmdList,
_In_ ID3D12Resource* pDestinationResource,
_In_ ID3D12Resource* pIntermediate,
UINT64 IntermediateOffset,
_In_range_(0, MaxSubresources) UINT FirstSubresource,
_In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources)
{
UINT64 RequiredSize = 0;
UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
if (MemToAlloc > SIZE_MAX)
{
return;
}
void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));
if (pMem == NULL)
{
return;
}
D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);
UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();
pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);
if (Desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
{
CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) );
pCmdList->CopyBufferRegion(
pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);
}
else
{
for (UINT i = 0; i < NumSubresources; ++i)
{
CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);
CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);
pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);
}
}
HeapFree(GetProcessHeap(), 0, pMem);
}
//------------------------------------------------------------------------------------------------
// Stack-allocating CommandSubresourcesTransfer implementation
template <UINT MaxSubresources>
inline void CommandSubresourcesTransfer(
_In_ ID3D12Device* pDevice,