diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index a94a768..10cb864 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -158,16 +158,31 @@ class D3D11TextureSA : public ITextureSA D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_IMMUTABLE); const uint8_t* dataIt = static_cast(data); - D3D11_SUBRESOURCE_DATA upData[16] = {}; - for (size_t i=0 ; i 16) { - upData[i].pSysMem = dataIt; - upData[i].SysMemPitch = width * pixelPitch; - upData[i].SysMemSlicePitch = upData[i].SysMemPitch * height; - dataIt += upData[i].SysMemSlicePitch; + std::unique_ptr upData(new D3D11_SUBRESOURCE_DATA[layers]); + for (size_t i=0 ; im_dev->CreateTexture2D(&desc, upData.get(), &m_tex)); + } + else + { + D3D11_SUBRESOURCE_DATA upData[16] = {}; + for (size_t i=0 ; im_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 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(); } diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index 28d4eb7..84a5f25 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -243,17 +243,33 @@ class D3D12TextureSA : public ITextureSA D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_tex)); const uint8_t* dataIt = static_cast(data); - D3D12_SUBRESOURCE_DATA upData[16] = {}; - for (size_t i=0 ; i(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 upData(new D3D12_SUBRESOURCE_DATA[layers]); + for (size_t i=0 ; im_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(ctx->m_dev.Get(), &m_gpuDesc, m_tex.Get(), 0, 0, layers, upData)) + Log.report(LogVisor::FatalError, "error preparing resource for upload"); + } } public: ComPtr 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)); } diff --git a/lib/graphicsdev/d3dx12.h b/lib/graphicsdev/d3dx12.h index f63c441..adacc89 100644 --- a/lib/graphicsdev/d3dx12.h +++ b/lib/graphicsdev/d3dx12.h @@ -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(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources; + if (MemToAlloc > SIZE_MAX) + { + return 0; + } + void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast(MemToAlloc)); + if (pMem == NULL) + { + return 0; + } + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast(pMem); + UINT64* pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); + UINT* pNumRows = reinterpret_cast(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 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(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources; + if (MemToAlloc > SIZE_MAX) + { + return; + } + void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast(MemToAlloc)); + if (pMem == NULL) + { + return; + } + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast(pMem); + UINT64* pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); + UINT* pNumRows = reinterpret_cast(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 inline void CommandSubresourcesTransfer( _In_ ID3D12Device* pDevice,