Function map
Synopsis
#include <Source/Falcor/Core/API/Buffer.h>
void * map(MapType Type)
Description
Map the buffer.
The low-level behavior depends on MapType and the CpuAccess flags of the buffer:
- For CPU accessible buffers, the caller should ensure CPU/GPU memory accesses do not conflict.
- For GPU-only buffers, map for read will create an internal staging buffer that is safe to read.
- Mapping a CPU write buffer for WriteDiscard will cause the buffer to be internally re-allocated, causing its address range to change and invalidating all previous views to the buffer.
Source
Lines 260-324 in Source/Falcor/Core/API/Buffer.cpp. Line 263 in Source/Falcor/Core/API/Buffer.h.
void* Buffer::map(MapType type)
{
if (type == MapType::Write)
{
if (mCpuAccess != CpuAccess::Write)
{
logError("Trying to map a buffer for write, but it wasn't created with the write permissions");
return nullptr;
}
return mDynamicData.pData;
}
else if (type == MapType::WriteDiscard)
{
if (mCpuAccess != CpuAccess::Write)
{
logError("Trying to map a buffer for write, but it wasn't created with the write permissions");
return nullptr;
}
// Allocate a new buffer
if (mDynamicData.pResourceHandle)
{
gpDevice->getUploadHeap()->release(mDynamicData);
}
mpCBV = nullptr;
mDynamicData = gpDevice->getUploadHeap()->allocate(mSize, getBufferDataAlignment(this));
mApiHandle = mDynamicData.pResourceHandle;
mGpuVaOffset = mDynamicData.offset;
invalidateViews();
return mDynamicData.pData;
}
else
{
assert(type == MapType::Read);
if (mCpuAccess == CpuAccess::Write)
{
// Buffers on the upload heap are already mapped, just return the ptr.
assert(mDynamicData.pResourceHandle);
assert(mDynamicData.pData);
return mDynamicData.pData;
}
else if (mCpuAccess == CpuAccess::Read)
{
assert(mBindFlags == BindFlags::None);
return mapBufferApi(mApiHandle, mSize);
}
else
{
// For buffers without CPU access we must copy the contents to a staging buffer.
logWarning("Buffer::map() performance warning - using staging resource which require us to flush the pipeline and wait for the GPU to finish its work");
if (mpStagingResource == nullptr)
{
mpStagingResource = Buffer::create(mSize, Buffer::BindFlags::None, Buffer::CpuAccess::Read, nullptr);
}
// Copy the buffer and flush the pipeline
RenderContext* pContext = gpDevice->getRenderContext();
assert(mGpuVaOffset == 0);
pContext->copyResource(mpStagingResource.get(), this);
pContext->flush(true);
return mpStagingResource->map(MapType::Read);
}
}
}