Fix GPU Buffer Map/Unmap pair to prevent stall if map fails on DX11
#942
This commit is contained in:
@@ -377,12 +377,9 @@ void GPUBuffer::SetData(const void* data, uint32 size)
|
||||
Log::ArgumentOutOfRangeException(TEXT("Buffer.SetData"));
|
||||
return;
|
||||
}
|
||||
|
||||
void* mapped = Map(GPUResourceMapMode::Write);
|
||||
if (!mapped)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Platform::MemoryCopy(mapped, data, size);
|
||||
Unmap();
|
||||
}
|
||||
|
||||
@@ -190,6 +190,7 @@ public:
|
||||
/// <summary>
|
||||
/// Gets a CPU pointer to the resource by mapping its contents. Denies the GPU access to that resource.
|
||||
/// </summary>
|
||||
/// <remarks>Always call Unmap if the returned pointer is valid to release resources.</remarks>
|
||||
/// <param name="mode">The map operation mode.</param>
|
||||
/// <returns>The pointer of the mapped CPU buffer with resource data or null if failed.</returns>
|
||||
API_FUNCTION() virtual void* Map(GPUResourceMapMode mode) = 0;
|
||||
|
||||
@@ -48,18 +48,19 @@ void* GPUBufferDX11::Map(GPUResourceMapMode mode)
|
||||
const HRESULT result = _device->GetIM()->Map(_resource, 0, mapType, mapFlags, &map);
|
||||
if (result != DXGI_ERROR_WAS_STILL_DRAWING)
|
||||
LOG_DIRECTX_RESULT(result);
|
||||
|
||||
_mapped = map.pData != nullptr;
|
||||
if (!_mapped && !isMainThread)
|
||||
_device->Locker.Unlock();
|
||||
|
||||
return map.pData;
|
||||
}
|
||||
|
||||
void GPUBufferDX11::Unmap()
|
||||
{
|
||||
if (_mapped)
|
||||
{
|
||||
_mapped = false;
|
||||
_device->GetIM()->Unmap(_resource, 0);
|
||||
}
|
||||
|
||||
ASSERT(_mapped);
|
||||
_mapped = false;
|
||||
_device->GetIM()->Unmap(_resource, 0);
|
||||
if (!IsInMainThread())
|
||||
_device->Locker.Unlock();
|
||||
}
|
||||
|
||||
@@ -104,15 +104,18 @@ int32 ParticleSystemInstance::GetParticlesCount() const
|
||||
if (GPUParticlesCountReadback && GPUParticlesCountReadback->IsAllocated())
|
||||
{
|
||||
auto data = static_cast<uint32*>(GPUParticlesCountReadback->Map(GPUResourceMapMode::Read));
|
||||
for (const auto& emitter : Emitters)
|
||||
if (data)
|
||||
{
|
||||
if (emitter.Buffer && emitter.Buffer->Mode == ParticlesSimulationMode::GPU && emitter.Buffer->GPU.HasValidCount)
|
||||
for (const auto& emitter : Emitters)
|
||||
{
|
||||
result += *data;
|
||||
if (emitter.Buffer && emitter.Buffer->Mode == ParticlesSimulationMode::GPU && emitter.Buffer->GPU.HasValidCount)
|
||||
{
|
||||
result += *data;
|
||||
}
|
||||
++data;
|
||||
}
|
||||
++data;
|
||||
GPUParticlesCountReadback->Unmap();
|
||||
}
|
||||
GPUParticlesCountReadback->Unmap();
|
||||
}
|
||||
else if (Emitters.HasItems())
|
||||
{
|
||||
|
||||
@@ -689,8 +689,8 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
||||
objectsBufferCapacity = counter;
|
||||
notReady = false;
|
||||
}
|
||||
_culledObjectsSizeBuffer->Unmap();
|
||||
}
|
||||
_culledObjectsSizeBuffer->Unmap();
|
||||
|
||||
// Allow to be ready if the buffer was already used
|
||||
if (notReady && surfaceAtlasData.CulledObjectsBuffer && surfaceAtlasData.CulledObjectsBuffer->IsAllocated())
|
||||
|
||||
@@ -152,7 +152,7 @@ void ShadowsOfMordor::Builder::updateLightmaps()
|
||||
{
|
||||
auto texture = textures[textureIndex];
|
||||
GPUDevice::Instance->Locker.Unlock();
|
||||
if (!texture || texture->WaitForLoaded())
|
||||
if (texture == nullptr || texture->WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Lightmap load failed.");
|
||||
return;
|
||||
|
||||
@@ -276,6 +276,7 @@ void ShadowsOfMordor::Builder::saveState()
|
||||
context->Flush();
|
||||
Platform::Sleep(10);
|
||||
void* mapped = lightmapDataStaging->Map(GPUResourceMapMode::Read);
|
||||
ASSERT(mapped);
|
||||
stream->WriteInt32(lightmapDataSize);
|
||||
stream->WriteBytes(mapped, lightmapDataSize);
|
||||
lightmapDataStaging->Unmap();
|
||||
|
||||
Reference in New Issue
Block a user