Skip to content

Commit 3ac2245

Browse files
GPUUploadManager: add destination buffer/texture state transition mode parameter
1 parent a52dc0d commit 3ac2245

File tree

3 files changed

+33
-15
lines changed

3 files changed

+33
-15
lines changed

Graphics/GraphicsTools/include/GPUUploadManagerImpl.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ class GPUUploadManagerImpl final : public ObjectBase<IGPUUploadManager>
248248
GPUBufferUploadEnqueuedCallbackType UploadEnqueued = nullptr;
249249
void* pUploadEnqueuedData = nullptr;
250250

251+
RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode = RESOURCE_STATE_TRANSITION_MODE_NONE;
252+
251253
Uint32 SrcOffset = 0;
252254
Uint32 DstOffset = 0;
253255
Uint32 NumBytes = 0;
@@ -259,6 +261,8 @@ class GPUUploadManagerImpl final : public ObjectBase<IGPUUploadManager>
259261
{
260262
RefCntAutoPtr<ITexture> pDstTexture;
261263

264+
RESOURCE_STATE_TRANSITION_MODE DstTextureTransitionMode = RESOURCE_STATE_TRANSITION_MODE_NONE;
265+
262266
// For Direct3D11, coordinates of the source region within the staging texture.
263267
Uint32 SrcX = 0;
264268
Uint32 SrcY = 0;
@@ -282,7 +286,7 @@ class GPUUploadManagerImpl final : public ObjectBase<IGPUUploadManager>
282286
using PendingOp = std::variant<PendingBufferOp, PendingTextureOp>;
283287
MPSCQueue<PendingOp> m_PendingOps;
284288

285-
static std::atomic<int> sm_PageCounter;
289+
static std::atomic<Uint32> sm_PageCounter;
286290
};
287291

288292
private:

Graphics/GraphicsTools/interface/GPUUploadManager.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ struct ScheduleBufferUpdateInfo
161161
/// Otherwise, this buffer will be used as the destination for the copy operation
162162
IBuffer* pDstBuffer DEFAULT_INITIALIZER(nullptr);
163163

164+
/// State transition mode for the destination buffer. This parameter is ignored if CopyBuffer callback is provided,
165+
/// and the callback is expected to perform any necessary state transitions itself.
166+
RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
167+
164168
/// Offset in the destination buffer where the update will be applied.
165169
/// If CopyBuffer callback is provided, this parameter will be ignored, and the callback must
166170
/// perform the copy operation itself.
@@ -375,6 +379,10 @@ struct ScheduleTextureUpdateInfo
375379
/// Otherwise, this texture will be used as the destination for the copy operation
376380
ITexture* pDstTexture DEFAULT_INITIALIZER(nullptr);
377381

382+
/// State transition mode for the destination texture. This parameter is ignored if CopyTexture/CopyD3D11Texture callback is provided,
383+
/// and the callback is expected to perform any necessary state transitions itself.
384+
RESOURCE_STATE_TRANSITION_MODE DstTextureTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
385+
378386
/// Destination mip level in the texture where the update will be applied.
379387
/// This parameter is ignored if CopyTexture callback is provided.
380388
Uint32 DstMipLevel DEFAULT_INITIALIZER(0);

Graphics/GraphicsTools/src/GPUUploadManagerImpl.cpp

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ bool GPUUploadManagerImpl::Page::Writer::ScheduleTextureUpdate(const ScheduleTex
6161
{
6262
if (m_pPage == nullptr)
6363
{
64-
UNEXPECTED("Attempting to schedule a buffer update with an invalid writer.");
64+
UNEXPECTED("Attempting to schedule a texture update with an invalid writer.");
6565
return false;
6666
}
6767

@@ -114,6 +114,7 @@ GPUUploadManagerImpl::Page::StagingTextureAtlas::~StagingTextureAtlas()
114114

115115
void* GPUUploadManagerImpl::Page::StagingTextureAtlas::Map(IDeviceContext* pContext)
116116
{
117+
pContext->TransitionResourceState({pTex, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_COPY_SOURCE, STATE_TRANSITION_FLAG_UPDATE_STATE});
117118
MappedTextureSubresource MappedData;
118119
pContext->MapTextureSubresource(pTex, 0, 0, MAP_WRITE, MAP_FLAG_NONE, nullptr, MappedData);
119120
RowStride = static_cast<Uint32>(MappedData.Stride);
@@ -135,7 +136,7 @@ void GPUUploadManagerImpl::Page::StagingTextureAtlas::Reset()
135136

136137
DynamicAtlasManager::Region GPUUploadManagerImpl::Page::StagingTextureAtlas::Allocate(Uint32 Width, Uint32 Height)
137138
{
138-
std::lock_guard<std::mutex> Lock(MgrMtx);
139+
std::lock_guard<std::mutex> Lock{MgrMtx};
139140
return Mgr.Allocate(Width, Height);
140141
}
141142

@@ -148,10 +149,12 @@ GPUUploadManagerImpl::Page::Page(Uint32 Size, bool PersistentMapped) noexcept :
148149
inline bool PersistentMapSupported(IRenderDevice* pDevice)
149150
{
150151
RENDER_DEVICE_TYPE DeviceType = pDevice->GetDeviceInfo().Type;
151-
return DeviceType == RENDER_DEVICE_TYPE_D3D12 || DeviceType == RENDER_DEVICE_TYPE_VULKAN;
152+
return (DeviceType == RENDER_DEVICE_TYPE_D3D12 ||
153+
DeviceType == RENDER_DEVICE_TYPE_VULKAN ||
154+
DeviceType == RENDER_DEVICE_TYPE_METAL);
152155
}
153156

154-
std::atomic<int> GPUUploadManagerImpl::Page::sm_PageCounter{0};
157+
std::atomic<Uint32> GPUUploadManagerImpl::Page::sm_PageCounter{0};
155158

156159
GPUUploadManagerImpl::Page::Page(UploadStream& Stream, IRenderDevice* pDevice, Uint32 Size) :
157160
m_pStream{&Stream},
@@ -354,9 +357,10 @@ bool GPUUploadManagerImpl::Page::ScheduleBufferUpdate(const ScheduleBufferUpdate
354357
}
355358

356359
PendingBufferOp Op;
357-
Op.pDstBuffer = UpdateInfo.pDstBuffer;
358-
Op.CopyBuffer = UpdateInfo.CopyBuffer;
359-
Op.pCopyBufferData = UpdateInfo.pCopyBufferData;
360+
Op.pDstBuffer = UpdateInfo.pDstBuffer;
361+
Op.DstBufferTransitionMode = UpdateInfo.DstBufferTransitionMode;
362+
Op.CopyBuffer = UpdateInfo.CopyBuffer;
363+
Op.pCopyBufferData = UpdateInfo.pCopyBufferData;
360364
if (Op.CopyBuffer == nullptr)
361365
{
362366
Op.UploadEnqueued = UpdateInfo.UploadEnqueued;
@@ -456,7 +460,8 @@ bool GPUUploadManagerImpl::Page::ScheduleTextureUpdate(const ScheduleTextureUpda
456460
}
457461

458462
PendingTextureOp Op;
459-
Op.pDstTexture = UpdateInfo.pDstTexture;
463+
Op.pDstTexture = UpdateInfo.pDstTexture;
464+
Op.DstTextureTransitionMode = UpdateInfo.DstTextureTransitionMode;
460465
if (m_pStagingBuffer)
461466
{
462467
Op.CopyTexture = UpdateInfo.CopyTexture;
@@ -523,8 +528,8 @@ void GPUUploadManagerImpl::Page::ExecutePendingOps(IDeviceContext* pContext, Uin
523528
{
524529
if (pContext != nullptr && BuffOp.pDstBuffer != nullptr && BuffOp.NumBytes > 0)
525530
{
526-
pContext->CopyBuffer(m_pStagingBuffer, BuffOp.SrcOffset, RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
527-
BuffOp.pDstBuffer, BuffOp.DstOffset, BuffOp.NumBytes, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
531+
pContext->CopyBuffer(m_pStagingBuffer, BuffOp.SrcOffset, RESOURCE_STATE_TRANSITION_MODE_VERIFY,
532+
BuffOp.pDstBuffer, BuffOp.DstOffset, BuffOp.NumBytes, BuffOp.DstBufferTransitionMode);
528533
}
529534

530535
if (BuffOp.UploadEnqueued != nullptr)
@@ -558,16 +563,16 @@ void GPUUploadManagerImpl::Page::ExecutePendingOps(IDeviceContext* pContext, Uin
558563
if (m_pStagingBuffer)
559564
{
560565
pContext->UpdateTexture(TexOp.pDstTexture, TexOp.DstMipLevel, TexOp.DstSlice, TexOp.DstBox, SrcData,
561-
RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
566+
RESOURCE_STATE_TRANSITION_MODE_VERIFY, TexOp.DstTextureTransitionMode);
562567
}
563568
else if (m_pStagingAtlas)
564569
{
565570
CopyTextureAttribs CopyAttribs;
566571

567572
CopyAttribs.pSrcTexture = m_pStagingAtlas->pTex;
568573
CopyAttribs.pDstTexture = TexOp.pDstTexture;
569-
CopyAttribs.DstTextureTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
570574
CopyAttribs.SrcTextureTransitionMode = RESOURCE_STATE_TRANSITION_MODE_VERIFY;
575+
CopyAttribs.DstTextureTransitionMode = TexOp.DstTextureTransitionMode;
571576
CopyAttribs.DstMipLevel = TexOp.DstMipLevel;
572577
CopyAttribs.DstSlice = TexOp.DstSlice;
573578

@@ -619,6 +624,7 @@ void GPUUploadManagerImpl::Page::Reset(IDeviceContext* pContext)
619624
{
620625
if (m_pStagingBuffer)
621626
{
627+
pContext->TransitionResourceState({m_pStagingBuffer, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_COPY_SOURCE, STATE_TRANSITION_FLAG_UPDATE_STATE});
622628
const MAP_FLAGS MapFlags = m_PersistentMapped ?
623629
MAP_FLAG_DO_NOT_WAIT :
624630
MAP_FLAG_NONE;
@@ -721,8 +727,7 @@ GPUUploadManagerImpl::UploadStream::UploadStream(GPUUploadManagerImpl& Mgr,
721727
TEXTURE_FORMAT Format) noexcept :
722728
m_Mgr{Mgr},
723729
m_PageSize{AlignUpToPowerOfTwo(PageSize)},
724-
// Ensure that the max page count is at least 2 to allow for double buffering, unless it's set to 0 which means no limit.
725-
m_MaxPageCount{MaxPageCount != 0 ? std::max(MaxPageCount, 2u) : 0},
730+
m_MaxPageCount{MaxPageCount},
726731
m_Format{Format}
727732
{
728733
if (pContext != nullptr)
@@ -897,6 +902,7 @@ GPUUploadManagerImpl::~GPUUploadManagerImpl()
897902
if (m_pTextureStreams)
898903
{
899904
m_pTextureStreams->SetStopping();
905+
// After the stopping flag is set, no new streams can be added.
900906
m_pTextureStreams->MoveNewStreamsToManager();
901907
}
902908

0 commit comments

Comments
 (0)